Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
slapos.core
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Léo-Paul Géneau
slapos.core
Commits
00c3e8a5
Commit
00c3e8a5
authored
Aug 16, 2011
by
Łukasz Nowak
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into networkcache_signature
Conflicts: slapos/tests/slapgrid.py
parents
b175699c
1eddcede
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
1808 additions
and
49 deletions
+1808
-49
buildout.cfg
buildout.cfg
+6
-0
master/bt5/vifib_base/DocumentTemplateItem/SoftwareInstance.py
...r/bt5/vifib_base/DocumentTemplateItem/SoftwareInstance.py
+48
-0
master/bt5/vifib_base/WorkflowTemplateItem/portal_workflow/software_instance_slap_interface_workflow/scripts/SoftwareInstance_requestSoftwareInstance.xml
...flow/scripts/SoftwareInstance_requestSoftwareInstance.xml
+26
-1
master/bt5/vifib_base/bt/revision
master/bt5/vifib_base/bt/revision
+1
-1
master/product/Vifib/tests/testVifibSlapWebService.py
master/product/Vifib/tests/testVifibSlapWebService.py
+961
-29
slapos/grid/slapgrid.py
slapos/grid/slapgrid.py
+56
-2
slapos/tests/mock/httplib.py
slapos/tests/mock/httplib.py
+2
-5
slapos/tests/slapgrid.py
slapos/tests/slapgrid.py
+708
-11
No files found.
buildout.cfg
View file @
00c3e8a5
...
...
@@ -3,6 +3,7 @@ develop = .
parts =
slapos
pyflakes
test
find-links =
http://www.nexedi.org/static/packages/source/slapos.buildout/
...
...
@@ -44,5 +45,10 @@ eggs =
rstctl
interpreter = python
[test]
recipe = zc.recipe.testrunner
eggs =
slapos.core
[versions]
zc.buildout = 1.5.3-dev-SlapOS-005
master/bt5/vifib_base/DocumentTemplateItem/SoftwareInstance.py
View file @
00c3e8a5
...
...
@@ -29,6 +29,13 @@ from AccessControl import ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
from
Products.ERP5.Document.Item
import
Item
from
lxml
import
etree
import
collections
class
DisconnectedSoftwareTree
(
Exception
):
pass
class
CyclicSoftwareTree
(
Exception
):
pass
class
SoftwareInstance
(
Item
):
"""
...
...
@@ -60,3 +67,44 @@ class SoftwareInstance(Item):
value
=
element
.
text
result_dict
[
key
]
=
value
return
result_dict
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'checkNotCyclic'
)
def
checkNotCyclic
(
self
,
graph
):
# see http://neopythonic.blogspot.com/2009/01/detecting-cycles-in-directed-graph.html
todo
=
set
(
graph
.
keys
())
while
todo
:
node
=
todo
.
pop
()
stack
=
[
node
]
while
stack
:
top
=
stack
[
-
1
]
for
node
in
graph
[
top
]:
if
node
in
stack
:
raise
CyclicSoftwareTree
if
node
in
todo
:
stack
.
append
(
node
)
todo
.
remove
(
node
)
break
else
:
node
=
stack
.
pop
()
return
True
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'checkConnected'
)
def
checkConnected
(
self
,
graph
,
root
):
size
=
len
(
graph
)
visited
=
set
()
to_crawl
=
collections
.
deque
(
graph
[
root
])
while
to_crawl
:
current
=
to_crawl
.
popleft
()
if
current
in
visited
:
continue
visited
.
add
(
current
)
node_children
=
set
(
graph
[
current
])
to_crawl
.
extend
(
node_children
-
visited
)
# add one to visited, as root won't be visited, only children
# this is false positive in case of cyclic graphs, but they are
# anyway wrong in Software Instance trees
if
size
!=
len
(
visited
)
+
1
:
raise
DisconnectedSoftwareTree
return
True
master/bt5/vifib_base/WorkflowTemplateItem/portal_workflow/software_instance_slap_interface_workflow/scripts/SoftwareInstance_requestSoftwareInstance.xml
View file @
00c3e8a5
...
...
@@ -64,9 +64,18 @@ instance_xml = kwargs["instance_xml"]\n
sla_xml = kwargs["sla_xml"]\n
state = kwargs["state"]\n
\n
# Get root software instance\n
# graph allows to "simulate" tree change after requested operation\n
graph = {}\n
# Get root software instance and create initial graph\n
predecessor_software_instance = software_instance\n
while (predecessor_software_instance is not None):\n
predecessor_software_instance_pred_uid_list = predecessor_software_instance.getPredecessorUidList()\n
graph[predecessor_software_instance.getUid()] = predecessor_software_instance_pred_uid_list\n
# as this walking is not fetching all instances fill predecessors into graph, in order to have\n
# "nearly" complete representation\n
for uid in predecessor_software_instance_pred_uid_list:\n
if uid not in graph:\n
graph[uid] = []\n
root_software_instance = predecessor_software_instance\n
predecessor_software_instance = predecessor_software_instance.getPredecessorRelatedValue(\n
portal_type="Software Instance")\n
...
...
@@ -84,6 +93,11 @@ request_software_instance = software_instance.portal_catalog.getResultValue(\n
root_uid=root_software_instance.getUid(),\n
)\n
\n
# above query does not find root software instance, but as this case is easy\n
# to find, just check if such request does not come and raise\n
if root_software_instance.getTitle() == requested_partition_reference:\n
raise ValueError(\'It is disallowed to request root software instance\')\n
\n
if (request_software_instance is None):\n
if (portal.portal_activities.countMessageWithTag(tag) >
0):\n
# The software instance is already under creation but can not be fetched from catalog\n
...
...
@@ -130,6 +144,8 @@ else:\n
predecessor_software_instance.edit(\n
predecessor_uid_list=predecessor_uid_list,\n
activate_kw={\'tag\': tag},)\n
graph[predecessor_software_instance.getUid()] = predecessor_uid_list\n
\n
if state == \'started\':\n
request_software_instance.startRequested()\n
request_software_instance.activate(after_tag=tag).requestStartComputerPartition()\n
...
...
@@ -139,7 +155,16 @@ else:\n
else:\n
raise ValueError(\'State %r is not supported\' % state)\n
predecessor_list = software_instance.getPredecessorList() + [request_software_instance.getRelativeUrl()]\n
# Add requested software instance to graph if does not exists there yet\n
if not request_software_instance.getUid() in graph:\n
graph[request_software_instance.getUid()] = []\n
\n
# update graph to reflect requested operation\n
graph[software_instance.getUid()] = software_instance.getPredecessorUidList() + [request_software_instance.getUid()]\n
\n
# check if all elements are still connected and if there is no cycle\n
software_instance.checkConnected(graph, root_software_instance.getUid())\n
software_instance.checkNotCyclic(graph)\n
\n
software_instance.edit(\n
predecessor_list=predecessor_list,\n
...
...
master/bt5/vifib_base/bt/revision
View file @
00c3e8a5
246
\ No newline at end of file
254
\ No newline at end of file
master/product/Vifib/tests/testVifibSlapWebService.py
View file @
00c3e8a5
...
...
@@ -361,6 +361,7 @@ class TestVifibSlapWebService(testVifibMixin):
self
.
assertEqual
(
1
,
len
(
software_instance_list
))
software_instance
=
software_instance_list
[
0
]
sequence
.
edit
(
root_software_instance_title
=
software_title
,
software_instance_uid
=
software_instance
.
getUid
(),
software_instance_reference
=
software_instance
.
getReference
(),
hosting_subscription_uid
=
software_instance
.
getAggregateRelatedValue
(
...
...
@@ -1187,6 +1188,16 @@ class TestVifibSlapWebService(testVifibMixin):
def
stepSelectRequestedReferenceChildrenBChild
(
self
,
sequence
,
**
kw
):
sequence
.
edit
(
requested_reference
=
'children_b_child'
)
def
stepSelectRequestedReferenceRootSoftwareInstanceTitle
(
self
,
sequence
,
**
kw
):
sequence
.
edit
(
requested_reference
=
sequence
[
'root_software_instance_title'
])
def
stepSelectRequestedReferenceB
(
self
,
sequence
,
**
kw
):
sequence
.
edit
(
requested_reference
=
'b'
)
def
stepSelectRequestedReferenceC
(
self
,
sequence
,
**
kw
):
sequence
.
edit
(
requested_reference
=
'c'
)
def
stepSelectEmptyRequestedParameterDict
(
self
,
sequence
,
**
kw
):
sequence
.
edit
(
requested_parameter_dict
=
None
)
...
...
@@ -1355,6 +1366,7 @@ class TestVifibSlapWebService(testVifibMixin):
requested_computer_partition_reference
=
\
requested_slap_computer_partition
.
getId
())
def
stepDirectRequestComputerPartitionNotReadyResponseWithoutState
(
self
,
sequence
,
**
kw
):
request_dict
=
{
'computer_id'
:
sequence
[
'computer_reference'
]
,
...
...
@@ -3103,6 +3115,14 @@ class TestVifibSlapWebService(testVifibMixin):
def
stepCheckSoftwareInstanceAndRelatedComputerPartition
(
self
,
sequence
,
**
kw
):
self
.
stepCheckSoftwareInstanceAndRelatedComputerPartitionNoPackingListCheck
(
sequence
,
**
kw
)
software_instance_uid
=
sequence
[
'software_instance_uid'
]
software_instance
=
self
.
portal
.
portal_catalog
.
getResultValue
(
uid
=
software_instance_uid
)
self
.
_checkSoftwareInstanceAndRelatedPartition
(
software_instance
)
def
stepCheckSoftwareInstanceAndRelatedComputerPartitionNoPackingListCheck
(
self
,
sequence
,
**
kw
):
software_instance_uid
=
sequence
[
'software_instance_uid'
]
software_instance
=
self
.
portal
.
portal_catalog
.
getResultValue
(
uid
=
software_instance_uid
)
...
...
@@ -3110,7 +3130,6 @@ class TestVifibSlapWebService(testVifibMixin):
predecessor_value_list
=
software_instance
.
getPredecessorValueList
()
self
.
assertEqual
(
1
,
len
(
predecessor_value_list
))
self
.
_checkSoftwareInstanceAndRelatedPartition
(
software_instance
)
sequence
.
edit
(
requested_software_instance_uid
=
predecessor_value_list
[
0
].
getUid
(),
requested_software_instance_reference
=
predecessor_value_list
[
0
].
getReference
())
...
...
@@ -7623,12 +7642,42 @@ class TestVifibSlapWebService(testVifibMixin):
sequence_list
.
addSequenceString
(
sequence_string
)
sequence_list
.
play
(
self
)
def
stepStoreCurrentSoftwareInstanceUidBufferA
(
self
,
sequence
,
**
kw
):
sequence
[
'buffer_a_software_instance_uid'
]
=
sequence
[
'software_instance_uid'
]
def
stepStoreCurrentSoftwareInstanceUidBufferB
(
self
,
sequence
,
**
kw
):
sequence
[
'buffer_b_software_instance_uid'
]
=
sequence
[
'software_instance_uid'
]
def
stepStoreCurrentComputerUidBufferA
(
self
,
sequence
,
**
kw
):
sequence
[
'buffer_a_computer_uid'
]
=
sequence
[
'computer_uid'
]
def
stepStoreCurrentComputerUidBufferB
(
self
,
sequence
,
**
kw
):
sequence
[
'buffer_b_computer_uid'
]
=
sequence
[
'computer_uid'
]
def
stepRestoreSoftwareInstanceUidFromBufferA
(
self
,
sequence
,
**
kw
):
sequence
[
'software_instance_uid'
]
=
sequence
[
'buffer_a_software_instance_uid'
]
def
stepRestoreSoftwareInstanceUidFromBufferB
(
self
,
sequence
,
**
kw
):
sequence
[
'software_instance_uid'
]
=
sequence
[
'buffer_b_software_instance_uid'
]
def
stepRestoreComputerUidFromBufferA
(
self
,
sequence
,
**
kw
):
sequence
[
'computer_uid'
]
=
sequence
[
'buffer_a_computer_uid'
]
def
stepRestoreComputerUidFromBufferB
(
self
,
sequence
,
**
kw
):
sequence
[
'computer_uid'
]
=
sequence
[
'buffer_b_computer_uid'
]
def
stepStoreCurrentComputerReferenceBufferA
(
self
,
sequence
,
**
kw
):
sequence
[
'buffer_a_computer_reference'
]
=
sequence
[
'computer_reference'
]
def
stepStoreCurrentComputerReferenceBufferB
(
self
,
sequence
,
**
kw
):
sequence
[
'buffer_b_computer_reference'
]
=
sequence
[
'computer_reference'
]
def
stepStoreCurrentComputerPartitionUidBufferA
(
self
,
sequence
,
**
kw
):
sequence
[
'buffer_a_computer_partition_uid'
]
=
sequence
[
'computer_partition_uid'
]
def
stepStoreCurrentComputerPartitionUidBufferB
(
self
,
sequence
,
**
kw
):
sequence
[
'buffer_b_computer_partition_uid'
]
=
sequence
[
'computer_partition_uid'
]
def
stepStoreCurrentComputerPartitionReferenceBufferA
(
self
,
sequence
,
**
kw
):
sequence
[
'buffer_a_computer_partition_reference'
]
=
sequence
[
'computer_partition_reference'
]
...
...
@@ -7641,6 +7690,12 @@ class TestVifibSlapWebService(testVifibMixin):
def
stepRestoreComputerReferenceFromBufferB
(
self
,
sequence
,
**
kw
):
sequence
[
'computer_reference'
]
=
sequence
[
'buffer_b_computer_reference'
]
def
stepRestoreComputerPartitionUidFromBufferA
(
self
,
sequence
,
**
kw
):
sequence
[
'computer_partition_uid'
]
=
sequence
[
'buffer_a_computer_partition_uid'
]
def
stepRestoreComputerPartitionUidFromBufferB
(
self
,
sequence
,
**
kw
):
sequence
[
'computer_partition_uid'
]
=
sequence
[
'buffer_b_computer_partition_uid'
]
def
stepRestoreComputerPartitionReferenceFromBufferA
(
self
,
sequence
,
**
kw
):
sequence
[
'computer_partition_reference'
]
=
sequence
[
'buffer_a_computer_partition_reference'
]
...
...
@@ -7652,31 +7707,149 @@ class TestVifibSlapWebService(testVifibMixin):
If software instance originated on computer comes from another computer it
shall be possible to sucesfully destroy it.
Test is done in a way to trigger unstable Assignor role calculation
on Hosting Subscription which leads to unavailability of Software Instances
from one computer to another.
"""
sequence_list
=
SequenceList
()
sequence_string
=
self
.
prepare_install_requested_computer_partition_sequence_string
+
\
"""
sequence_string
=
"""
# Prepare software release shared by both Computers
LoginTestVifibDeveloper
SelectNewSoftwareReleaseUri
CreateSoftwareRelease
Tic
SubmitSoftwareRelease
Tic
CreateSoftwareProduct
Tic
ValidateSoftwareProduct
Tic
SetSoftwareProductToSoftwareRelease
PublishByActionSoftwareRelease
Logout
# Create first computer
LoginTestVifibAdmin
CreateComputer
Tic
Logout
SlapLoginCurrentComputer
FormatComputer
Tic
SlapLogout
StoreCurrentComputerReferenceBufferA
StoreCurrentComputerUidBufferA
# Install software on first computer
LoginTestVifibAdmin
RequestSoftwareInstallation
Tic
Logout
SlapLoginCurrentComputer
ComputerSoftwareReleaseAvailable
Tic
SlapLogout
# Now request and instantiate this software release on first computer
LoginTestVifibCustomer
PersonRequestSoftwareInstance
Tic
Logout
LoginDefaultUser
ConfirmOrderedSaleOrderActiveSense
Tic
SetSelectedComputerPartition
SelectCurrentlyUsedSalePackingListUid
Logout
StoreCurrentComputerPartitionReferenceBufferA
"""
+
\
self
.
prepare_formated_computer
+
\
"""
StoreCurrentComputerPartitionUidBufferA
StoreCurrentSoftwareInstanceUidBufferA
LoginDefaultUser
CheckComputerPartitionInstanceSetupSalePackingListConfirmed
Logout
# Start it..
SlapLoginCurrentComputer
SoftwareInstanceAvailable
Tic
SlapLogout
LoginDefaultUser
SetSelectedComputerPartition
CheckComputerPartitionInstanceSetupSalePackingListStopped
CheckComputerPartitionInstanceHostingSalePackingListConfirmed
Logout
SlapLoginCurrentComputer
SoftwareInstanceStarted
Tic
SlapLogout
LoginDefaultUser
CheckComputerPartitionInstanceHostingSalePackingListStarted
Logout
# ...stop it...
LoginDefaultUser
RequestSoftwareInstanceStop
Tic
Logout
LoginDefaultUser
CheckComputerPartitionInstanceHostingSalePackingListStopped
Logout
SlapLoginCurrentComputer
SoftwareInstanceStopped
Tic
SlapLogout
LoginDefaultUser
CheckComputerPartitionInstanceHostingSalePackingListDelivered
Logout
# ...and request destruction
LoginDefaultUser
RequestSoftwareInstanceDestroy
Tic
Logout
LoginDefaultUser
CheckComputerPartitionInstanceCleanupSalePackingListConfirmed
Logout
# Now prepare second computer
LoginTestVifibAdmin
CreateComputer
Tic
Logout
SlapLoginCurrentComputer
FormatComputer
Tic
SlapLogout
StoreCurrentComputerReferenceBufferB
StoreCurrentComputer
PartitionReference
BufferB
StoreCurrentComputer
Uid
BufferB
LoginTestVifibAdmin
RequestSoftwareInstallation
Tic
Logout
SlapLoginCurrentComputer
ComputerSoftwareReleaseAvailable
Tic
SlapLogout
StoreCurrentComputerReferenceBufferB
StoreCurrentComputerUidBufferB
# Now request self software release from one computer to another
RestoreComputerReferenceFromBufferA
RestoreComputer
PartitionReference
FromBufferA
RestoreComputer
Uid
FromBufferA
RestoreSoftwareInstanceUidFromBufferA
SlapLoginCurrentSoftwareInstance
RequestComputerPartitionNotReadyResponse
Tic
...
...
@@ -7688,55 +7861,72 @@ class TestVifibSlapWebService(testVifibMixin):
SlapLogout
LoginDefaultUser
CheckSoftwareInstanceAndRelatedComputerPartition
CheckSoftwareInstanceAndRelatedComputerPartition
NoPackingListCheck
CheckRequestedSoftwareInstanceAndRelatedComputerPartition
Logout
SlapLoginCurrentSoftwareInstance
CheckRequestedComputerPartitionCleanParameterList
Logout
LoginDefaultUser
SetCurrentSoftwareInstanceRequested
SetSelectedComputerPartition
SelectCurrentlyUsedSalePackingListUid
Logout
SlapLoginCurrentSoftwareInstance
CheckRequestedComputerPartitionCleanParameterList
Logout
StoreCurrentComputerPartitionReferenceBufferB
StoreCurrentComputerPartitionUidBufferB
StoreCurrentSoftwareInstanceUidBufferB
RestoreComputerReferenceFromBufferB
RestoreComputerPartitionReferenceFromBufferB
RestoreComputerUidFromBufferB
# Start the requested software instance...
SlapLoginCurrentComputer
SoftwareInstance
Building
SoftwareInstance
Available
Tic
SlapLogout
LoginDefaultUser
CheckComputerPartitionInstanceSetupSalePackingListStarted
SetSelectedComputerPartition
CheckComputerPartitionInstanceSetupSalePackingListStopped
CheckComputerPartitionInstanceHostingSalePackingListConfirmed
Logout
SlapLoginCurrentComputer
SoftwareInstance
Available
SoftwareInstance
Started
Tic
SlapLogout
LoginDefaultUser
CheckComputerPartitionInstanceSetupSalePackingListStopped
CheckComputerPartitionInstanceHostingSalePackingListConfirmed
CheckComputerPartitionInstanceHostingSalePackingListStarted
Logout
# ...and stop it
LoginDefaultUser
RequestSoftwareInstanceStop
Tic
Logout
LoginDefaultUser
CheckComputerPartitionInstanceHostingSalePackingListStopped
Logout
SlapLoginCurrentComputer
SoftwareInstanceSt
art
ed
SoftwareInstanceSt
opp
ed
Tic
SlapLogout
LoginDefaultUser
CheckComputerPartitionInstanceHostingSalePackingListStarted
SetCurrentSoftwareInstanceRequester
SetSelectedComputerPartition
SelectCurrentlyUsedSalePackingListUid
CheckComputerPartitionInstanceHostingSalePackingListDelivered
Logout
LoginTestVifibCustomer
# Now request destruction of second software instance...
LoginDefaultUser
RequestSoftwareInstanceDestroy
Tic
Logout
...
...
@@ -7745,8 +7935,24 @@ class TestVifibSlapWebService(testVifibMixin):
CheckComputerPartitionInstanceCleanupSalePackingListConfirmed
Logout
RestoreComputerReferenceFromBufferA
# ...and destroy it
SlapLoginCurrentComputer
SoftwareInstanceDestroyed
Tic
SlapLogout
LoginDefaultUser
CheckComputerPartitionInstanceCleanupSalePackingListDelivered
CheckComputerPartitionIsFree
Logout
# Time to switch back to first software instance and destroy it
RestoreComputerPartitionReferenceFromBufferA
RestoreComputerPartitionUidFromBufferA
RestoreSoftwareInstanceUidFromBufferA
RestoreComputerReferenceFromBufferA
RestoreComputerUidFromBufferA
SlapLoginCurrentComputer
SoftwareInstanceDestroyed
...
...
@@ -7760,15 +7966,741 @@ class TestVifibSlapWebService(testVifibMixin):
"""
sequence_list
.
addSequenceString
(
sequence_string
)
sequence_list
.
play
(
self
)
def
test_bug_hosting_subscription_assignor_role_instability
(
self
):
"""Show instability issue of Assignor role on Hosting Subscription
Related to fact when Hosting Subscription is associated to
Software Instances deployed on many computers"""
raise
NotImplementedError
def
test_bug_destruction_with_unfinished_packing_list
(
self
):
"""Proves that even if some packing lists are not fully delivered
it is possible to destroy software instance"""
sequence_list
=
SequenceList
()
sequence_string
=
"""
# Prepare software release
LoginTestVifibDeveloper
SelectNewSoftwareReleaseUri
CreateSoftwareRelease
Tic
SubmitSoftwareRelease
Tic
CreateSoftwareProduct
Tic
ValidateSoftwareProduct
Tic
SetSoftwareProductToSoftwareRelease
PublishByActionSoftwareRelease
Logout
# Create first computer
LoginTestVifibAdmin
CreateComputer
Tic
Logout
SlapLoginCurrentComputer
FormatComputer
Tic
SlapLogout
StoreCurrentComputerReferenceBufferA
StoreCurrentComputerUidBufferA
# Install software on first computer
LoginTestVifibAdmin
RequestSoftwareInstallation
Tic
Logout
SlapLoginCurrentComputer
ComputerSoftwareReleaseAvailable
Tic
SlapLogout
# Now request and instantiate this software release on first computer
LoginTestVifibCustomer
PersonRequestSoftwareInstance
Tic
Logout
LoginDefaultUser
ConfirmOrderedSaleOrderActiveSense
Tic
SetSelectedComputerPartition
SelectCurrentlyUsedSalePackingListUid
Logout
LoginDefaultUser
CheckComputerPartitionInstanceSetupSalePackingListConfirmed
Logout
# Request destruction...
LoginDefaultUser
RequestSoftwareInstanceDestroy
Tic
Logout
LoginDefaultUser
CheckComputerPartitionInstanceCleanupSalePackingListConfirmed
Logout
# ...and destroy it
SlapLoginCurrentComputer
SoftwareInstanceDestroyed
Tic
SlapLogout
LoginDefaultUser
CheckComputerPartitionInstanceCleanupSalePackingListDelivered
CheckComputerPartitionIsFree
Logout
"""
sequence_list
.
addSequenceString
(
sequence_string
)
sequence_list
.
play
(
self
)
def
stepDirectRequestComputerPartitionRaisesDisconnectedSoftwareTree
(
self
,
sequence
,
**
kw
):
software_instance
=
self
.
portal
.
portal_catalog
.
getResultValue
(
uid
=
sequence
[
'software_instance_uid'
])
from
erp5.document.SoftwareInstance
import
DisconnectedSoftwareTree
self
.
assertRaises
(
DisconnectedSoftwareTree
,
software_instance
.
requestSoftwareInstance
,
software_release
=
sequence
[
'software_release_uri'
],
software_type
=
sequence
[
'requested_reference'
],
partition_reference
=
sequence
[
'requested_reference'
],
shared
=
False
,
instance_xml
=
self
.
minimal_correct_xml
,
sla_xml
=
self
.
minimal_correct_xml
,
state
=
'started'
)
def
test_bug_orhpaned_software_instance
(
self
):
"""Check that no orphaned Software Instances would be created
In below scenario system shall behave like mentioned:
OpenOrder.request(SR, A) | SR(A)
A.request(SR, B) | SR(A) <- SR(B)
B.request(SR, C) | SR(A) <- SR(B) <- SR(C)
C.request(SR, B) raises immediately, because the result would be:
SR(A)
SR(B) <- SR(C)
do B would become root of orphaned tree.
"""
# Setup sufficient amount of CP
self
.
computer_partition_amount
=
3
sequence_list
=
SequenceList
()
sequence_string
=
"""
# Prepare software release
LoginTestVifibDeveloper
SelectNewSoftwareReleaseUri
CreateSoftwareRelease
Tic
SubmitSoftwareRelease
Tic
CreateSoftwareProduct
Tic
ValidateSoftwareProduct
Tic
SetSoftwareProductToSoftwareRelease
PublishByActionSoftwareRelease
Logout
# Create the computer
LoginTestVifibAdmin
CreateComputer
Tic
Logout
SlapLoginCurrentComputer
FormatComputer
Tic
SlapLogout
StoreCurrentComputerReferenceBufferA
StoreCurrentComputerUidBufferA
# Install the software release
LoginTestVifibAdmin
RequestSoftwareInstallation
Tic
Logout
SlapLoginCurrentComputer
ComputerSoftwareReleaseAvailable
Tic
SlapLogout
# Create Software Instance A (originates from Open Order)
LoginTestVifibCustomer
PersonRequestSoftwareInstance
Tic
Logout
LoginDefaultUser
ConfirmOrderedSaleOrderActiveSense
Tic
SetSelectedComputerPartition
SelectCurrentlyUsedSalePackingListUid
Logout
LoginDefaultUser
CheckComputerPartitionInstanceSetupSalePackingListConfirmed
Logout
# From root request B
SelectRequestedReferenceB
SlapLoginCurrentSoftwareInstance
RequestComputerPartitionNotReadyResponse
Tic
SlapLogout
SlapLoginCurrentSoftwareInstance
RequestComputerPartition
Tic
SlapLogout
LoginDefaultUser
CheckSoftwareInstanceAndRelatedComputerPartitionNoPackingListCheck
CheckRequestedSoftwareInstanceAndRelatedComputerPartition
Logout
LoginDefaultUser
SetCurrentSoftwareInstanceRequested
SetSelectedComputerPartition
SelectCurrentlyUsedSalePackingListUid
Logout
SlapLoginCurrentSoftwareInstance
CheckRequestedComputerPartitionCleanParameterList
Logout
# From B request C
SelectRequestedReferenceC
SlapLoginCurrentSoftwareInstance
RequestComputerPartitionNotReadyResponse
Tic
SlapLogout
SlapLoginCurrentSoftwareInstance
RequestComputerPartition
Tic
SlapLogout
LoginDefaultUser
CheckSoftwareInstanceAndRelatedComputerPartitionNoPackingListCheck
CheckRequestedSoftwareInstanceAndRelatedComputerPartition
Logout
LoginDefaultUser
SetCurrentSoftwareInstanceRequested
SetSelectedComputerPartition
SelectCurrentlyUsedSalePackingListUid
Logout
SlapLoginCurrentSoftwareInstance
CheckRequestedComputerPartitionCleanParameterList
Logout
# Try to: from C request B and prove that it raises
SelectRequestedReferenceB
LoginDefaultUser # login as superuser in order to work in erp5
DirectRequestComputerPartitionRaisesDisconnectedSoftwareTree
"""
sequence_list
.
addSequenceString
(
sequence_string
)
sequence_list
.
play
(
self
)
def
stepDirectRequestComputerPartitionRaisesCyclicSoftwareTree
(
self
,
sequence
,
**
kw
):
software_instance
=
self
.
portal
.
portal_catalog
.
getResultValue
(
uid
=
sequence
[
'software_instance_uid'
])
from
erp5.document.SoftwareInstance
import
CyclicSoftwareTree
self
.
assertRaises
(
CyclicSoftwareTree
,
software_instance
.
requestSoftwareInstance
,
software_release
=
sequence
[
'software_release_uri'
],
software_type
=
sequence
[
'requested_reference'
],
partition_reference
=
sequence
[
'requested_reference'
],
shared
=
False
,
instance_xml
=
self
.
minimal_correct_xml
,
sla_xml
=
self
.
minimal_correct_xml
,
state
=
'started'
)
def
test_bug_cyclic_software_instance
(
self
):
"""Check that no cyclic Software Instance trees would be created
In below scenario system shall behave like mentioned:
OpenOrder.request(SR, A) | SR(A)
A.request(SR, B) | SR(A) <- SR(B)
B.request(SR, A) | SR(A) <- SR(B) <- SR(C)
C.request(SR, B) raises immediately, because the result would be:
SR(A)
SR(B) <-> SR(C)
so B and C would be cyclic
"""
# Setup sufficient amount of CP
self
.
computer_partition_amount
=
3
sequence_list
=
SequenceList
()
sequence_string
=
"""
# Prepare software release
LoginTestVifibDeveloper
SelectNewSoftwareReleaseUri
CreateSoftwareRelease
Tic
SubmitSoftwareRelease
Tic
CreateSoftwareProduct
Tic
ValidateSoftwareProduct
Tic
SetSoftwareProductToSoftwareRelease
PublishByActionSoftwareRelease
Logout
# Create the computer
LoginTestVifibAdmin
CreateComputer
Tic
Logout
SlapLoginCurrentComputer
FormatComputer
Tic
SlapLogout
StoreCurrentComputerReferenceBufferA
StoreCurrentComputerUidBufferA
# Install the software release
LoginTestVifibAdmin
RequestSoftwareInstallation
Tic
Logout
SlapLoginCurrentComputer
ComputerSoftwareReleaseAvailable
Tic
SlapLogout
# Create Software Instance A (originates from Open Order)
LoginTestVifibCustomer
PersonRequestSoftwareInstance
Tic
Logout
LoginDefaultUser
ConfirmOrderedSaleOrderActiveSense
Tic
SetSelectedComputerPartition
SelectCurrentlyUsedSalePackingListUid
Logout
LoginDefaultUser
CheckComputerPartitionInstanceSetupSalePackingListConfirmed
Logout
# From root request B
SelectRequestedReferenceB
SlapLoginCurrentSoftwareInstance
RequestComputerPartitionNotReadyResponse
Tic
SlapLogout
SlapLoginCurrentSoftwareInstance
RequestComputerPartition
Tic
SlapLogout
LoginDefaultUser
CheckSoftwareInstanceAndRelatedComputerPartitionNoPackingListCheck
CheckRequestedSoftwareInstanceAndRelatedComputerPartition
Logout
LoginDefaultUser
SetCurrentSoftwareInstanceRequested
SetSelectedComputerPartition
SelectCurrentlyUsedSalePackingListUid
Logout
SlapLoginCurrentSoftwareInstance
CheckRequestedComputerPartitionCleanParameterList
Logout
# From B request C
SelectRequestedReferenceC
SlapLoginCurrentSoftwareInstance
RequestComputerPartitionNotReadyResponse
Tic
SlapLogout
SlapLoginCurrentSoftwareInstance
RequestComputerPartition
Tic
SlapLogout
LoginDefaultUser
CheckSoftwareInstanceAndRelatedComputerPartitionNoPackingListCheck
CheckRequestedSoftwareInstanceAndRelatedComputerPartition
Logout
LoginDefaultUser
SetCurrentSoftwareInstanceRequested
SetSelectedComputerPartition
SelectCurrentlyUsedSalePackingListUid
Logout
SlapLoginCurrentSoftwareInstance
CheckRequestedComputerPartitionCleanParameterList
Logout
# Try to: from C request B and prove that it raises
SelectRequestedReferenceB
LoginDefaultUser # login as superuser in order to work in erp5
DirectRequestComputerPartitionRaisesCyclicSoftwareTree
"""
sequence_list
.
addSequenceString
(
sequence_string
)
sequence_list
.
play
(
self
)
def
stepDirectRequestComputerPartitionRaisesValueError
(
self
,
sequence
,
**
kw
):
software_instance
=
self
.
portal
.
portal_catalog
.
getResultValue
(
uid
=
sequence
[
'software_instance_uid'
])
self
.
assertRaises
(
ValueError
,
software_instance
.
requestSoftwareInstance
,
software_release
=
sequence
[
'software_release_uri'
],
software_type
=
sequence
[
'requested_reference'
],
partition_reference
=
sequence
[
'requested_reference'
],
shared
=
False
,
instance_xml
=
self
.
minimal_correct_xml
,
sla_xml
=
self
.
minimal_correct_xml
,
state
=
'started'
)
def
test_bug_cyclic_software_instance_small_tree
(
self
):
"""Check that no cyclic Software Instance trees would be created
In below scenario system shall behave like mentioned:
OpenOrder.request(SR, A) | SR(A)
A.request(SR, B) | SR(A) <- SR(B)
B.request(SR, A) raises immediately, because the result would be:
SR(A) <-> SR(B)
so B and A would be cyclic
"""
# Setup sufficient amount of CP
self
.
computer_partition_amount
=
2
sequence_list
=
SequenceList
()
sequence_string
=
"""
# Prepare software release
LoginTestVifibDeveloper
SelectNewSoftwareReleaseUri
CreateSoftwareRelease
Tic
SubmitSoftwareRelease
Tic
CreateSoftwareProduct
Tic
ValidateSoftwareProduct
Tic
SetSoftwareProductToSoftwareRelease
PublishByActionSoftwareRelease
Logout
# Create the computer
LoginTestVifibAdmin
CreateComputer
Tic
Logout
SlapLoginCurrentComputer
FormatComputer
Tic
SlapLogout
StoreCurrentComputerReferenceBufferA
StoreCurrentComputerUidBufferA
# Install the software release
LoginTestVifibAdmin
RequestSoftwareInstallation
Tic
Logout
SlapLoginCurrentComputer
ComputerSoftwareReleaseAvailable
Tic
SlapLogout
# Create Software Instance A (originates from Open Order)
LoginTestVifibCustomer
PersonRequestSoftwareInstance
Tic
Logout
LoginDefaultUser
ConfirmOrderedSaleOrderActiveSense
Tic
SetSelectedComputerPartition
SelectCurrentlyUsedSalePackingListUid
Logout
LoginDefaultUser
CheckComputerPartitionInstanceSetupSalePackingListConfirmed
Logout
# From root request B
SelectRequestedReferenceB
SlapLoginCurrentSoftwareInstance
RequestComputerPartitionNotReadyResponse
Tic
SlapLogout
SlapLoginCurrentSoftwareInstance
RequestComputerPartition
Tic
SlapLogout
LoginDefaultUser
CheckSoftwareInstanceAndRelatedComputerPartitionNoPackingListCheck
CheckRequestedSoftwareInstanceAndRelatedComputerPartition
Logout
LoginDefaultUser
SetCurrentSoftwareInstanceRequested
SetSelectedComputerPartition
SelectCurrentlyUsedSalePackingListUid
Logout
SlapLoginCurrentSoftwareInstance
CheckRequestedComputerPartitionCleanParameterList
Logout
# Try to: From B request root
SelectRequestedReferenceRootSoftwareInstanceTitle
LoginDefaultUser # login as superuser in order to work in erp5
DirectRequestComputerPartitionRaisesValueError
"""
sequence_list
.
addSequenceString
(
sequence_string
)
sequence_list
.
play
(
self
)
########################################
# Software Instance graph helpers
########################################
def
_test_si_tree
(
self
):
software_instance
=
self
.
portal
.
software_instance_module
.
newContent
(
portal_type
=
'Software Instance'
)
self
.
checkConnected
=
software_instance
.
checkConnected
self
.
checkNotCyclic
=
software_instance
.
checkNotCyclic
def
test_si_tree_simple_connected
(
self
):
"""Graph of one element is connected
A
"""
self
.
_test_si_tree
()
graph
=
{
'A'
:
[]}
root
=
'A'
self
.
assertEqual
(
True
,
self
.
checkConnected
(
graph
,
root
))
def
test_si_tree_simple_list_connected
(
self
):
"""Graph of list is connected
B->C->A
"""
self
.
_test_si_tree
()
graph
=
{
'A'
:
[],
'B'
:
[
'C'
],
'C'
:
[
'A'
]}
root
=
'B'
self
.
assertEqual
(
True
,
self
.
checkConnected
(
graph
,
root
))
def
test_si_tree_complex_connected
(
self
):
"""Tree is connected
B --> A
\
-> C --> D
\
-> E --> F
"""
self
.
_test_si_tree
()
graph
=
{
'A'
:
[],
'B'
:
[
'A'
,
'C'
],
'C'
:
[
'D'
,
'E'
],
'D'
:
[],
'E'
:
[
'F'
],
'F'
:
[],
}
root
=
'B'
self
.
assertEqual
(
True
,
self
.
checkConnected
(
graph
,
root
))
def
test_si_tree_simple_list_disconnected
(
self
):
"""Two lists are disconnected
A->B
C
"""
self
.
_test_si_tree
()
graph
=
{
'A'
:
[
'B'
],
'B'
:
[],
'C'
:
[]}
root
=
'A'
from
erp5.document.SoftwareInstance
import
DisconnectedSoftwareTree
self
.
assertRaises
(
DisconnectedSoftwareTree
,
self
.
checkConnected
,
graph
,
root
)
# For now limitation of implementation gives false positive
@
expectedFailure
def
test_si_tree_cyclic_connected
(
self
):
"""Cyclic is connected
A<->B
"""
self
.
_test_si_tree
()
graph
=
{
'A'
:
[
'B'
],
'B'
:
[
'A'
]}
root
=
'B'
self
.
assertEqual
(
True
,
self
.
checkConnected
(
graph
,
root
))
def
test_si_tree_cyclic_disconnected
(
self
):
"""Two trees, where one is cyclic are disconnected
B --> A
\
-> H
C --> D --> G
^
\
-> E --> F
\
\
------------/
"""
self
.
_test_si_tree
()
graph
=
{
'A'
:
[],
'B'
:
[
'A'
,
'H'
],
'C'
:
[
'D'
,
'E'
],
'D'
:
[
'G'
],
'E'
:
[
'F'
],
'F'
:
[
'C'
],
'G'
:
[],
'H'
:
[],
}
root
=
'B'
from
erp5.document.SoftwareInstance
import
DisconnectedSoftwareTree
self
.
assertRaises
(
DisconnectedSoftwareTree
,
self
.
checkConnected
,
graph
,
root
)
def
test_si_tree_simple_not_cyclic
(
self
):
"""Graph of one element is not cyclic
A
"""
self
.
_test_si_tree
()
graph
=
{
'A'
:
[]}
self
.
assertEqual
(
True
,
self
.
checkNotCyclic
(
graph
))
def
test_si_tree_simple_list_not_cyclic
(
self
):
"""Graph of list is not cyclic
B->C->A
"""
self
.
_test_si_tree
()
graph
=
{
'A'
:
[],
'B'
:
[
'C'
],
'C'
:
[
'A'
]}
self
.
assertEqual
(
True
,
self
.
checkNotCyclic
(
graph
))
def
test_si_tree_simple_list_cyclic
(
self
):
"""Graph of cyclic list is cyclic
B->C->A-
\
^-------/
"""
self
.
_test_si_tree
()
graph
=
{
'A'
:
[
'B'
],
'B'
:
[
'C'
],
'C'
:
[
'A'
]}
from
erp5.document.SoftwareInstance
import
CyclicSoftwareTree
self
.
assertRaises
(
CyclicSoftwareTree
,
self
.
checkNotCyclic
,
graph
)
def
test_si_tree_simple_list_cyclic_non_root
(
self
):
"""Graph of cyclic list is cyclic
B->C->D->A-
\
^-------/
"""
self
.
_test_si_tree
()
graph
=
{
'A'
:
[
'C'
],
'B'
:
[
'C'
],
'C'
:
[
'D'
],
'D'
:
[
'A'
]}
from
erp5.document.SoftwareInstance
import
CyclicSoftwareTree
self
.
assertRaises
(
CyclicSoftwareTree
,
self
.
checkNotCyclic
,
graph
)
def
test_si_tree_complex_not_cyclic
(
self
):
"""Tree is not cyclic
B --> A
\
-> C --> D
\
-> E --> F
"""
self
.
_test_si_tree
()
graph
=
{
'A'
:
[],
'B'
:
[
'A'
,
'C'
],
'C'
:
[
'D'
,
'E'
],
'D'
:
[],
'E'
:
[
'F'
],
'F'
:
[],
}
self
.
assertEqual
(
True
,
self
.
checkNotCyclic
(
graph
))
def
test_si_tree_complex_cyclic
(
self
):
"""Tree is not cyclic
B --> A
\
-> C --> D
^
\
-> E --> F -
\
\
-------------/
"""
self
.
_test_si_tree
()
graph
=
{
'A'
:
[],
'B'
:
[
'A'
,
'C'
],
'C'
:
[
'D'
,
'E'
],
'D'
:
[],
'E'
:
[
'F'
],
'F'
:
[
'C'
],
}
from
erp5.document.SoftwareInstance
import
CyclicSoftwareTree
self
.
assertRaises
(
CyclicSoftwareTree
,
self
.
checkNotCyclic
,
graph
)
def
test_si_tree_simple_list_disconnected_not_cyclic
(
self
):
"""Two lists are disconnected
A->B
C
"""
self
.
_test_si_tree
()
graph
=
{
'A'
:
[
'B'
],
'B'
:
[],
'C'
:
[]}
self
.
assertEqual
(
True
,
self
.
checkNotCyclic
(
graph
))
def
test_si_tree_cyclic
(
self
):
"""Cyclic is connected
A<->B
"""
self
.
_test_si_tree
()
graph
=
{
'A'
:
[
'B'
],
'B'
:
[
'A'
]}
from
erp5.document.SoftwareInstance
import
CyclicSoftwareTree
self
.
assertRaises
(
CyclicSoftwareTree
,
self
.
checkNotCyclic
,
graph
)
def
test_si_tree_cyclic_disconnected_cyclic
(
self
):
"""Two trees, where one is cyclic are disconnected
B --> A
\
-> H
C --> D --> G
^
\
-> E --> F
\
\
------------/
"""
self
.
_test_si_tree
()
graph
=
{
'A'
:
[],
'B'
:
[
'A'
,
'H'
],
'C'
:
[
'D'
,
'E'
],
'D'
:
[
'G'
],
'E'
:
[
'F'
],
'F'
:
[
'C'
],
'G'
:
[],
'H'
:
[
'A'
],
}
from
erp5.document.SoftwareInstance
import
CyclicSoftwareTree
self
.
assertRaises
(
CyclicSoftwareTree
,
self
.
checkNotCyclic
,
graph
)
########################################
# Other tests
########################################
def
stepRequestCredentialFromWebSite
(
self
,
sequence
,
**
kw
):
sequence
[
'web_user'
]
=
'%s.%s'
%
(
self
.
id
(),
random
())
result
=
self
.
portal
.
ERP5Site_newCredentialRequest
(
\
self
.
portal
.
ERP5Site_newCredentialRequest
(
\
first_name
=
'Homer'
,
last_name
=
'Simpson'
,
reference
=
sequence
[
'web_user'
],
...
...
slapos/grid/slapgrid.py
View file @
00c3e8a5
...
...
@@ -35,6 +35,7 @@ if sys.version_info < (2, 6):
import
socket
import
subprocess
import
traceback
import
time
#from time import strftime
from
SlapObject
import
Software
,
Partition
,
WrongPermissionError
,
\
...
...
@@ -106,6 +107,9 @@ def parseArgumentTupleAndReturnSlapgridObject(*argument_tuple):
help
=
"Enables console output and live output from subcommands."
)
parser
.
add_argument
(
"-v"
,
"--verbose"
,
action
=
"store_true"
,
default
=
False
,
help
=
"Be verbose."
)
parser
.
add_argument
(
"--promise-timeout"
,
type
=
int
,
default
=
3
,
help
=
"Promise timeout in seconds."
)
parser
.
add_argument
(
"configuration_file"
,
nargs
=
1
,
type
=
argparse
.
FileType
(),
help
=
"SlapOS configuration file."
)
...
...
@@ -210,7 +214,8 @@ def parseArgumentTupleAndReturnSlapgridObject(*argument_tuple):
upload_cache_url
=
option_dict
.
get
(
'upload-cache-url'
,
None
),
upload_dir_url
=
option_dict
.
get
(
'upload-dir-url'
,
None
),
console
=
option_dict
[
'console'
],
buildout
=
option_dict
.
get
(
'buildout'
)),
buildout
=
option_dict
.
get
(
'buildout'
),
promise_timeout
=
option_dict
[
'promise_timeout'
]),
option_dict
])
...
...
@@ -282,7 +287,8 @@ class Slapgrid(object):
upload_dir_url
=
None
,
master_ca_file
=
None
,
certificate_repository_path
=
None
,
console
=
False
):
console
=
False
,
promise_timeout
=
3
):
"""Makes easy initialisation of class parameters"""
# Parses arguments
self
.
software_root
=
os
.
path
.
abspath
(
software_root
)
...
...
@@ -312,6 +318,7 @@ class Slapgrid(object):
os
.
path
.
join
(
self
.
instance_etc_directory
,
'supervisord.conf.d'
)
self
.
console
=
console
self
.
buildout
=
buildout
self
.
promise_timeout
=
promise_timeout
def
checkEnvironmentAndCreateStructure
(
self
):
"""Checks for software_root and instance_root existence, then creates
...
...
@@ -473,6 +480,53 @@ class Slapgrid(object):
exception
=
traceback
.
format_exc
()
logger
.
error
(
exception
)
computer_partition
.
error
(
exception
)
# Promises
instance_path
=
os
.
path
.
join
(
self
.
instance_root
,
computer_partition
.
getId
())
uid
,
gid
=
None
,
None
stat_info
=
os
.
stat
(
instance_path
)
#stat sys call to get statistics informations
uid
=
stat_info
.
st_uid
gid
=
stat_info
.
st_gid
# Get the list of promises
promise_dir
=
os
.
path
.
join
(
instance_path
,
'etc'
,
'promise'
)
if
os
.
path
.
exists
(
promise_dir
)
and
os
.
path
.
isdir
(
promise_dir
):
cwd
=
instance_path
promises_list
=
os
.
listdir
(
promise_dir
)
# Check whether every promise is kept
for
promise
in
promises_list
:
command
=
os
.
path
.
join
(
promise_dir
,
promise
)
kw
=
dict
()
if
not
self
.
console
:
kw
.
update
(
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
)
process_handler
=
SlapPopen
(
command
,
preexec_fn
=
lambda
:
dropPrivileges
(
uid
,
gid
),
cwd
=
cwd
,
env
=
None
,
**
kw
)
time
.
sleep
(
self
.
promise_timeout
)
promise
=
os
.
path
.
basename
(
command
)
if
process_handler
.
poll
()
is
None
:
process_handler
.
kill
()
computer_partition
.
error
(
"The promise %r timed out"
%
promise
)
elif
process_handler
.
poll
()
!=
0
:
stderr
=
process_handler
.
communicate
()[
1
]
if
stderr
is
None
:
stderr
=
'No error output from %r.'
%
promise
computer_partition
.
error
(
stderr
)
logger
.
info
(
"Finished computer partitions..."
)
return
clean_run
...
...
slapos/tests/mock/httplib.py
View file @
00c3e8a5
...
...
@@ -3,8 +3,6 @@
"""Mocked httplib
"""
from
urlparse
import
urlparse
__all__
=
[]
def
log
(
message
):
...
...
@@ -21,13 +19,13 @@ class HTTPConnection(object):
HTTPConnection._callback. This method received the instance, the path,
method and request body as parameter, and it has to return a tuple with
headers dictionary and body response string.
@param self object instance reference
@param URL the parsed URL
@param method the http method
@param body the request body
@param headers the request headers
@return tuple containing status integer, headers dictionary and body
response"""
return
(
0
,
{},
''
,
)
...
...
@@ -83,7 +81,6 @@ class HTTPSConnection(HTTPConnection):
source_address
=
None
):
super
().
__init__
(
self
,
host
,
port
,
strict
,
timeout
,
source_address
)
pass
class
HTTPResponse
(
object
):
...
...
slapos/tests/slapgrid.py
View file @
00c3e8a5
...
...
@@ -6,7 +6,9 @@ import shutil
import
signal
import
slapos.slap.slap
import
socket
import
sys
import
tempfile
import
time
import
unittest
import
urlparse
import
xml_marshaller
...
...
@@ -34,6 +36,15 @@ class BasicMixin:
self
.
buildout
)
def
tearDown
(
self
):
# XXX: Hardcoded pid, as it is not configurable in slapos
svc
=
os
.
path
.
join
(
self
.
instance_root
,
'var'
,
'run'
,
'supervisord.pid'
)
if
os
.
path
.
exists
(
svc
):
try
:
pid
=
int
(
open
(
svc
).
read
().
strip
())
except
ValueError
:
pass
else
:
os
.
kill
(
pid
,
signal
.
SIGTERM
)
shutil
.
rmtree
(
self
.
_tempdir
,
True
)
class
TestBasicSlapgridCP
(
BasicMixin
,
unittest
.
TestCase
):
...
...
@@ -68,21 +79,51 @@ class MasterMixin(BasicMixin):
setattr
(
httplib
,
name
,
original_value
)
del
self
.
saved_httplib
def
_mock_sleep
(
self
):
self
.
fake_waiting_time
=
None
self
.
real_sleep
=
time
.
sleep
def
mocked_sleep
(
secs
):
if
self
.
fake_waiting_time
is
not
None
:
secs
=
self
.
fake_waiting_time
self
.
real_sleep
(
secs
)
time
.
sleep
=
mocked_sleep
def
_unmock_sleep
(
self
):
time
.
sleep
=
self
.
real_sleep
def
_create_instance
(
self
,
name
=
0
):
if
not
os
.
path
.
isdir
(
self
.
instance_root
):
os
.
mkdir
(
self
.
instance_root
)
partition_path
=
os
.
path
.
join
(
self
.
instance_root
,
str
(
name
))
os
.
mkdir
(
partition_path
,
0750
)
return
partition_path
def
_bootstrap
(
self
):
os
.
mkdir
(
self
.
software_root
)
software_hash
=
slapos
.
grid
.
utils
.
getSoftwareUrlHash
(
'http://sr/'
)
srdir
=
os
.
path
.
join
(
self
.
software_root
,
software_hash
)
os
.
mkdir
(
srdir
)
open
(
os
.
path
.
join
(
srdir
,
'template.cfg'
),
'w'
).
write
(
"""[buildout]"""
)
srbindir
=
os
.
path
.
join
(
srdir
,
'bin'
)
os
.
mkdir
(
srbindir
)
open
(
os
.
path
.
join
(
srbindir
,
'buildout'
),
'w'
).
write
(
"""#!/bin/sh
touch worked"""
)
os
.
chmod
(
os
.
path
.
join
(
srbindir
,
'buildout'
),
0755
)
return
software_hash
def
setUp
(
self
):
self
.
_patchHttplib
()
self
.
_mock_sleep
()
BasicMixin
.
setUp
(
self
)
def
tearDown
(
self
):
self
.
_unpatchHttplib
()
# XXX: Hardcoded pid, as it is not configurable in slapos
svc
=
os
.
path
.
join
(
self
.
instance_root
,
'var'
,
'run'
,
'supervisord.pid'
)
if
os
.
path
.
exists
(
svc
):
try
:
pid
=
int
(
open
(
svc
).
read
().
strip
())
except
ValueError
:
pass
else
:
os
.
kill
(
pid
,
signal
.
SIGTERM
)
self
.
_unmock_sleep
()
BasicMixin
.
tearDown
(
self
)
class
TestSlapgridCPWithMaster
(
MasterMixin
,
unittest
.
TestCase
):
...
...
@@ -111,9 +152,9 @@ class TestSlapgridCPWithMaster(MasterMixin, unittest.TestCase):
def
test_one_partition
(
self
):
def
server_response
(
self
,
path
,
method
,
body
,
header
):
parsed_url
=
urlparse
.
urlparse
(
'/'
+
path
)
parsed_url
=
urlparse
.
urlparse
(
path
.
lstrip
(
'/'
)
)
parsed_qs
=
urlparse
.
parse_qs
(
parsed_url
.
query
)
if
parsed_url
.
path
==
'
/
getComputerInformation'
and
\
if
parsed_url
.
path
==
'getComputerInformation'
and
\
'computer_id'
in
parsed_qs
:
slap_computer
=
slapos
.
slap
.
Computer
(
parsed_qs
[
'computer_id'
])
slap_computer
.
_software_release_list
=
[]
...
...
@@ -147,8 +188,258 @@ touch worked""")
self
.
assertTrue
(
self
.
grid
.
processComputerPartitionList
())
self
.
assertSortedListEqual
(
os
.
listdir
(
self
.
instance_root
),
[
'0'
,
'etc'
,
'var'
])
partition
=
os
.
path
.
join
(
self
.
instance_root
,
'0'
)
self
.
assertSortedListEqual
(
os
.
listdir
(
partition
),
[
'worked'
,
'buildout.cfg'
])
self
.
assertSortedListEqual
(
os
.
listdir
(
self
.
software_root
),
[
software_hash
])
def
test_one_partition_started
(
self
):
def
server_response
(
self
,
path
,
method
,
body
,
header
):
parsed_url
=
urlparse
.
urlparse
(
path
.
lstrip
(
'/'
))
parsed_qs
=
urlparse
.
parse_qs
(
parsed_url
.
query
)
if
parsed_url
.
path
==
'getComputerInformation'
and
\
'computer_id'
in
parsed_qs
:
slap_computer
=
slapos
.
slap
.
Computer
(
parsed_qs
[
'computer_id'
])
slap_computer
.
_software_release_list
=
[]
partition
=
slapos
.
slap
.
ComputerPartition
(
parsed_qs
[
'computer_id'
],
'0'
)
partition
.
_need_modification
=
True
sr
=
slapos
.
slap
.
SoftwareRelease
()
sr
.
_software_release
=
'http://sr/'
partition
.
_software_release_document
=
sr
partition
.
_requested_state
=
'started'
slap_computer
.
_computer_partition_list
=
[
partition
]
return
(
200
,
{},
xml_marshaller
.
xml_marshaller
.
dumps
(
slap_computer
))
else
:
return
(
404
,
{},
''
)
httplib
.
HTTPConnection
.
_callback
=
server_response
os
.
mkdir
(
self
.
software_root
)
os
.
mkdir
(
self
.
instance_root
)
partition_path
=
os
.
path
.
join
(
self
.
instance_root
,
'0'
)
os
.
mkdir
(
partition_path
,
0750
)
software_hash
=
slapos
.
grid
.
utils
.
getSoftwareUrlHash
(
'http://sr/'
)
srdir
=
os
.
path
.
join
(
self
.
software_root
,
software_hash
)
os
.
mkdir
(
srdir
)
open
(
os
.
path
.
join
(
srdir
,
'template.cfg'
),
'w'
).
write
(
"""[buildout]"""
)
srbindir
=
os
.
path
.
join
(
srdir
,
'bin'
)
os
.
mkdir
(
srbindir
)
open
(
os
.
path
.
join
(
srbindir
,
'buildout'
),
'w'
).
write
(
"""#!/bin/sh
touch worked &&
mkdir -p etc/run &&
echo "#!/bin/sh" > etc/run/wrapper &&
echo "while :; do echo "Working
\
\
nWorking
\
\
n" ; done" >> etc/run/wrapper &&
chmod 755 etc/run/wrapper
"""
)
os
.
chmod
(
os
.
path
.
join
(
srbindir
,
'buildout'
),
0755
)
self
.
assertTrue
(
self
.
grid
.
processComputerPartitionList
())
self
.
assertSortedListEqual
(
os
.
listdir
(
self
.
instance_root
),
[
'0'
,
'etc'
,
'var'
])
self
.
assertSortedListEqual
(
os
.
listdir
(
partition_path
),
[
'.0_wrapper.log'
,
'worked'
,
'buildout.cfg'
,
'etc'
])
tries
=
10
wrapper_log
=
os
.
path
.
join
(
partition_path
,
'.0_wrapper.log'
)
while
tries
>
0
:
tries
-=
1
if
os
.
path
.
getsize
(
wrapper_log
)
>
0
:
break
time
.
sleep
(
0.2
)
self
.
assertTrue
(
'Working'
in
open
(
wrapper_log
,
'r'
).
read
())
self
.
assertSortedListEqual
(
os
.
listdir
(
self
.
software_root
),
[
software_hash
])
def
test_one_partition_started_stopped
(
self
):
def
server_response
(
self
,
path
,
method
,
body
,
header
):
parsed_url
=
urlparse
.
urlparse
(
path
.
lstrip
(
'/'
))
parsed_qs
=
urlparse
.
parse_qs
(
parsed_url
.
query
)
if
parsed_url
.
path
==
'getComputerInformation'
and
\
'computer_id'
in
parsed_qs
:
slap_computer
=
slapos
.
slap
.
Computer
(
parsed_qs
[
'computer_id'
])
slap_computer
.
_software_release_list
=
[]
partition
=
slapos
.
slap
.
ComputerPartition
(
parsed_qs
[
'computer_id'
],
'0'
)
partition
.
_need_modification
=
True
sr
=
slapos
.
slap
.
SoftwareRelease
()
sr
.
_software_release
=
'http://sr/'
partition
.
_software_release_document
=
sr
partition
.
_requested_state
=
'started'
slap_computer
.
_computer_partition_list
=
[
partition
]
return
(
200
,
{},
xml_marshaller
.
xml_marshaller
.
dumps
(
slap_computer
))
else
:
return
(
404
,
{},
''
)
httplib
.
HTTPConnection
.
_callback
=
server_response
os
.
mkdir
(
self
.
software_root
)
os
.
mkdir
(
self
.
instance_root
)
partition_path
=
os
.
path
.
join
(
self
.
instance_root
,
'0'
)
os
.
mkdir
(
partition_path
,
0750
)
software_hash
=
slapos
.
grid
.
utils
.
getSoftwareUrlHash
(
'http://sr/'
)
srdir
=
os
.
path
.
join
(
self
.
software_root
,
software_hash
)
os
.
mkdir
(
srdir
)
open
(
os
.
path
.
join
(
srdir
,
'template.cfg'
),
'w'
).
write
(
"""[buildout]"""
)
srbindir
=
os
.
path
.
join
(
srdir
,
'bin'
)
os
.
mkdir
(
srbindir
)
open
(
os
.
path
.
join
(
srbindir
,
'buildout'
),
'w'
).
write
(
"""#!/bin/sh
touch worked &&
mkdir -p etc/run &&
(
cat <<'HEREDOC'
#!%(python)s
import signal
def handler(signum, frame):
print 'Signal handler called with signal', signum
raise SystemExit
signal.signal(signal.SIGTERM, handler)
while True:
print "Working"
HEREDOC
)> etc/run/wrapper &&
chmod 755 etc/run/wrapper
"""
%
dict
(
python
=
sys
.
executable
))
os
.
chmod
(
os
.
path
.
join
(
srbindir
,
'buildout'
),
0755
)
self
.
assertTrue
(
self
.
grid
.
processComputerPartitionList
())
self
.
assertSortedListEqual
(
os
.
listdir
(
self
.
instance_root
),
[
'0'
,
'etc'
,
'var'
])
self
.
assertSortedListEqual
(
os
.
listdir
(
partition_path
),
[
'.0_wrapper.log'
,
'worked'
,
'buildout.cfg'
,
'etc'
])
wrapper_log
=
os
.
path
.
join
(
partition_path
,
'.0_wrapper.log'
)
tries
=
10
while
tries
>
0
:
tries
-=
1
if
os
.
path
.
getsize
(
wrapper_log
)
>
0
:
break
time
.
sleep
(
0.2
)
last_size
=
os
.
path
.
getsize
(
wrapper_log
)
self
.
assertTrue
(
'Working'
in
open
(
wrapper_log
,
'r'
).
read
())
self
.
assertSortedListEqual
(
os
.
listdir
(
self
.
software_root
),
[
software_hash
])
def
server_response
(
self
,
path
,
method
,
body
,
header
):
parsed_url
=
urlparse
.
urlparse
(
path
.
lstrip
(
'/'
))
parsed_qs
=
urlparse
.
parse_qs
(
parsed_url
.
query
)
if
parsed_url
.
path
==
'getComputerInformation'
and
\
'computer_id'
in
parsed_qs
:
slap_computer
=
slapos
.
slap
.
Computer
(
parsed_qs
[
'computer_id'
])
slap_computer
.
_software_release_list
=
[]
partition
=
slapos
.
slap
.
ComputerPartition
(
parsed_qs
[
'computer_id'
],
'0'
)
partition
.
_need_modification
=
True
sr
=
slapos
.
slap
.
SoftwareRelease
()
sr
.
_software_release
=
'http://sr/'
partition
.
_software_release_document
=
sr
partition
.
_requested_state
=
'stopped'
slap_computer
.
_computer_partition_list
=
[
partition
]
return
(
200
,
{},
xml_marshaller
.
xml_marshaller
.
dumps
(
slap_computer
))
else
:
return
(
404
,
{},
''
)
httplib
.
HTTPConnection
.
_callback
=
server_response
self
.
assertTrue
(
self
.
grid
.
processComputerPartitionList
())
self
.
assertSortedListEqual
(
os
.
listdir
(
self
.
instance_root
),
[
'0'
,
'etc'
,
'var'
])
self
.
assertSortedListEqual
(
os
.
listdir
(
partition_path
),
[
'.0_wrapper.log'
,
'.0_wrapper.log.1'
,
'worked'
,
'buildout.cfg'
,
'etc'
])
tries
=
10
expected_text
=
'Signal handler called with signal 15'
while
tries
>
0
:
tries
-=
1
found
=
expected_text
in
open
(
wrapper_log
,
'r'
).
read
()
if
found
:
break
time
.
sleep
(
0.2
)
self
.
assertTrue
(
found
)
def
test_one_partition_stopped_started
(
self
):
def
server_response
(
self
,
path
,
method
,
body
,
header
):
parsed_url
=
urlparse
.
urlparse
(
path
.
lstrip
(
'/'
))
parsed_qs
=
urlparse
.
parse_qs
(
parsed_url
.
query
)
if
parsed_url
.
path
==
'getComputerInformation'
and
\
'computer_id'
in
parsed_qs
:
slap_computer
=
slapos
.
slap
.
Computer
(
parsed_qs
[
'computer_id'
])
slap_computer
.
_software_release_list
=
[]
partition
=
slapos
.
slap
.
ComputerPartition
(
parsed_qs
[
'computer_id'
],
'0'
)
partition
.
_need_modification
=
True
sr
=
slapos
.
slap
.
SoftwareRelease
()
sr
.
_software_release
=
'http://sr/'
partition
.
_software_release_document
=
sr
partition
.
_requested_state
=
'stopped'
slap_computer
.
_computer_partition_list
=
[
partition
]
return
(
200
,
{},
xml_marshaller
.
xml_marshaller
.
dumps
(
slap_computer
))
else
:
return
(
404
,
{},
''
)
httplib
.
HTTPConnection
.
_callback
=
server_response
os
.
mkdir
(
self
.
software_root
)
os
.
mkdir
(
self
.
instance_root
)
partition_path
=
os
.
path
.
join
(
self
.
instance_root
,
'0'
)
os
.
mkdir
(
partition_path
,
0750
)
software_hash
=
slapos
.
grid
.
utils
.
getSoftwareUrlHash
(
'http://sr/'
)
srdir
=
os
.
path
.
join
(
self
.
software_root
,
software_hash
)
os
.
mkdir
(
srdir
)
open
(
os
.
path
.
join
(
srdir
,
'template.cfg'
),
'w'
).
write
(
"""[buildout]"""
)
srbindir
=
os
.
path
.
join
(
srdir
,
'bin'
)
os
.
mkdir
(
srbindir
)
open
(
os
.
path
.
join
(
srbindir
,
'buildout'
),
'w'
).
write
(
"""#!/bin/sh
touch worked &&
mkdir -p etc/run &&
echo "#!/bin/sh" > etc/run/wrapper &&
echo "while :; do echo "Working
\
\
nWorking
\
\
n" ; done" >> etc/run/wrapper &&
chmod 755 etc/run/wrapper
"""
)
os
.
chmod
(
os
.
path
.
join
(
srbindir
,
'buildout'
),
0755
)
self
.
assertTrue
(
self
.
grid
.
processComputerPartitionList
())
self
.
assertSortedListEqual
(
os
.
listdir
(
self
.
instance_root
),
[
'0'
,
'etc'
,
'var'
])
partition
=
os
.
path
.
join
(
self
.
instance_root
,
'0'
)
self
.
assertSortedListEqual
(
os
.
listdir
(
partition
),
[
'worked'
,
'etc'
,
'buildout.cfg'
])
self
.
assertSortedListEqual
(
os
.
listdir
(
self
.
software_root
),
[
software_hash
])
def
server_response
(
self
,
path
,
method
,
body
,
header
):
parsed_url
=
urlparse
.
urlparse
(
path
.
lstrip
(
'/'
))
parsed_qs
=
urlparse
.
parse_qs
(
parsed_url
.
query
)
if
parsed_url
.
path
==
'getComputerInformation'
and
\
'computer_id'
in
parsed_qs
:
slap_computer
=
slapos
.
slap
.
Computer
(
parsed_qs
[
'computer_id'
])
slap_computer
.
_software_release_list
=
[]
partition
=
slapos
.
slap
.
ComputerPartition
(
parsed_qs
[
'computer_id'
],
'0'
)
partition
.
_need_modification
=
True
sr
=
slapos
.
slap
.
SoftwareRelease
()
sr
.
_software_release
=
'http://sr/'
partition
.
_software_release_document
=
sr
partition
.
_requested_state
=
'started'
slap_computer
.
_computer_partition_list
=
[
partition
]
return
(
200
,
{},
xml_marshaller
.
xml_marshaller
.
dumps
(
slap_computer
))
else
:
return
(
404
,
{},
''
)
httplib
.
HTTPConnection
.
_callback
=
server_response
self
.
assertTrue
(
self
.
grid
.
processComputerPartitionList
())
self
.
assertSortedListEqual
(
os
.
listdir
(
self
.
instance_root
),
[
'0'
,
'etc'
,
'var'
])
partition
=
os
.
path
.
join
(
self
.
instance_root
,
'0'
)
self
.
assertSortedListEqual
(
os
.
listdir
(
partition
),
[
'.0_wrapper.log'
,
'worked'
,
'etc'
,
'buildout.cfg'
])
self
.
assertSortedListEqual
(
os
.
listdir
(
self
.
software_root
),
[
software_hash
])
tries
=
10
wrapper_log
=
os
.
path
.
join
(
partition_path
,
'.0_wrapper.log'
)
while
tries
>
0
:
tries
-=
1
if
os
.
path
.
getsize
(
wrapper_log
)
>
0
:
break
time
.
sleep
(
0.2
)
self
.
assertTrue
(
'Working'
in
open
(
wrapper_log
,
'r'
).
read
())
class
TestSlapgridArgumentTuple
(
unittest
.
TestCase
):
"""
...
...
@@ -231,3 +522,409 @@ buildout = /path/to/buildout/binary
slapgrid_object
=
parser
(
*
argument_tuple
)[
0
]
self
.
assertEquals
(
self
.
signature_key_file_descriptor
.
name
,
slapgrid_object
.
signature_private_key_file
)
class
TestSlapgridCPWithMasterPromise
(
MasterMixin
,
unittest
.
TestCase
):
def
test_one_failing_promise
(
self
):
def
server_response
(
self_httplib
,
path
,
method
,
body
,
header
):
parsed_url
=
urlparse
.
urlparse
(
path
.
lstrip
(
'/'
))
if
method
==
'GET'
:
parsed_qs
=
urlparse
.
parse_qs
(
parsed_url
.
query
)
else
:
parsed_qs
=
urlparse
.
parse_qs
(
body
)
if
parsed_url
.
path
==
'getComputerInformation'
and
\
'computer_id'
in
parsed_qs
:
slap_computer
=
slapos
.
slap
.
Computer
(
parsed_qs
[
'computer_id'
][
0
])
slap_computer
.
_software_release_list
=
[]
partition
=
slapos
.
slap
.
ComputerPartition
(
parsed_qs
[
'computer_id'
][
0
],
'0'
)
partition
.
_need_modification
=
True
sr
=
slapos
.
slap
.
SoftwareRelease
()
sr
.
_software_release
=
'http://sr/'
partition
.
_software_release_document
=
sr
partition
.
_requested_state
=
'stopped'
slap_computer
.
_computer_partition_list
=
[
partition
]
return
(
200
,
{},
xml_marshaller
.
xml_marshaller
.
dumps
(
slap_computer
))
if
parsed_url
.
path
==
'softwareInstanceError'
and
\
method
==
'POST'
and
'computer_partition_id'
in
parsed_qs
:
self
.
error
=
True
self
.
assertEqual
(
parsed_qs
[
'computer_partition_id'
][
0
],
'0'
)
return
(
200
,
{},
''
)
else
:
return
(
404
,
{},
''
)
httplib
.
HTTPConnection
.
_callback
=
server_response
self
.
fake_waiting_time
=
0.2
self
.
error
=
False
instance_path
=
self
.
_create_instance
(
'0'
)
software_hash
=
self
.
_bootstrap
()
promise_path
=
os
.
path
.
join
(
instance_path
,
'etc'
,
'promise'
)
os
.
makedirs
(
promise_path
)
fail
=
os
.
path
.
join
(
promise_path
,
'fail'
)
worked_file
=
os
.
path
.
join
(
instance_path
,
'fail_worked'
)
with
open
(
fail
,
'w'
)
as
f
:
f
.
write
(
"""#!/usr/bin/env sh
touch "%(worked_file)s"
exit 127"""
%
{
'worked_file'
:
worked_file
})
os
.
chmod
(
fail
,
0777
)
self
.
assertTrue
(
self
.
grid
.
processComputerPartitionList
())
self
.
assertTrue
(
os
.
path
.
isfile
(
worked_file
))
self
.
assertTrue
(
self
.
error
)
def
test_one_succeeding_promise
(
self
):
def
server_response
(
self_httplib
,
path
,
method
,
body
,
header
):
parsed_url
=
urlparse
.
urlparse
(
path
.
lstrip
(
'/'
))
if
method
==
'GET'
:
parsed_qs
=
urlparse
.
parse_qs
(
parsed_url
.
query
)
else
:
parsed_qs
=
urlparse
.
parse_qs
(
body
)
if
parsed_url
.
path
==
'getComputerInformation'
and
\
'computer_id'
in
parsed_qs
:
slap_computer
=
slapos
.
slap
.
Computer
(
parsed_qs
[
'computer_id'
][
0
])
slap_computer
.
_software_release_list
=
[]
partition
=
slapos
.
slap
.
ComputerPartition
(
parsed_qs
[
'computer_id'
][
0
],
'0'
)
partition
.
_need_modification
=
True
sr
=
slapos
.
slap
.
SoftwareRelease
()
sr
.
_software_release
=
'http://sr/'
partition
.
_software_release_document
=
sr
partition
.
_requested_state
=
'stopped'
slap_computer
.
_computer_partition_list
=
[
partition
]
return
(
200
,
{},
xml_marshaller
.
xml_marshaller
.
dumps
(
slap_computer
))
if
parsed_url
.
path
==
'softwareInstanceError'
and
\
method
==
'POST'
and
'computer_partition_id'
in
parsed_qs
:
self
.
error
=
True
raise
AssertionError
(
'ComputerPartition.error was raised'
)
return
(
200
,
{},
''
)
else
:
return
(
404
,
{},
''
)
httplib
.
HTTPConnection
.
_callback
=
server_response
self
.
fake_waiting_time
=
0.2
self
.
error
=
False
instance_path
=
self
.
_create_instance
(
'0'
)
software_hash
=
self
.
_bootstrap
()
promise_path
=
os
.
path
.
join
(
instance_path
,
'etc'
,
'promise'
)
os
.
makedirs
(
promise_path
)
succeed
=
os
.
path
.
join
(
promise_path
,
'succeed'
)
worked_file
=
os
.
path
.
join
(
instance_path
,
'succeed_worked'
)
with
open
(
succeed
,
'w'
)
as
f
:
f
.
write
(
"""#!/usr/bin/env sh
touch "%(worked_file)s"
exit 0"""
%
{
'worked_file'
:
worked_file
})
os
.
chmod
(
succeed
,
0777
)
self
.
assertTrue
(
self
.
grid
.
processComputerPartitionList
())
self
.
assertTrue
(
os
.
path
.
isfile
(
worked_file
))
self
.
assertFalse
(
self
.
error
)
def
test_stderr_has_been_sent
(
self
):
def
server_response
(
self_httplib
,
path
,
method
,
body
,
header
):
parsed_url
=
urlparse
.
urlparse
(
path
.
lstrip
(
'/'
))
if
method
==
'GET'
:
parsed_qs
=
urlparse
.
parse_qs
(
parsed_url
.
query
)
else
:
parsed_qs
=
urlparse
.
parse_qs
(
body
)
if
parsed_url
.
path
==
'getComputerInformation'
and
\
'computer_id'
in
parsed_qs
:
slap_computer
=
slapos
.
slap
.
Computer
(
parsed_qs
[
'computer_id'
][
0
])
slap_computer
.
_software_release_list
=
[]
partition
=
slapos
.
slap
.
ComputerPartition
(
parsed_qs
[
'computer_id'
][
0
],
'0'
)
partition
.
_need_modification
=
True
sr
=
slapos
.
slap
.
SoftwareRelease
()
sr
.
_software_release
=
'http://sr/'
partition
.
_software_release_document
=
sr
partition
.
_requested_state
=
'stopped'
slap_computer
.
_computer_partition_list
=
[
partition
]
return
(
200
,
{},
xml_marshaller
.
xml_marshaller
.
dumps
(
slap_computer
))
if
parsed_url
.
path
==
'softwareInstanceError'
and
\
method
==
'POST'
and
'computer_partition_id'
in
parsed_qs
:
self
.
error
=
True
self
.
assertEqual
(
parsed_qs
[
'computer_partition_id'
][
0
],
'0'
)
# XXX: Hardcoded dropPrivileges line ignore
self
.
error_log
=
'
\
n
'
.
join
([
line
for
line
in
parsed_qs
[
'error_log'
][
0
].
splitlines
()
if
'dropPrivileges'
not
in
line
])
# end XXX
return
(
200
,
{},
''
)
else
:
return
(
404
,
{},
''
)
httplib
.
HTTPConnection
.
_callback
=
server_response
self
.
fake_waiting_time
=
0.5
self
.
error
=
False
instance_path
=
self
.
_create_instance
(
'0'
)
software_hash
=
self
.
_bootstrap
()
promise_path
=
os
.
path
.
join
(
instance_path
,
'etc'
,
'promise'
)
os
.
makedirs
(
promise_path
)
succeed
=
os
.
path
.
join
(
promise_path
,
'stderr_writer'
)
worked_file
=
os
.
path
.
join
(
instance_path
,
'stderr_worked'
)
with
open
(
succeed
,
'w'
)
as
f
:
f
.
write
(
"""#!/usr/bin/env sh
touch "%(worked_file)s"
echo -n Error 1>&2
exit 127"""
%
{
'worked_file'
:
worked_file
})
os
.
chmod
(
succeed
,
0777
)
self
.
assertTrue
(
self
.
grid
.
processComputerPartitionList
())
self
.
assertTrue
(
os
.
path
.
isfile
(
worked_file
))
self
.
assertEqual
(
self
.
error_log
,
'Error'
)
self
.
assertTrue
(
self
.
error
)
def
test_timeout_works
(
self
):
def
server_response
(
self_httplib
,
path
,
method
,
body
,
header
):
parsed_url
=
urlparse
.
urlparse
(
path
.
lstrip
(
'/'
))
if
method
==
'GET'
:
parsed_qs
=
urlparse
.
parse_qs
(
parsed_url
.
query
)
else
:
parsed_qs
=
urlparse
.
parse_qs
(
body
)
if
parsed_url
.
path
==
'getComputerInformation'
and
\
'computer_id'
in
parsed_qs
:
slap_computer
=
slapos
.
slap
.
Computer
(
parsed_qs
[
'computer_id'
][
0
])
slap_computer
.
_software_release_list
=
[]
partition
=
slapos
.
slap
.
ComputerPartition
(
parsed_qs
[
'computer_id'
][
0
],
'0'
)
partition
.
_need_modification
=
True
sr
=
slapos
.
slap
.
SoftwareRelease
()
sr
.
_software_release
=
'http://sr/'
partition
.
_software_release_document
=
sr
partition
.
_requested_state
=
'stopped'
slap_computer
.
_computer_partition_list
=
[
partition
]
return
(
200
,
{},
xml_marshaller
.
xml_marshaller
.
dumps
(
slap_computer
))
if
parsed_url
.
path
==
'softwareInstanceError'
and
\
method
==
'POST'
and
'computer_partition_id'
in
parsed_qs
:
self
.
error
=
True
self
.
assertEqual
(
parsed_qs
[
'computer_partition_id'
][
0
],
'0'
)
# XXX: Hardcoded dropPrivileges line ignore
error_log
=
'
\
n
'
.
join
([
line
for
line
in
parsed_qs
[
'error_log'
][
0
].
splitlines
()
if
'dropPrivileges'
not
in
line
])
# end XXX
self
.
assertEqual
(
error_log
,
'The promise %r timed out'
%
'timed_out_promise'
)
return
(
200
,
{},
''
)
else
:
return
(
404
,
{},
''
)
httplib
.
HTTPConnection
.
_callback
=
server_response
self
.
fake_waiting_time
=
0.2
self
.
error
=
False
instance_path
=
self
.
_create_instance
(
'0'
)
software_hash
=
self
.
_bootstrap
()
promise_path
=
os
.
path
.
join
(
instance_path
,
'etc'
,
'promise'
)
os
.
makedirs
(
promise_path
)
succeed
=
os
.
path
.
join
(
promise_path
,
'timed_out_promise'
)
worked_file
=
os
.
path
.
join
(
instance_path
,
'timed_out_worked'
)
with
open
(
succeed
,
'w'
)
as
f
:
f
.
write
(
"""#!/usr/bin/env sh
touch "%(worked_file)s"
sleep 5
exit 0"""
%
{
'worked_file'
:
worked_file
})
os
.
chmod
(
succeed
,
0777
)
self
.
assertTrue
(
self
.
grid
.
processComputerPartitionList
())
self
.
assertTrue
(
os
.
path
.
isfile
(
worked_file
))
self
.
assertTrue
(
self
.
error
)
def
test_two_succeeding_promises
(
self
):
def
server_response
(
self_httplib
,
path
,
method
,
body
,
header
):
parsed_url
=
urlparse
.
urlparse
(
path
.
lstrip
(
'/'
))
if
method
==
'GET'
:
parsed_qs
=
urlparse
.
parse_qs
(
parsed_url
.
query
)
else
:
parsed_qs
=
urlparse
.
parse_qs
(
body
)
if
parsed_url
.
path
==
'getComputerInformation'
and
\
'computer_id'
in
parsed_qs
:
slap_computer
=
slapos
.
slap
.
Computer
(
parsed_qs
[
'computer_id'
][
0
])
slap_computer
.
_software_release_list
=
[]
partition
=
slapos
.
slap
.
ComputerPartition
(
parsed_qs
[
'computer_id'
][
0
],
'0'
)
partition
.
_need_modification
=
True
sr
=
slapos
.
slap
.
SoftwareRelease
()
sr
.
_software_release
=
'http://sr/'
partition
.
_software_release_document
=
sr
partition
.
_requested_state
=
'stopped'
slap_computer
.
_computer_partition_list
=
[
partition
]
return
(
200
,
{},
xml_marshaller
.
xml_marshaller
.
dumps
(
slap_computer
))
if
parsed_url
.
path
==
'softwareInstanceError'
and
\
method
==
'POST'
and
'computer_partition_id'
in
parsed_qs
:
self
.
error
=
True
raise
AssertionError
(
'ComputerPartition.error was raised'
)
return
(
200
,
{},
''
)
else
:
return
(
404
,
{},
''
)
httplib
.
HTTPConnection
.
_callback
=
server_response
self
.
fake_waiting_time
=
0.2
self
.
error
=
False
instance_path
=
self
.
_create_instance
(
'0'
)
software_hash
=
self
.
_bootstrap
()
promise_path
=
os
.
path
.
join
(
instance_path
,
'etc'
,
'promise'
)
os
.
makedirs
(
promise_path
)
succeed
=
os
.
path
.
join
(
promise_path
,
'succeed'
)
worked_file
=
os
.
path
.
join
(
instance_path
,
'succeed_worked'
)
with
open
(
succeed
,
'w'
)
as
f
:
f
.
write
(
"""#!/usr/bin/env sh
touch "%(worked_file)s"
exit 0"""
%
{
'worked_file'
:
worked_file
})
os
.
chmod
(
succeed
,
0777
)
succeed_2
=
os
.
path
.
join
(
promise_path
,
'succeed_2'
)
worked_file_2
=
os
.
path
.
join
(
instance_path
,
'succeed_2_worked'
)
with
open
(
succeed_2
,
'w'
)
as
f
:
f
.
write
(
"""#!/usr/bin/env sh
touch "%(worked_file)s"
exit 0"""
%
{
'worked_file'
:
worked_file_2
})
os
.
chmod
(
succeed_2
,
0777
)
self
.
assertTrue
(
self
.
grid
.
processComputerPartitionList
())
self
.
assertTrue
(
os
.
path
.
isfile
(
worked_file
))
self
.
assertTrue
(
os
.
path
.
isfile
(
worked_file_2
))
self
.
assertFalse
(
self
.
error
)
def
test_one_succeeding_one_failing_promises
(
self
):
def
server_response
(
self_httplib
,
path
,
method
,
body
,
header
):
parsed_url
=
urlparse
.
urlparse
(
path
.
lstrip
(
'/'
))
if
method
==
'GET'
:
parsed_qs
=
urlparse
.
parse_qs
(
parsed_url
.
query
)
else
:
parsed_qs
=
urlparse
.
parse_qs
(
body
)
if
parsed_url
.
path
==
'getComputerInformation'
and
\
'computer_id'
in
parsed_qs
:
slap_computer
=
slapos
.
slap
.
Computer
(
parsed_qs
[
'computer_id'
][
0
])
slap_computer
.
_software_release_list
=
[]
partition
=
slapos
.
slap
.
ComputerPartition
(
parsed_qs
[
'computer_id'
][
0
],
'0'
)
partition
.
_need_modification
=
True
sr
=
slapos
.
slap
.
SoftwareRelease
()
sr
.
_software_release
=
'http://sr/'
partition
.
_software_release_document
=
sr
partition
.
_requested_state
=
'stopped'
slap_computer
.
_computer_partition_list
=
[
partition
]
return
(
200
,
{},
xml_marshaller
.
xml_marshaller
.
dumps
(
slap_computer
))
if
parsed_url
.
path
==
'softwareInstanceError'
and
\
method
==
'POST'
and
'computer_partition_id'
in
parsed_qs
:
self
.
error
+=
1
self
.
assertEqual
(
parsed_qs
[
'computer_partition_id'
][
0
],
'0'
)
return
(
200
,
{},
''
)
else
:
return
(
404
,
{},
''
)
httplib
.
HTTPConnection
.
_callback
=
server_response
self
.
fake_waiting_time
=
0.2
self
.
error
=
0
instance_path
=
self
.
_create_instance
(
'0'
)
software_hash
=
self
.
_bootstrap
()
promise_path
=
os
.
path
.
join
(
instance_path
,
'etc'
,
'promise'
)
os
.
makedirs
(
promise_path
)
promises_files
=
[]
for
i
in
range
(
2
):
promise
=
os
.
path
.
join
(
promise_path
,
'promise_%d'
)
promises_files
.
append
(
promise
)
worked_file
=
os
.
path
.
join
(
instance_path
,
'promise_worked_%d'
)
lockfile
=
os
.
path
.
join
(
instance_path
,
'lock'
)
with
open
(
promise
,
'w'
)
as
f
:
f
.
write
(
"""#!/usr/bin/env sh
touch "%(worked_file)s"
[[ ! -f "%(lockfile)s" ]] || { touch "%(lockfile)s" ; exit 127 }
exit 0"""
%
{
'worked_file'
:
worked_file
,
'lockfile'
:
lockfile
})
os
.
chmod
(
promise
,
0777
)
self
.
assertTrue
(
self
.
grid
.
processComputerPartitionList
())
for
file_
in
promises_files
:
self
.
assertTrue
(
os
.
path
.
isfile
(
file_
))
self
.
assertEquals
(
self
.
error
,
1
)
def
test_one_succeeding_one_timing_out_promises
(
self
):
def
server_response
(
self_httplib
,
path
,
method
,
body
,
header
):
parsed_url
=
urlparse
.
urlparse
(
path
.
lstrip
(
'/'
))
if
method
==
'GET'
:
parsed_qs
=
urlparse
.
parse_qs
(
parsed_url
.
query
)
else
:
parsed_qs
=
urlparse
.
parse_qs
(
body
)
if
parsed_url
.
path
==
'getComputerInformation'
and
\
'computer_id'
in
parsed_qs
:
slap_computer
=
slapos
.
slap
.
Computer
(
parsed_qs
[
'computer_id'
][
0
])
slap_computer
.
_software_release_list
=
[]
partition
=
slapos
.
slap
.
ComputerPartition
(
parsed_qs
[
'computer_id'
][
0
],
'0'
)
partition
.
_need_modification
=
True
sr
=
slapos
.
slap
.
SoftwareRelease
()
sr
.
_software_release
=
'http://sr/'
partition
.
_software_release_document
=
sr
partition
.
_requested_state
=
'stopped'
slap_computer
.
_computer_partition_list
=
[
partition
]
return
(
200
,
{},
xml_marshaller
.
xml_marshaller
.
dumps
(
slap_computer
))
if
parsed_url
.
path
==
'softwareInstanceError'
and
\
method
==
'POST'
and
'computer_partition_id'
in
parsed_qs
:
self
.
error
+=
1
self
.
assertEqual
(
parsed_qs
[
'computer_partition_id'
][
0
],
'0'
)
return
(
200
,
{},
''
)
else
:
return
(
404
,
{},
''
)
httplib
.
HTTPConnection
.
_callback
=
server_response
self
.
fake_waiting_time
=
0.2
self
.
error
=
0
instance_path
=
self
.
_create_instance
(
'0'
)
software_hash
=
self
.
_bootstrap
()
promise_path
=
os
.
path
.
join
(
instance_path
,
'etc'
,
'promise'
)
os
.
makedirs
(
promise_path
)
promises_files
=
[]
for
i
in
range
(
2
):
promise
=
os
.
path
.
join
(
promise_path
,
'promise_%d'
)
promises_files
.
append
(
promise
)
worked_file
=
os
.
path
.
join
(
instance_path
,
'promise_worked_%d'
)
lockfile
=
os
.
path
.
join
(
instance_path
,
'lock'
)
with
open
(
promise
,
'w'
)
as
f
:
f
.
write
(
"""#!/usr/bin/env sh
touch "%(worked_file)s"
[[ ! -f "%(lockfile)s" ]] || { touch "%(lockfile)s" ; sleep 5 }
exit 0"""
%
{
'worked_file'
:
worked_file
,
'lockfile'
:
lockfile
})
os
.
chmod
(
promise
,
0777
)
self
.
assertTrue
(
self
.
grid
.
processComputerPartitionList
())
for
file_
in
promises_files
:
self
.
assertTrue
(
os
.
path
.
isfile
(
file_
))
self
.
assertEquals
(
self
.
error
,
1
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment