Commit dd185796 authored by Romain Courteaud's avatar Romain Courteaud

slapos_cloud:

* update xml
* fix InstanceTree_assertSuccessor tests
* fixup slapos_free_compute_partition tests
* more slapos_free_compute_partition tests
* return todestroy status when instance tree is destroyed
* fixup tests for slapos_garbage_collect_destroyed_root_tree
* fixup slapos_update_compute_node_capacity_scope tests
* fixup slapos_stop_collect_instance tests
* fixup slapos_garbage_collect_non_allocated_root_tree tests
* fixup slapos_cloud_invalidate_destroyed_instance tests
* tests: prevent test to impact other tests
* test: commit transaction before end of test
* test: compatibility with _makeComplexComputeNode
* test: fixup remote node creation
parent 6ec414fc
...@@ -70,12 +70,6 @@ ...@@ -70,12 +70,6 @@
<tuple/> <tuple/>
</value> </value>
</item> </item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
......
...@@ -76,12 +76,6 @@ ...@@ -76,12 +76,6 @@
<tuple/> <tuple/>
</value> </value>
</item> </item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
......
...@@ -12,10 +12,20 @@ ...@@ -12,10 +12,20 @@
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent> <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value> </value>
</item> </item>
<item>
<key> <string>acquire_local_roles</string> </key>
<value> <int>0</int> </value>
</item>
<item> <item>
<key> <string>content_icon</string> </key> <key> <string>content_icon</string> </key>
<value> <string>folder_icon.gif</string> </value> <value> <string>folder_icon.gif</string> </value>
</item> </item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item> <item>
<key> <string>factory</string> </key> <key> <string>factory</string> </key>
<value> <string>addFolder</string> </value> <value> <string>addFolder</string> </value>
...@@ -32,6 +42,18 @@ ...@@ -32,6 +42,18 @@
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>Allocation Supply Module</string> </value> <value> <string>Allocation Supply Module</string> </value>
</item> </item>
<item>
<key> <string>init_script</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>permission</string> </key>
<value>
<none/>
</value>
</item>
<item> <item>
<key> <string>portal_type</string> </key> <key> <string>portal_type</string> </key>
<value> <string>Base Type</string> </value> <value> <string>Base Type</string> </value>
...@@ -40,6 +62,12 @@ ...@@ -40,6 +62,12 @@
<key> <string>type_class</string> </key> <key> <string>type_class</string> </key>
<value> <string>Folder</string> </value> <value> <string>Folder</string> </value>
</item> </item>
<item>
<key> <string>type_interface</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
......
...@@ -60,12 +60,6 @@ ...@@ -60,12 +60,6 @@
<tuple/> <tuple/>
</value> </value>
</item> </item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
......
...@@ -58,12 +58,6 @@ ...@@ -58,12 +58,6 @@
<tuple/> <tuple/>
</value> </value>
</item> </item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
......
...@@ -58,12 +58,6 @@ ...@@ -58,12 +58,6 @@
<tuple/> <tuple/>
</value> </value>
</item> </item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
......
...@@ -6,18 +6,18 @@ ...@@ -6,18 +6,18 @@
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item> <item>
<key> <string>_bind_names</string> </key> <key> <string>_bind_names</string> </key>
<value> <value>
<object> <object>
<klass> <klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/> <global name="_reconstructor" module="copy_reg"/>
</klass> </klass>
<tuple/> <tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state> <state>
<dictionary> <dictionary>
<item> <item>
......
...@@ -6,18 +6,18 @@ ...@@ -6,18 +6,18 @@
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item> <item>
<key> <string>_bind_names</string> </key> <key> <string>_bind_names</string> </key>
<value> <value>
<object> <object>
<klass> <klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/> <global name="_reconstructor" module="copy_reg"/>
</klass> </klass>
<tuple/> <tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state> <state>
<dictionary> <dictionary>
<item> <item>
......
...@@ -6,18 +6,18 @@ ...@@ -6,18 +6,18 @@
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item> <item>
<key> <string>_bind_names</string> </key> <key> <string>_bind_names</string> </key>
<value> <value>
<object> <object>
<klass> <klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/> <global name="_reconstructor" module="copy_reg"/>
</klass> </klass>
<tuple/> <tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state> <state>
<dictionary> <dictionary>
<item> <item>
......
...@@ -11,9 +11,13 @@ ...@@ -11,9 +11,13 @@
<value> <value>
<object> <object>
<klass> <klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/> <global name="_reconstructor" module="copy_reg"/>
</klass> </klass>
<tuple/> <tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state> <state>
<dictionary> <dictionary>
<item> <item>
......
...@@ -6,18 +6,18 @@ ...@@ -6,18 +6,18 @@
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item> <item>
<key> <string>_bind_names</string> </key> <key> <string>_bind_names</string> </key>
<value> <value>
<object> <object>
<klass> <klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/> <global name="_reconstructor" module="copy_reg"/>
</klass> </klass>
<tuple/> <tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state> <state>
<dictionary> <dictionary>
<item> <item>
......
...@@ -6,18 +6,18 @@ ...@@ -6,18 +6,18 @@
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item> <item>
<key> <string>_bind_names</string> </key> <key> <string>_bind_names</string> </key>
<value> <value>
<object> <object>
<klass> <klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/> <global name="_reconstructor" module="copy_reg"/>
</klass> </klass>
<tuple/> <tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state> <state>
<dictionary> <dictionary>
<item> <item>
......
...@@ -11,9 +11,13 @@ ...@@ -11,9 +11,13 @@
<value> <value>
<object> <object>
<klass> <klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/> <global name="_reconstructor" module="copy_reg"/>
</klass> </klass>
<tuple/> <tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state> <state>
<dictionary> <dictionary>
<item> <item>
......
...@@ -6,18 +6,18 @@ ...@@ -6,18 +6,18 @@
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item> <item>
<key> <string>_bind_names</string> </key> <key> <string>_bind_names</string> </key>
<value> <value>
<object> <object>
<klass> <klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/> <global name="_reconstructor" module="copy_reg"/>
</klass> </klass>
<tuple/> <tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state> <state>
<dictionary> <dictionary>
<item> <item>
......
service = context item = context
portal = context.getPortalObject() portal = context.getPortalObject()
if (item.getPortalType() == 'Instance Tree') and (item.getSlapState() == "destroy_requested"):
return 'todestroy'
# If no open order, subscription must be approved # If no open order, subscription must be approved
open_sale_order_movement_list = portal.portal_catalog( open_sale_order_movement_list = portal.portal_catalog(
portal_type=['Open Sale Order Line', 'Open Sale Order Cell'], portal_type=['Open Sale Order Line', 'Open Sale Order Cell'],
aggregate__uid=service.getUid(), aggregate__uid=item.getUid(),
validation_state='validated', validation_state='validated',
limit=1 limit=1
) )
context.log("%s %s" % (service.getRelativeUrl(), len(open_sale_order_movement_list)))
if len(open_sale_order_movement_list) == 0: if len(open_sale_order_movement_list) == 0:
return "not_subscribed" return "not_subscribed"
......
...@@ -6,18 +6,18 @@ ...@@ -6,18 +6,18 @@
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item> <item>
<key> <string>_bind_names</string> </key> <key> <string>_bind_names</string> </key>
<value> <value>
<object> <object>
<klass> <klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/> <global name="_reconstructor" module="copy_reg"/>
</klass> </klass>
<tuple/> <tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state> <state>
<dictionary> <dictionary>
<item> <item>
......
...@@ -6,18 +6,18 @@ ...@@ -6,18 +6,18 @@
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item> <item>
<key> <string>_bind_names</string> </key> <key> <string>_bind_names</string> </key>
<value> <value>
<object> <object>
<klass> <klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/> <global name="_reconstructor" module="copy_reg"/>
</klass> </klass>
<tuple/> <tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state> <state>
<dictionary> <dictionary>
<item> <item>
......
...@@ -11,9 +11,13 @@ ...@@ -11,9 +11,13 @@
<value> <value>
<object> <object>
<klass> <klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/> <global name="_reconstructor" module="copy_reg"/>
</klass> </klass>
<tuple/> <tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state> <state>
<dictionary> <dictionary>
<item> <item>
......
...@@ -248,6 +248,36 @@ class SlapOSTestCaseMixin(testSlapOSMixin): ...@@ -248,6 +248,36 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
return person_user return person_user
def addInstanceTree(self, project=None, person=None, shared=False):
# XXX supposed to replace _makeTree
if project is None:
project = self.addProject()
self.tic()
new_id = self.generateNewId()
if person is None:
person = self.makePerson(project, new_id=new_id, index=False)
person_user = person
request_kw = dict(
software_release=self.generateNewSoftwareReleaseUrl(),
software_title=self.generateNewSoftwareTitle(),
software_type=self.generateNewSoftwareType(),
instance_xml=self.generateSafeXml(),
sla_xml=self.generateEmptyXml(),
shared=shared,
state="started",
project_reference=project.getReference()
)
# As the software url does not match any service, and any trade condition
# no instance is automatically created.
# except if we fake Item_getSubscriptionStatus
with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
person_user.requestSoftwareInstance(**request_kw)
return person_user.REQUEST.get('request_instance_tree')
def _makeTree(self, project, requested_template_id='template_software_instance'): def _makeTree(self, project, requested_template_id='template_software_instance'):
new_id = self.generateNewId() new_id = self.generateNewId()
...@@ -322,6 +352,37 @@ class SlapOSTestCaseMixin(testSlapOSMixin): ...@@ -322,6 +352,37 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
def _makeSlaveTree(self, project, requested_template_id='template_slave_instance'): def _makeSlaveTree(self, project, requested_template_id='template_slave_instance'):
return self._makeTree(project, requested_template_id=requested_template_id) return self._makeTree(project, requested_template_id=requested_template_id)
def addComputeNodeAndPartition(self, project=None):
# XXX replace _makeComputeNode
if project is None:
project = self.addProject()
self.tic()
reference = 'TESTCOMP-%s' % self.generateNewId()
compute_node = self.portal.compute_node_module.newContent(
portal_type="Compute Node",
#allocation_scope=allocation_scope,
reference=reference,
title=reference,
follow_up_value=project
)
# The edit above will update capacity scope due the interaction workflow
# The line above force capacity scope to be open, keeping the previous
# behaviour.
compute_node.edit(capacity_scope='open')
compute_node.validate()
reference = 'TESTPART-%s' % self.generateNewId()
partition = compute_node.newContent(
portal_type='Compute Partition',
reference=reference,
title=reference
)
partition.markFree()
partition.validate()
return compute_node, partition
def _makeComputeNode(self, project, allocation_scope='open'): def _makeComputeNode(self, project, allocation_scope='open'):
self.compute_node = self.portal.compute_node_module.template_compute_node\ self.compute_node = self.portal.compute_node_module.template_compute_node\
.Base_createCloneDocument(batch_mode=1) .Base_createCloneDocument(batch_mode=1)
...@@ -436,7 +497,8 @@ class SlapOSTestCaseMixin(testSlapOSMixin): ...@@ -436,7 +497,8 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
project_reference=project.getReference() project_reference=project.getReference()
) )
instance_tree.requestStart(**kw) instance_tree.requestStart(**kw)
instance_tree.requestInstance(**kw) with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
instance_tree.requestInstance(**kw)
self.start_requested_software_instance = instance_tree.getSuccessorValue() self.start_requested_software_instance = instance_tree.getSuccessorValue()
self.start_requested_software_instance.edit(aggregate=self.compute_node.partition1.getRelativeUrl()) self.start_requested_software_instance.edit(aggregate=self.compute_node.partition1.getRelativeUrl())
...@@ -462,7 +524,8 @@ class SlapOSTestCaseMixin(testSlapOSMixin): ...@@ -462,7 +524,8 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
project_reference=project.getReference() project_reference=project.getReference()
) )
instance_tree.requestStart(**slave_kw) instance_tree.requestStart(**slave_kw)
instance_tree.requestInstance(**slave_kw) with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
instance_tree.requestInstance(**slave_kw)
self.start_requested_slave_instance = instance_tree.getSuccessorValue() self.start_requested_slave_instance = instance_tree.getSuccessorValue()
self.start_requested_slave_instance.edit(aggregate=self.compute_node.partition1.getRelativeUrl()) self.start_requested_slave_instance.edit(aggregate=self.compute_node.partition1.getRelativeUrl())
...@@ -488,7 +551,8 @@ class SlapOSTestCaseMixin(testSlapOSMixin): ...@@ -488,7 +551,8 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
project_reference=project.getReference() project_reference=project.getReference()
) )
instance_tree.requestStop(**kw) instance_tree.requestStop(**kw)
instance_tree.requestInstance(**kw) with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
instance_tree.requestInstance(**kw)
self.stop_requested_software_instance = instance_tree.getSuccessorValue() self.stop_requested_software_instance = instance_tree.getSuccessorValue()
self.stop_requested_software_instance.edit( self.stop_requested_software_instance.edit(
...@@ -515,7 +579,8 @@ class SlapOSTestCaseMixin(testSlapOSMixin): ...@@ -515,7 +579,8 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
project_reference=project.getReference() project_reference=project.getReference()
) )
instance_tree.requestStop(**kw) instance_tree.requestStop(**kw)
instance_tree.requestInstance(**kw) with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
instance_tree.requestInstance(**kw)
kw['state'] = 'destroyed' kw['state'] = 'destroyed'
instance_tree.requestDestroy(**kw) instance_tree.requestDestroy(**kw)
...@@ -546,7 +611,8 @@ class SlapOSTestCaseMixin(testSlapOSMixin): ...@@ -546,7 +611,8 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
project_reference=project.getReference() project_reference=project.getReference()
) )
instance_tree.requestStop(**kw) instance_tree.requestStop(**kw)
instance_tree.requestInstance(**kw) with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
instance_tree.requestInstance(**kw)
kw['state'] = 'destroyed' kw['state'] = 'destroyed'
instance_tree.requestDestroy(**kw) instance_tree.requestDestroy(**kw)
...@@ -647,9 +713,12 @@ class SlapOSTestCaseMixin(testSlapOSMixin): ...@@ -647,9 +713,12 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
# behaviour. # behaviour.
compute_node.edit(capacity_scope='open') compute_node.edit(capacity_scope='open')
elif node == "remote": elif node == "remote":
remote_project = self.addProject(is_accountable=False)
compute_node = self.portal.compute_node_module.newContent( compute_node = self.portal.compute_node_module.newContent(
portal_type="Remote Node", portal_type="Remote Node",
follow_up_value=project follow_up_value=project,
destination_project_value=remote_project,
destination_section_value=person
) )
elif node == "instance": elif node == "instance":
compute_node = self.portal.compute_node_module.newContent( compute_node = self.portal.compute_node_module.newContent(
...@@ -733,7 +802,10 @@ class SlapOSTestCaseMixin(testSlapOSMixin): ...@@ -733,7 +802,10 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
partition.markBusy() partition.markBusy()
# create fake open order, to bypass Service_getSubscriptionStatus # create fake open order, to bypass Service_getSubscriptionStatus
for item in [instance_tree.getSuccessorValue(), partition.getParentValue()]: subscrible_item_list = [instance_tree]
if partition is not None:
subscrible_item_list.append(partition.getParentValue())
for item in subscrible_item_list:
open_order = self.portal.open_sale_order_module.newContent( open_order = self.portal.open_sale_order_module.newContent(
portal_type="Open Sale Order", portal_type="Open Sale Order",
ledger="automated", ledger="automated",
......
# Copyright (c) 2002-2012 Nexedi SA and Contributors. All Rights Reserved. # Copyright (c) 2002-2012 Nexedi SA and Contributors. All Rights Reserved.
import transaction import transaction
from erp5.component.test.SlapOSTestCaseMixin import SlapOSTestCaseMixin from erp5.component.test.SlapOSTestCaseMixin import SlapOSTestCaseMixin, TemporaryAlarmScript
from zExceptions import Unauthorized from zExceptions import Unauthorized
from DateTime import DateTime from DateTime import DateTime
from erp5.component.module.DateUtils import addToDate from erp5.component.module.DateUtils import addToDate
class TestSlapOSCoreSlapOSAssertInstanceTreeSuccessorAlarm(
SlapOSTestCaseMixin):
def afterSetUp(self):
SlapOSTestCaseMixin.afterSetUp(self)
self.project = self.addProject()
self._makeTree(self.project)
def test_InstanceTree_assertSuccessor(self):
self.software_instance.rename(new_name=self.generateNewSoftwareTitle())
self.tic()
# check that no interaction has recreated the instance
self.assertFalse(self.instance_tree.getTitle() in
self.instance_tree.getSuccessorTitleList())
self.instance_tree.InstanceTree_assertSuccessor()
self.assertTrue(self.instance_tree.getTitle() in
self.instance_tree.getSuccessorTitleList())
def test_InstanceTree_assertSuccessor_stop_requested(self):
self.software_instance.rename(new_name=self.generateNewSoftwareTitle())
self.portal.portal_workflow._jumpToStateFor(self.instance_tree,
'stop_requested')
self.tic()
# check that no interaction has recreated the instance
self.assertFalse(self.instance_tree.getTitle() in
self.instance_tree.getSuccessorTitleList())
self.instance_tree.InstanceTree_assertSuccessor()
self.assertTrue(self.instance_tree.getTitle() in
self.instance_tree.getSuccessorTitleList())
def test_InstanceTree_assertSuccessor_destroy_requested(self):
self.software_instance.rename(new_name=self.generateNewSoftwareTitle())
self.portal.portal_workflow._jumpToStateFor(self.instance_tree,
'destroy_requested')
self.tic()
# check that no interaction has recreated the instance
self.assertFalse(self.instance_tree.getTitle() in
self.instance_tree.getSuccessorTitleList())
self.instance_tree.InstanceTree_assertSuccessor()
self.assertFalse(self.instance_tree.getTitle() in
self.instance_tree.getSuccessorTitleList())
def test_InstanceTree_assertSuccessor_archived(self):
self.software_instance.rename(new_name=self.generateNewSoftwareTitle())
self.instance_tree.archive()
self.tic()
# check that no interaction has recreated the instance
self.assertFalse(self.instance_tree.getTitle() in
self.instance_tree.getSuccessorTitleList())
self.instance_tree.InstanceTree_assertSuccessor()
self.assertFalse(self.instance_tree.getTitle() in
self.instance_tree.getSuccessorTitleList())
class TestSlapOSCoreSlapOSAssertInstanceTreeSuccessorAlarm(SlapOSTestCaseMixin):
#################################################################
# slapos_assert_instance_tree_successor
#################################################################
def test_InstanceTree_assertSuccessor_alarm_orphaned(self): def test_InstanceTree_assertSuccessor_alarm_orphaned(self):
instance_tree = self.portal.instance_tree_module.newContent( instance_tree = self.portal.instance_tree_module.newContent(
portal_type='Instance Tree' portal_type='Instance Tree'
...@@ -79,661 +23,815 @@ class TestSlapOSCoreSlapOSAssertInstanceTreeSuccessorAlarm( ...@@ -79,661 +23,815 @@ class TestSlapOSCoreSlapOSAssertInstanceTreeSuccessorAlarm(
) )
def test_InstanceTree_assertSuccessor_alarm_renamed(self): def test_InstanceTree_assertSuccessor_alarm_renamed(self):
self.software_instance.edit(title=self.generateNewSoftwareTitle()) instance_tree = self.addInstanceTree()
instance_tree.getSuccessorValue().edit(title=self.generateNewSoftwareTitle())
self._test_alarm( self._test_alarm(
self.portal.portal_alarms.slapos_assert_instance_tree_successor, self.portal.portal_alarms.slapos_assert_instance_tree_successor,
self.instance_tree, instance_tree,
'InstanceTree_assertSuccessor' 'InstanceTree_assertSuccessor'
) )
def test_InstanceTree_assertSuccessor_alarm_not_renamed(self): def test_InstanceTree_assertSuccessor_alarm_not_renamed(self):
self._test_alarm_not_visited( self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_assert_instance_tree_successor, self.portal.portal_alarms.slapos_assert_instance_tree_successor,
self.instance_tree, self.addInstanceTree(),
'InstanceTree_assertSuccessor' 'InstanceTree_assertSuccessor'
) )
#################################################################
# InstanceTree_assertSuccessor
#################################################################
def test_InstanceTree_assertSuccessor_script_renamed(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
software_instance.edit(title=self.generateNewSoftwareTitle())
self.tic()
class TestSlapOSFreeComputePartitionAlarm(SlapOSTestCaseMixin): # check that no interaction has recreated the instance
self.assertNotEqual(instance_tree.getTitle(), software_instance.getTitle())
self.assertFalse(instance_tree.getTitle() in
instance_tree.getSuccessorTitleList())
def afterSetUp(self): with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
SlapOSTestCaseMixin.afterSetUp(self) instance_tree.InstanceTree_assertSuccessor()
self.project = self.addProject()
self._makeTree(self.project)
def test_SoftwareInstance_tryToUnallocatePartition(self): self.assertNotEqual(instance_tree.getTitle(), software_instance.getTitle())
self._makeComputeNode(self.project) self.assertTrue(instance_tree.getTitle() in
self.software_instance.setAggregate(self.partition.getRelativeUrl()) instance_tree.getSuccessorTitleList())
self.partition.markBusy()
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
'destroy_requested')
self.tic()
self.software_instance.SoftwareInstance_tryToUnallocatePartition() def test_InstanceTree_assertSuccessor_script_renamedAndStopped(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
software_instance.edit(title=self.generateNewSoftwareTitle())
self.portal.portal_workflow._jumpToStateFor(instance_tree,
'stop_requested')
self.tic() self.tic()
self.assertEqual(None, self.software_instance.getAggregate())
self.assertEqual('free', self.partition.getSlapState())
def test_SoftwareInstance_tryToUnallocatePartition_concurrency(self): # check that no interaction has recreated the instance
self._makeComputeNode(self.project) self.assertNotEqual(instance_tree.getTitle(), software_instance.getTitle())
self.software_instance.setAggregate(self.partition.getRelativeUrl()) self.assertFalse(instance_tree.getTitle() in
self.partition.markBusy() instance_tree.getSuccessorTitleList())
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
instance_tree.InstanceTree_assertSuccessor()
self.assertNotEqual(instance_tree.getTitle(), software_instance.getTitle())
self.assertTrue(instance_tree.getTitle() in
instance_tree.getSuccessorTitleList())
def test_InstanceTree_assertSuccessor_script_renamedAndDestroyed(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
software_instance.edit(title=self.generateNewSoftwareTitle())
self.portal.portal_workflow._jumpToStateFor(instance_tree,
'destroy_requested') 'destroy_requested')
self.tic() self.tic()
self.partition.activate(tag="allocate_%s" % self.partition.getRelativeUrl()\ # check that no interaction has recreated the instance
).getId() self.assertNotEqual(instance_tree.getTitle(), software_instance.getTitle())
transaction.commit() self.assertFalse(instance_tree.getTitle() in
self.software_instance.SoftwareInstance_tryToUnallocatePartition() instance_tree.getSuccessorTitleList())
with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
instance_tree.InstanceTree_assertSuccessor()
self.assertNotEqual(instance_tree.getTitle(), software_instance.getTitle())
self.assertFalse(instance_tree.getTitle() in
instance_tree.getSuccessorTitleList())
def test_InstanceTree_assertSuccessor_script_archived(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
software_instance.edit(title=self.generateNewSoftwareTitle())
instance_tree.archive()
self.tic() self.tic()
self.assertEqual(self.partition.getRelativeUrl(),
self.software_instance.getAggregate())
self.assertEqual('busy', self.partition.getSlapState())
def test_SoftwareInstance_tryToUnallocatePartition_twoInstances(self): # check that no interaction has recreated the instance
software_instance = self.portal.software_instance_module\ self.assertNotEqual(instance_tree.getTitle(), software_instance.getTitle())
.template_software_instance.Base_createCloneDocument(batch_mode=1) self.assertFalse(instance_tree.getTitle() in
instance_tree.getSuccessorTitleList())
with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
instance_tree.InstanceTree_assertSuccessor()
self._makeComputeNode(self.project) self.assertNotEqual(instance_tree.getTitle(), software_instance.getTitle())
self.software_instance.setAggregate(self.partition.getRelativeUrl()) self.assertFalse(instance_tree.getTitle() in
software_instance.setAggregate(self.partition.getRelativeUrl()) instance_tree.getSuccessorTitleList())
self.partition.markBusy()
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
class TestSlapOSFreeComputePartitionAlarm(SlapOSTestCaseMixin):
#################################################################
# slapos_free_compute_partition
#################################################################
def test_SoftwareInstance_tryToUnallocatePartition_alarm_allocated(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
_, partition = self.addComputeNodeAndPartition(project=instance_tree.getFollowUpValue())
software_instance.setAggregateValue(partition)
partition.markBusy()
self.portal.portal_workflow._jumpToStateFor(software_instance,
'destroy_requested') 'destroy_requested')
self.tic() # invalidate transition triggers the alarm
self.portal.portal_workflow._jumpToStateFor(software_instance,
'invalidated')
self.software_instance.SoftwareInstance_tryToUnallocatePartition()
self.tic() self.tic()
self.assertEqual(None, self.software_instance.getAggregate()) self._test_alarm(
self.assertEqual('busy', self.partition.getSlapState()) self.portal.portal_alarms.slapos_free_compute_partition,
self.assertEqual(self.partition.getRelativeUrl(), software_instance.getAggregate()) software_instance,
'SoftwareInstance_tryToUnallocatePartition'
)
def test_alarm_allocated(self): def test_SoftwareInstance_tryToUnallocatePartition_alarm_sharedAndAllocated(self):
self._makeComputeNode(self.project) instance_tree = self.addInstanceTree(shared=True)
self.software_instance.setAggregate(self.partition.getRelativeUrl()) software_instance = instance_tree.getSuccessorValue()
self.partition.markBusy() _, partition = self.addComputeNodeAndPartition(project=instance_tree.getFollowUpValue())
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
software_instance.setAggregateValue(partition)
partition.markBusy()
self.portal.portal_workflow._jumpToStateFor(software_instance,
'destroy_requested') 'destroy_requested')
self.software_instance.invalidate() # invalidate transition triggers the alarm
self.portal.portal_workflow._jumpToStateFor(software_instance,
'invalidated')
self.tic()
self._test_alarm( self._test_alarm(
self.portal.portal_alarms.slapos_free_compute_partition, self.portal.portal_alarms.slapos_free_compute_partition,
self.software_instance, software_instance,
'SoftwareInstance_tryToUnallocatePartition' 'SoftwareInstance_tryToUnallocatePartition'
) )
def test_alarm_unallocated(self): def test_SoftwareInstance_tryToUnallocatePartition_alarm_unallocated(self):
self._makeComputeNode(self.project) instance_tree = self.addInstanceTree()
self.partition.markBusy() software_instance = instance_tree.getSuccessorValue()
self.portal.portal_workflow._jumpToStateFor(self.software_instance, _, partition = self.addComputeNodeAndPartition(project=instance_tree.getFollowUpValue())
partition.markBusy()
self.portal.portal_workflow._jumpToStateFor(software_instance,
'destroy_requested') 'destroy_requested')
self.software_instance.invalidate() # invalidate transition triggers the alarm
self.portal.portal_workflow._jumpToStateFor(software_instance,
'invalidated')
self.tic()
self._test_alarm_not_visited( self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_free_compute_partition, self.portal.portal_alarms.slapos_free_compute_partition,
self.software_instance, software_instance,
'SoftwareInstance_tryToUnallocatePartition' 'SoftwareInstance_tryToUnallocatePartition'
) )
def test_alarm_validated(self): def test_SoftwareInstance_tryToUnallocatePartition_alarm_allocatedAndValidated(self):
self._makeComputeNode(self.project) instance_tree = self.addInstanceTree()
self.software_instance.setAggregate(self.partition.getRelativeUrl()) software_instance = instance_tree.getSuccessorValue()
self.partition.markBusy() _, partition = self.addComputeNodeAndPartition(project=instance_tree.getFollowUpValue())
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
software_instance.setAggregateValue(partition)
partition.markBusy()
self.portal.portal_workflow._jumpToStateFor(software_instance,
'destroy_requested') 'destroy_requested')
self.tic()
self._test_alarm_not_visited( self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_free_compute_partition, self.portal.portal_alarms.slapos_free_compute_partition,
self.software_instance, software_instance,
'SoftwareInstance_tryToUnallocatePartition' 'SoftwareInstance_tryToUnallocatePartition'
) )
def test_alarm_start_requested(self): def test_SoftwareInstance_tryToUnallocatePartition_alarm_allocatedAndStarted(self):
self._makeComputeNode(self.project) instance_tree = self.addInstanceTree()
self.software_instance.setAggregate(self.partition.getRelativeUrl()) software_instance = instance_tree.getSuccessorValue()
self.partition.markBusy() _, partition = self.addComputeNodeAndPartition(project=instance_tree.getFollowUpValue())
software_instance.setAggregateValue(partition)
partition.markBusy()
self.tic()
self._test_alarm_not_visited( self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_free_compute_partition, self.portal.portal_alarms.slapos_free_compute_partition,
self.software_instance, software_instance,
'SoftwareInstance_tryToUnallocatePartition' 'SoftwareInstance_tryToUnallocatePartition'
) )
class TestSlapOSFreeComputePartitionAlarmWithSlave(SlapOSTestCaseMixin): #################################################################
def afterSetUp(self): # SoftwareInstance_tryToUnallocatePartition
SlapOSTestCaseMixin.afterSetUp(self) #################################################################
self.project = self.addProject() def test_SoftwareInstance_tryToUnallocatePartition_script_allocated(self):
self._makeTree(self.project, instance_tree = self.addInstanceTree()
requested_template_id='template_slave_instance') software_instance = instance_tree.getSuccessorValue()
_, partition = self.addComputeNodeAndPartition(project=instance_tree.getFollowUpValue())
def test_SoftwareInstance_tryToUnallocatePartition(self):
self._makeComputeNode(self.project) software_instance.setAggregateValue(partition)
self.software_instance.setAggregate(self.partition.getRelativeUrl()) partition.markBusy()
self.partition.markBusy() self.portal.portal_workflow._jumpToStateFor(software_instance,
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
'destroy_requested') 'destroy_requested')
self.tic() self.tic()
self.software_instance.SoftwareInstance_tryToUnallocatePartition() software_instance.SoftwareInstance_tryToUnallocatePartition()
self.tic() self.assertEqual(None, software_instance.getAggregate())
self.assertEqual(None, self.software_instance.getAggregate()) self.assertEqual('free', partition.getSlapState())
self.assertEqual('free', self.partition.getSlapState())
def test_SoftwareInstance_tryToUnallocatePartition_nonDestroyed(self): def test_SoftwareInstance_tryToUnallocatePartition_script_sharedAndAllocated(self):
self._makeComputeNode(self.project) instance_tree = self.addInstanceTree(shared=True)
self.software_instance.setAggregate(self.partition.getRelativeUrl()) software_instance = instance_tree.getSuccessorValue()
self.partition.markBusy() _, partition = self.addComputeNodeAndPartition(project=instance_tree.getFollowUpValue())
self.tic()
self.software_instance.SoftwareInstance_tryToUnallocatePartition() software_instance.setAggregateValue(partition)
partition.markBusy()
self.portal.portal_workflow._jumpToStateFor(software_instance,
'destroy_requested')
self.tic() self.tic()
self.assertEqual(self.partition.getRelativeUrl(),
self.software_instance.getAggregate())
self.assertEqual('busy', self.partition.getSlapState())
class TestSlapOSGarbageCollectDestroyedRootTreeAlarm(SlapOSTestCaseMixin): software_instance.SoftwareInstance_tryToUnallocatePartition()
self.assertEqual(None, software_instance.getAggregate())
self.assertEqual('free', partition.getSlapState())
def afterSetUp(self): def test_SoftwareInstance_tryToUnallocatePartition_script_concurrency(self):
SlapOSTestCaseMixin.afterSetUp(self) instance_tree = self.addInstanceTree()
self.project = self.addProject() software_instance = instance_tree.getSuccessorValue()
self._makeTree(self.project) _, partition = self.addComputeNodeAndPartition(project=instance_tree.getFollowUpValue())
def test_SoftwareInstance_tryToGarbageCollect(self): software_instance.setAggregateValue(partition)
self.instance_tree.archive() partition.markBusy()
self.portal.portal_workflow._jumpToStateFor(self.software_instance, self.portal.portal_workflow._jumpToStateFor(software_instance,
'destroy_requested')
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
'destroy_requested') 'destroy_requested')
self.tic() self.tic()
self.requested_software_instance.SoftwareInstance_tryToGarbageCollect() partition.activate(tag="allocate_%s" % partition.getRelativeUrl()\
self.tic() ).getId()
self.assertEqual('destroy_requested', transaction.commit()
self.requested_software_instance.getSlapState()) software_instance.SoftwareInstance_tryToUnallocatePartition()
self.assertEqual('validated', self.assertEqual(partition.getRelativeUrl(),
self.requested_software_instance.getValidationState()) software_instance.getAggregate())
self.assertEqual('busy', partition.getSlapState())
def test_SoftwareInstance_tryToUnallocatePartition_script_twoInstances(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
_, partition = self.addComputeNodeAndPartition(project=instance_tree.getFollowUpValue())
instance_tree2 = self.addInstanceTree(project=instance_tree.getFollowUpValue())
software_instance2 = instance_tree2.getSuccessorValue()
def test_SoftwareInstance_tryToGarbageCollect_not_destroy_requested(self):
self.requested_software_instance.SoftwareInstance_tryToGarbageCollect()
self.tic() self.tic()
self.assertEqual('start_requested',
self.requested_software_instance.getSlapState())
self.assertEqual('validated',
self.requested_software_instance.getValidationState())
def test_SoftwareInstance_tryToGarbageCollect_not_archived(self): try:
self.portal.portal_workflow._jumpToStateFor(self.software_instance, # Prevent calling interaction workflows
'destroy_requested') software_instance.setCategoryList(
self.portal.portal_workflow._jumpToStateFor(self.software_instance, software_instance.getCategoryList() + ['aggregate/%s' % partition.getRelativeUrl()]
'destroy_requested') )
software_instance2.setCategoryList(
software_instance2.getCategoryList() + ['aggregate/%s' % partition.getRelativeUrl()]
)
self.portal.portal_workflow._jumpToStateFor(partition,
'busy')
self.portal.portal_workflow._jumpToStateFor(software_instance,
'destroy_requested')
self.tic()
software_instance.SoftwareInstance_tryToUnallocatePartition()
self.assertEqual(None, software_instance.getAggregate())
self.assertEqual('busy', partition.getSlapState())
self.assertEqual(partition.getRelativeUrl(), software_instance2.getAggregate())
except:
# 2 instances linked to a partition crashes _fillComputeNodeInformationCache
# activity. Clean up to not impact the other tests
software_instance2.setAggregate(None)
raise
finally:
software_instance2.setAggregate(None)
self.tic() self.tic()
self.requested_software_instance.SoftwareInstance_tryToGarbageCollect() def test_SoftwareInstance_tryToUnallocatePartition_script_notDestroyed(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
_, partition = self.addComputeNodeAndPartition(project=instance_tree.getFollowUpValue())
software_instance.setAggregateValue(partition)
partition.markBusy()
self.tic() self.tic()
self.assertEqual('start_requested',
self.requested_software_instance.getSlapState())
self.assertEqual('validated',
self.requested_software_instance.getValidationState())
def test_SoftwareInstance_tryToGarbageCollect_only_instance_destroy_requested(self): software_instance.SoftwareInstance_tryToUnallocatePartition()
self.portal.portal_workflow._jumpToStateFor(self.software_instance, self.assertEqual(partition.getRelativeUrl(), software_instance.getAggregate())
self.assertEqual('busy', partition.getSlapState())
class TestSlapOSGarbageCollectDestroyedRootTreeAlarm(SlapOSTestCaseMixin):
#################################################################
# slapos_garbage_collect_destroyed_root_tree
#################################################################
def test_SoftwareInstance_tryToGarbageCollect_alarm_archived(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
instance_tree.archive()
self._test_alarm(
self.portal.portal_alarms.slapos_garbage_collect_destroyed_root_tree,
software_instance,
'SoftwareInstance_tryToGarbageCollect'
)
def test_SoftwareInstance_tryToGarbageCollect_alarm_sharedAndArchived(self):
instance_tree = self.addInstanceTree(shared=True)
software_instance = instance_tree.getSuccessorValue()
instance_tree.archive()
self._test_alarm(
self.portal.portal_alarms.slapos_garbage_collect_destroyed_root_tree,
software_instance,
'SoftwareInstance_tryToGarbageCollect'
)
def test_SoftwareInstance_tryToGarbageCollect_alarm_invalidated(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
instance_tree.archive()
software_instance.invalidate()
self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_garbage_collect_destroyed_root_tree,
software_instance,
'SoftwareInstance_tryToGarbageCollect'
)
def test_SoftwareInstance_tryToGarbageCollect_alarm_notArchived(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_garbage_collect_destroyed_root_tree,
software_instance,
'SoftwareInstance_tryToGarbageCollect'
)
#################################################################
# SoftwareInstance_tryToGarbageCollect
#################################################################
def test_SoftwareInstance_tryToGarbageCollect_script_destroyed(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
instance_tree.archive()
self.portal.portal_workflow._jumpToStateFor(instance_tree,
'destroy_requested') 'destroy_requested')
self.assertEqual('validated',
software_instance.getValidationState())
self.tic() self.tic()
software_instance.SoftwareInstance_tryToGarbageCollect()
self.assertEqual('destroy_requested',
software_instance.getSlapState())
self.assertEqual('validated',
software_instance.getValidationState())
def test_SoftwareInstance_tryToGarbageCollect_script_archived(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
instance_tree.archive()
self.requested_software_instance.SoftwareInstance_tryToGarbageCollect()
self.tic() self.tic()
software_instance.SoftwareInstance_tryToGarbageCollect()
self.assertEqual('start_requested', self.assertEqual('start_requested',
self.requested_software_instance.getSlapState()) software_instance.getSlapState())
self.assertEqual('validated', self.assertEqual('validated',
self.requested_software_instance.getValidationState()) software_instance.getValidationState())
def test_SoftwareInstance_tryToGarbageCollect_unlinked_successor(self): def test_SoftwareInstance_tryToGarbageCollect_script_notArchived(self):
self.requested_software_instance.edit(successor_list=[]) instance_tree = self.addInstanceTree()
self.instance_tree.archive() software_instance = instance_tree.getSuccessorValue()
self.portal.portal_workflow._jumpToStateFor(self.instance_tree, self.portal.portal_workflow._jumpToStateFor(instance_tree,
'destroy_requested')
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
'destroy_requested') 'destroy_requested')
self.tic()
self.requested_software_instance.SoftwareInstance_tryToGarbageCollect()
self.tic() self.tic()
software_instance.SoftwareInstance_tryToGarbageCollect()
self.assertEqual('destroy_requested', self.assertEqual('start_requested',
self.requested_software_instance.getSlapState()) software_instance.getSlapState())
self.assertEqual('validated', self.assertEqual('validated',
self.requested_software_instance.getValidationState()) software_instance.getValidationState())
def test_SoftwareInstance_tryToGarbageCollect_destroy_unlinked_with_child(self): def test_SoftwareInstance_tryToGarbageCollect_script_unlinkedSuccessor(self):
instance_kw = dict(software_release=self.generateNewSoftwareReleaseUrl(), instance_tree = self.addInstanceTree()
software_type=self.generateNewSoftwareType(), software_instance = instance_tree.getSuccessorValue()
instance_xml=self.generateSafeXml(),
sla_xml=self.generateSafeXml(),
shared=False,
software_title='Sub Instance',
state='started'
)
self.requested_software_instance.requestInstance(**instance_kw)
sub_instance = self.requested_software_instance.getSuccessorValue()
self.assertNotEqual(sub_instance, None)
self.requested_software_instance.edit(successor_list=[]) instance_tree.edit(successor_list=[])
self.instance_tree.archive() instance_tree.archive()
self.portal.portal_workflow._jumpToStateFor(self.instance_tree, self.portal.portal_workflow._jumpToStateFor(instance_tree,
'destroy_requested')
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
'destroy_requested') 'destroy_requested')
self.tic()
self.requested_software_instance.SoftwareInstance_tryToGarbageCollect()
self.tic() self.tic()
software_instance.SoftwareInstance_tryToGarbageCollect()
self.assertEqual('destroy_requested', self.assertEqual('destroy_requested',
self.requested_software_instance.getSlapState()) software_instance.getSlapState())
self.assertEqual('validated', self.assertEqual('validated',
self.requested_software_instance.getValidationState()) software_instance.getValidationState())
self.assertEqual(self.requested_software_instance.getSuccessorValue(),
None)
self.assertEqual(sub_instance.getSlapState(), 'start_requested')
sub_instance.SoftwareInstance_tryToGarbageCollect()
self.tic()
self.assertEqual(sub_instance.getSlapState(), 'destroy_requested')
self.assertEqual(sub_instance.getValidationState(), 'validated')
def test_alarm(self): class TestSlapOSUpdateComputeNodeCapacityScopeAlarm(SlapOSTestCaseMixin):
self.instance_tree.archive() #################################################################
# slapos_update_compute_node_capacity_scope
#################################################################
def test_ComputeNode_checkAndUpdateCapacityScope_alarm_open(self):
compute_node, _ = self.addComputeNodeAndPartition()
compute_node.edit(
allocation_scope='open',
)
self._test_alarm( self._test_alarm(
self.portal.portal_alarms.slapos_garbage_collect_destroyed_root_tree, self.portal.portal_alarms.slapos_update_compute_node_capacity_scope,
self.software_instance, compute_node,
'SoftwareInstance_tryToGarbageCollect' 'ComputeNode_checkAndUpdateCapacityScope'
) )
def test_alarm_invalidated(self): def test_ComputeNode_checkAndUpdateCapacityScope_alarm_close(self):
self.instance_tree.archive() compute_node, _ = self.addComputeNodeAndPartition()
self.software_instance.invalidate() compute_node.edit(
allocation_scope='close',
)
self._test_alarm_not_visited( self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_garbage_collect_destroyed_root_tree, self.portal.portal_alarms.slapos_update_compute_node_capacity_scope,
self.software_instance, compute_node,
'SoftwareInstance_tryToGarbageCollect' 'ComputeNode_checkAndUpdateCapacityScope'
) )
def test_alarm_not_archived(self): def test_ComputeNode_checkAndUpdateCapacityScope_alarm_invalidated(self):
compute_node, _ = self.addComputeNodeAndPartition()
compute_node.invalidate()
compute_node.edit(
allocation_scope='open',
)
self._test_alarm_not_visited( self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_garbage_collect_destroyed_root_tree, self.portal.portal_alarms.slapos_update_compute_node_capacity_scope,
self.software_instance, compute_node,
'SoftwareInstance_tryToGarbageCollect' 'ComputeNode_checkAndUpdateCapacityScope'
) )
#################################################################
# ComputeNode_checkAndUpdateCapacityScope
#################################################################
def test_ComputeNode_checkAndUpdateCapacityScope_script_open(self):
compute_node, _ = self.addComputeNodeAndPartition()
compute_node.edit(allocation_scope='open')
compute_node.edit(capacity_scope='open')
compute_node.setAccessStatus("#access ok")
compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('open', compute_node.getCapacityScope())
class TestSlapOSUpdateComputeNodeCapacityScopeAlarm(SlapOSTestCaseMixin): def addComputerModel(self, capacity_quantity=None):
return self.portal.computer_model_module.newContent(
def afterSetUp(self): portal_type="Computer Model",
SlapOSTestCaseMixin.afterSetUp(self) reference='TESTCM-%s' % self.generateNewId(),
self.project = self.addProject() capacity_quantity=capacity_quantity
self.compute_node = self.portal.compute_node_module.template_compute_node\
.Base_createCloneDocument(batch_mode=1)
self.compute_node.edit(
allocation_scope='open',
reference='TESTC-%s' % self.generateNewId(),
follow_up_value=self.project
) )
self.compute_node.edit(capacity_scope='open')
self.compute_node.validate()
self.compute_node.setAccessStatus("#access ok")
transaction.commit()
def test_ComputeNode_checkAndUpdateCapacityScope(self):
self.compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('open', self.compute_node.getCapacityScope())
def _newComputerModel(self, quantity=None): def test_ComputeNode_checkAndUpdateCapacityScope_script_model(self):
computer_model = self.portal.computer_model_module.\ compute_node, _ = self.addComputeNodeAndPartition()
template_computer_model.Base_createCloneDocument(batch_mode=1) compute_node.edit(allocation_scope='open')
computer_model.edit(capacity_quantity=quantity, compute_node.edit(capacity_scope='open')
reference='TESTCM-%s' % self.generateNewId(), compute_node.setAccessStatus("#access ok")
)
return computer_model
def _addPartitionToComputeNode(self): computer_model = self.addComputerModel(9999)
partition = self.compute_node.newContent(portal_type='Compute Partition', compute_node.edit(specialise_value=computer_model, capacity_quantity=None)
reference='part1')
partition.markFree()
partition.markBusy()
partition.validate()
self.software_instance.setAggregate(partition.getRelativeUrl())
self.tic()
def test_ComputeNode_checkAndUpdateCapacityScope_model(self): compute_node.ComputeNode_checkAndUpdateCapacityScope()
computer_model = self._newComputerModel(9999) self.assertEqual('open', compute_node.getCapacityScope())
self.assertEqual(computer_model.getCapacityQuantity(),
compute_node.getCapacityQuantity())
self.compute_node.edit(specialise_value=computer_model, def test_ComputeNode_checkAndUpdateCapacityScope_script_modelNoCapacity(self):
capacity_quantity=None) compute_node, partition = self.addComputeNodeAndPartition()
transaction.commit() compute_node.edit(allocation_scope='open')
compute_node.edit(capacity_scope='open')
compute_node.setAccessStatus("#access ok")
self.compute_node.ComputeNode_checkAndUpdateCapacityScope() computer_model = self.addComputerModel(1)
self.assertEqual('open', self.compute_node.getCapacityScope()) compute_node.edit(specialise_value=computer_model, capacity_quantity=None)
self.assertEqual(computer_model.getCapacityQuantity(),
self.compute_node.getCapacityQuantity())
def test_ComputeNode_checkAndUpdateCapacityScope_model_no_capacity(self): instance_tree = self.addInstanceTree()
self._makeTree(self.project) software_instance = instance_tree.getSuccessorValue()
software_instance.setAggregateValue(partition)
partition.markBusy()
computer_model = self._newComputerModel(1) self.tic()
self.compute_node.edit(specialise_value=computer_model,
capacity_quantity=None)
self._addPartitionToComputeNode() compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.compute_node.ComputeNode_checkAndUpdateCapacityScope() self.assertEqual('close', compute_node.getCapacityScope())
self.assertEqual('close', self.compute_node.getCapacityScope())
self.assertEqual('Compute Node capacity limit exceeded', self.assertEqual('Compute Node capacity limit exceeded',
self.compute_node.workflow_history['edit_workflow'][-1]['comment']) compute_node.workflow_history['edit_workflow'][-1]['comment'])
self.assertEqual(computer_model.getCapacityQuantity(), self.assertEqual(computer_model.getCapacityQuantity(),
self.compute_node.getCapacityQuantity()) compute_node.getCapacityQuantity())
def test_ComputeNode_checkAndUpdateCapacityScope_model_has_capacity(self): def test_ComputeNode_checkAndUpdateCapacityScope_script_modelHasCapacity(self):
# If capacity is set on compute_node, model value is ignored. # If capacity is set on compute_node, model value is ignored.
self._makeTree(self.project) compute_node, _ = self.addComputeNodeAndPartition()
compute_node.edit(allocation_scope='open')
compute_node.edit(capacity_scope='open')
compute_node.setAccessStatus("#access ok")
computer_model = self.addComputerModel(1)
compute_node.edit(specialise_value=computer_model, capacity_quantity=2)
computer_model = self._newComputerModel(1) self.tic()
self.compute_node.edit(specialise_value=computer_model,
capacity_quantity=2)
self._addPartitionToComputeNode() compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.compute_node.ComputeNode_checkAndUpdateCapacityScope() self.assertEqual('open', compute_node.getCapacityScope())
self.assertEqual('open', self.compute_node.getCapacityScope()) self.assertEqual(2,
compute_node.getCapacityQuantity())
self.assertNotEqual(computer_model.getCapacityQuantity(),
self.compute_node.getCapacityQuantity())
def test_ComputeNode_checkAndUpdateCapacityScope_with_old_access(self): def test_ComputeNode_checkAndUpdateCapacityScope_script_withOldAccess(self):
compute_node, _ = self.addComputeNodeAndPartition()
compute_node.edit(allocation_scope='open')
compute_node.edit(capacity_scope='open')
try: try:
self.pinDateTime(addToDate(DateTime(),to_add={'minute': -11})) self.pinDateTime(addToDate(DateTime(),to_add={'minute': -11}))
self.compute_node.setAccessStatus("#access ok") compute_node.setAccessStatus("#access ok")
finally: finally:
self.unpinDateTime() self.unpinDateTime()
self.compute_node.ComputeNode_checkAndUpdateCapacityScope() compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('close', self.compute_node.getCapacityScope()) self.assertEqual('close', compute_node.getCapacityScope())
self.assertEqual("Compute Node didn't contact for more than 10 minutes", self.assertEqual("Compute Node didn't contact for more than 10 minutes",
self.compute_node.workflow_history['edit_workflow'][-1]['comment']) compute_node.workflow_history['edit_workflow'][-1]['comment'])
def test_ComputeNode_checkAndUpdateCapacityScope_no_capacity_quantity(self): def test_ComputeNode_checkAndUpdateCapacityScope_script_noCapacityQuantity(self):
self._makeTree(self.project) compute_node, partition = self.addComputeNodeAndPartition()
self.compute_node.edit(capacity_quantity=1) compute_node.edit(allocation_scope='open')
self._addPartitionToComputeNode() compute_node.edit(capacity_scope='open')
self.compute_node.ComputeNode_checkAndUpdateCapacityScope() compute_node.setAccessStatus("#access ok")
self.assertEqual('close', self.compute_node.getCapacityScope()) compute_node.edit(capacity_quantity=1)
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
software_instance.setAggregateValue(partition)
partition.markBusy()
self.tic()
compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('close', compute_node.getCapacityScope())
self.assertEqual('Compute Node capacity limit exceeded', self.assertEqual('Compute Node capacity limit exceeded',
self.compute_node.workflow_history['edit_workflow'][-1]['comment']) compute_node.workflow_history['edit_workflow'][-1]['comment'])
def test_ComputeNode_checkAndUpdateCapacityScope_no_access(self): def test_ComputeNode_checkAndUpdateCapacityScope_script_noAccess(self):
self.compute_node.edit(reference='TESTC-%s' % self.generateNewId()) compute_node, _ = self.addComputeNodeAndPartition()
self.compute_node.ComputeNode_checkAndUpdateCapacityScope() compute_node.edit(allocation_scope='open')
self.assertEqual('close', self.compute_node.getCapacityScope()) compute_node.edit(capacity_scope='open')
compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('close', compute_node.getCapacityScope())
self.assertEqual("Compute Node didn't contact the server", self.assertEqual("Compute Node didn't contact the server",
self.compute_node.workflow_history['edit_workflow'][-1]['comment']) compute_node.workflow_history['edit_workflow'][-1]['comment'])
def test_ComputeNode_checkAndUpdateCapacityScope_close(self): def test_ComputeNode_checkAndUpdateCapacityScope_script_capacityClose(self):
self.compute_node.edit(capacity_scope='close') compute_node, _ = self.addComputeNodeAndPartition()
self.compute_node.ComputeNode_checkAndUpdateCapacityScope() compute_node.edit(allocation_scope='open')
self.assertEqual('open', self.compute_node.getCapacityScope()) compute_node.setAccessStatus("#access ok")
compute_node.edit(capacity_scope='close')
def test_ComputeNode_checkAndUpdateCapacityScope_with_error(self): compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.compute_node.setAccessStatus('#error not ok') self.assertEqual('open', compute_node.getCapacityScope())
self.compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('close', self.compute_node.getCapacityScope())
self.assertEqual("Compute Node reported an error",
self.compute_node.workflow_history['edit_workflow'][-1]['comment'])
def test_alarm(self): def test_ComputeNode_checkAndUpdateCapacityScope_script_withError(self):
self._test_alarm( compute_node, _ = self.addComputeNodeAndPartition()
self.portal.portal_alarms.slapos_update_compute_node_capacity_scope, compute_node.edit(allocation_scope='open')
self.compute_node, compute_node.edit(capacity_scope='open')
'ComputeNode_checkAndUpdateCapacityScope' compute_node.setAccessStatus('#error not ok')
)
def test_alarm_non_public(self): compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.compute_node.edit(allocation_scope='close') self.assertEqual('close', compute_node.getCapacityScope())
self._test_alarm_not_visited( self.assertEqual("Compute Node reported an error",
self.portal.portal_alarms.slapos_update_compute_node_capacity_scope, compute_node.workflow_history['edit_workflow'][-1]['comment'])
self.compute_node,
'ComputeNode_checkAndUpdateCapacityScope'
)
def test_alarm_invalidated(self):
self.compute_node.invalidate()
self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_update_compute_node_capacity_scope,
self.compute_node,
'ComputeNode_checkAndUpdateCapacityScope'
)
class TestSlapOSGarbageCollectStoppedRootTreeAlarm(SlapOSTestCaseMixin): class TestSlapOSGarbageCollectStoppedRootTreeAlarm(SlapOSTestCaseMixin):
#################################################################
def afterSetUp(self): # slapos_stop_collect_instance
SlapOSTestCaseMixin.afterSetUp(self) #################################################################
self.project = self.addProject() def test_SoftwareInstance_tryToStopCollect_alarm(self):
instance_tree = self.addInstanceTree()
def createInstance(self, project): software_instance = instance_tree.getSuccessorValue()
instance_tree = self.portal.instance_tree_module\ self._test_alarm(
.template_instance_tree.Base_createCloneDocument(batch_mode=1) self.portal.portal_alarms.slapos_stop_collect_instance,
instance_tree.edit( software_instance,
follow_up_value=project 'SoftwareInstance_tryToStopCollect'
)
instance_tree.validate()
instance_tree.edit(
title=self.generateNewSoftwareTitle(),
reference="TESTHS-%s" % self.generateNewId(),
)
request_kw = dict(
software_release=\
self.generateNewSoftwareReleaseUrl(),
software_type=self.generateNewSoftwareType(),
instance_xml=self.generateSafeXml(),
sla_xml=self.generateSafeXml(),
shared=False,
software_title=instance_tree.getTitle(),
state='started',
project_reference=project.getReference()
) )
instance_tree.requestStart(**request_kw)
instance_tree.requestInstance(**request_kw)
instance = instance_tree.getSuccessorValue() def test_SoftwareInstance_tryToStopCollect_alarm_invalidated(self):
self.tic() instance_tree = self.addInstanceTree()
return instance software_instance = instance_tree.getSuccessorValue()
software_instance.invalidate()
self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_stop_collect_instance,
software_instance,
'SoftwareInstance_tryToStopCollect'
)
#################################################################
# SoftwareInstance_tryToStopCollect
#################################################################
def test_SoftwareInstance_tryToStopCollect_REQUEST_disallowed(self): def test_SoftwareInstance_tryToStopCollect_REQUEST_disallowed(self):
self.assertRaises( self.assertRaises(
Unauthorized, Unauthorized,
self.portal.SoftwareInstance_tryToStopCollect, self.portal.SoftwareInstance_tryToStopCollect,
REQUEST={}) REQUEST={})
def test_SoftwareInstance_tryToStopCollect_started_instance(self): def test_SoftwareInstance_tryToStopCollect_script_startedInstance(self):
instance = self.createInstance(self.project) instance_tree = self.addInstanceTree()
instance_tree = instance.getSpecialiseValue() software_instance = instance_tree.getSuccessorValue()
self.portal.portal_workflow._jumpToStateFor(instance_tree, self.portal.portal_workflow._jumpToStateFor(instance_tree,
'stop_requested') 'stop_requested')
self.assertEqual('start_requested', instance.getSlapState()) self.assertEqual('start_requested', software_instance.getSlapState())
instance.SoftwareInstance_tryToStopCollect() software_instance.SoftwareInstance_tryToStopCollect()
self.assertEqual('stop_requested', instance.getSlapState()) self.assertEqual('stop_requested', software_instance.getSlapState())
def test_SoftwareInstance_tryToStopCollect_destroyed_instance(self): def test_SoftwareInstance_tryToStopCollect_script_destroyedInstance(self):
instance = self.createInstance(self.project) instance_tree = self.addInstanceTree()
instance_tree = instance.getSpecialiseValue() software_instance = instance_tree.getSuccessorValue()
self.portal.portal_workflow._jumpToStateFor(instance_tree, self.portal.portal_workflow._jumpToStateFor(instance_tree,
'stop_requested') 'stop_requested')
self.portal.portal_workflow._jumpToStateFor(instance, self.portal.portal_workflow._jumpToStateFor(software_instance,
'destroy_requested') 'destroy_requested')
instance.SoftwareInstance_tryToStopCollect() software_instance.SoftwareInstance_tryToStopCollect()
self.assertEqual('destroy_requested', instance.getSlapState()) self.assertEqual('destroy_requested', software_instance.getSlapState())
def test_SoftwareInstance_tryToStopCollect_started_subscription(self): def test_SoftwareInstance_tryToStopCollect_script_startedInstanceTree(self):
instance = self.createInstance(self.project) instance_tree = self.addInstanceTree()
instance_tree = instance.getSpecialiseValue() software_instance = instance_tree.getSuccessorValue()
self.assertEqual('start_requested', instance_tree.getSlapState()) self.assertEqual('start_requested', instance_tree.getSlapState())
self.assertEqual('start_requested', instance.getSlapState()) self.assertEqual('start_requested', software_instance.getSlapState())
software_instance.SoftwareInstance_tryToStopCollect()
self.assertEqual('start_requested', software_instance.getSlapState())
instance.SoftwareInstance_tryToStopCollect()
self.assertEqual('start_requested', instance.getSlapState())
def test_alarm(self): class TestSlapOSGarbageCollectNonAllocatedRootTreeAlarm(SlapOSTestCaseMixin):
instance = self.createInstance(self.project) #################################################################
# slapos_garbage_collect_non_allocated_root_tree
#################################################################
def test_tryToGarbageCollectNonAllocatedRootTree_alarm(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
self._test_alarm( self._test_alarm(
self.portal.portal_alarms.slapos_stop_collect_instance, self.portal.portal_alarms.slapos_garbage_collect_non_allocated_root_tree,
instance, software_instance,
'SoftwareInstance_tryToStopCollect' 'SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree'
) )
def test_alarm_invalidated(self): def test_tryToGarbageCollectNonAllocatedRootTree_alarm_invalidated(self):
instance = self.createInstance(self.project) instance_tree = self.addInstanceTree()
instance.invalidate() software_instance = instance_tree.getSuccessorValue()
software_instance.invalidate()
self._test_alarm_not_visited( self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_stop_collect_instance, self.portal.portal_alarms.slapos_garbage_collect_non_allocated_root_tree,
instance, software_instance,
'SoftwareInstance_tryToStopCollect' 'SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree'
)
class TestSlapOSGarbageCollectNonAllocatedRootTreeAlarm(SlapOSTestCaseMixin):
def afterSetUp(self):
SlapOSTestCaseMixin.afterSetUp(self)
self.project = self.addProject()
def createInstance(self, project):
instance_tree = self.portal.instance_tree_module\
.template_instance_tree.Base_createCloneDocument(batch_mode=1)
instance_tree.edit(
follow_up_value=project
)
instance_tree.validate()
instance_tree.edit(
title=self.generateNewSoftwareTitle(),
reference="TESTHS-%s" % self.generateNewId(),
)
request_kw = dict(
software_release=\
self.generateNewSoftwareReleaseUrl(),
software_type=self.generateNewSoftwareType(),
instance_xml=self.generateSafeXml(),
sla_xml=self.generateSafeXml(),
shared=False,
software_title=instance_tree.getTitle(),
state='started',
project_reference=project
) )
instance_tree.requestStart(**request_kw)
instance_tree.requestInstance(**request_kw)
instance = instance_tree.getSuccessorValue() def test_tryToGarbageCollectNonAllocatedRootTree_alarm_allocated(self):
return instance _, partition = self.addComputeNodeAndPartition()
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
software_instance.setAggregateValue(partition)
partition.markBusy()
def createComputePartition(self): self._test_alarm_not_visited(
compute_node = self.portal.compute_node_module\ self.portal.portal_alarms.slapos_garbage_collect_non_allocated_root_tree,
.template_compute_node.Base_createCloneDocument(batch_mode=1) software_instance,
compute_node.validate() 'SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree'
compute_node.edit(
title=self.generateNewSoftwareTitle(),
reference="TESTCOMP-%s" % self.generateNewId(),
) )
partition = compute_node.newContent(portal_type="Compute Partition")
return partition
def test_tryToGarbageCollect_REQUEST_disallowed(self): #################################################################
# SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree
#################################################################
def test_tryToGarbageCollectNonAllocatedRootTree_REQUEST_disallowed(self):
self.assertRaises( self.assertRaises(
Unauthorized, Unauthorized,
self.portal.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree, self.portal.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree,
REQUEST={}) REQUEST={})
def test_tryToGarbageCollect_invalidated_instance(self): def test_tryToGarbageCollectNonAllocatedRootTree_script_invalidatedInstance(self):
instance = self.createInstance(self.project) instance_tree = self.addInstanceTree()
instance.invalidate() software_instance = instance_tree.getSuccessorValue()
self.tic() software_instance.invalidate()
instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree() self.tic()
self.assertEqual('start_requested', instance.getSlapState()) software_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
instance_tree = instance.getSpecialiseValue() self.assertEqual('start_requested', software_instance.getSlapState())
self.assertEqual('start_requested', instance_tree.getSlapState()) self.assertEqual('start_requested', instance_tree.getSlapState())
def test_tryToGarbageCollect_destroyed_instance(self): def test_tryToGarbageCollectNonAllocatedRootTree_script_destroyedInstance(self):
instance = self.createInstance(self.project) instance_tree = self.addInstanceTree()
self.portal.portal_workflow._jumpToStateFor(instance, 'destroy_requested') software_instance = instance_tree.getSuccessorValue()
self.tic() self.portal.portal_workflow._jumpToStateFor(software_instance, 'destroy_requested')
instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree() self.tic()
self.assertEqual('destroy_requested', instance.getSlapState()) software_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
instance_tree = instance.getSpecialiseValue() self.assertEqual('destroy_requested', software_instance.getSlapState())
self.assertEqual('start_requested', instance_tree.getSlapState()) self.assertEqual('start_requested', instance_tree.getSlapState())
def test_tryToGarbageCollect_allocated_instance(self): def test_tryToGarbageCollectNonAllocatedRootTree_script_allocatedInstance(self):
instance = self.createInstance(self.project) _, partition = self.addComputeNodeAndPartition()
partition = self.createComputePartition() instance_tree = self.addInstanceTree()
instance.edit(aggregate_value=partition) software_instance = instance_tree.getSuccessorValue()
self.tic() software_instance.setAggregateValue(partition)
partition.markBusy()
instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree() self.tic()
self.assertEqual('start_requested', instance.getSlapState()) software_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
instance_tree = instance.getSpecialiseValue() self.assertEqual('start_requested', software_instance.getSlapState())
self.assertEqual('start_requested', instance_tree.getSlapState()) self.assertEqual('start_requested', instance_tree.getSlapState())
def test_tryToGarbageCollect_no_allocation_try_found(self): def test_tryToGarbageCollectNonAllocatedRootTree_script_noAllocationTryFound(self):
instance = self.createInstance(self.project) instance_tree = self.addInstanceTree()
self.tic() software_instance = instance_tree.getSuccessorValue()
instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree() self.tic()
self.assertEqual('start_requested', instance.getSlapState()) software_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
instance_tree = instance.getSpecialiseValue() self.assertEqual('start_requested', software_instance.getSlapState())
self.assertEqual('start_requested', instance_tree.getSlapState()) self.assertEqual('start_requested', instance_tree.getSlapState())
def test_tryToGarbageCollect_recent_allocation_try_found(self): def test_tryToGarbageCollectNonAllocatedRootTree_script_recentAllocationTryFound(self):
instance = self.createInstance(self.project) instance_tree = self.addInstanceTree()
self.tic() software_instance = instance_tree.getSuccessorValue()
instance.workflow_history['edit_workflow'].append({ software_instance.workflow_history['edit_workflow'] = [{
'comment':'Allocation failed: no free Compute Partition', 'comment':'Allocation failed: no free Compute Partition',
'error_message': '', 'error_message': '',
'actor': 'ERP5TypeTestCase', 'actor': 'ERP5TypeTestCase',
'slap_state': '', 'state': 'current',
'time': addToDate(DateTime(), to_add={'day': -2}), 'time': addToDate(DateTime(), to_add={'day': -2}),
'action': 'edit' 'action': 'edit'
}) }]
instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree() self.tic()
self.assertEqual('start_requested', instance.getSlapState()) software_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
instance_tree = instance.getSpecialiseValue() self.assertEqual('start_requested', software_instance.getSlapState())
self.assertEqual('start_requested', instance_tree.getSlapState()) self.assertEqual('start_requested', instance_tree.getSlapState())
def test_tryToGarbageCollectNonAllocatedRootTree_script_oldAllocationTryFound(self):
def test_tryToGarbageCollect_recent_allocation_try_found_allocation_disallowed(self): instance_tree = self.addInstanceTree()
instance = self.createInstance(self.project) software_instance = instance_tree.getSuccessorValue()
self.tic() self.tic()
instance.workflow_history['edit_workflow'].append({
software_instance.workflow_history['edit_workflow'] = [{
'comment':'Allocation failed: no free Compute Partition',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'state': 'current',
'time': addToDate(DateTime(), to_add={'day': -4}),
'action': 'edit'
}]
software_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
self.assertEqual('destroy_requested', instance_tree.getSlapState())
self.assertEqual('archived', instance_tree.getValidationState())
self.assertEqual('start_requested', software_instance.getSlapState())
def test_tryToGarbageCollectNonAllocatedRootTree_script_recentAllocationTryFoundAllocationDisallowed(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
software_instance.workflow_history['edit_workflow'] = [{
'comment':'Allocation failed: Allocation disallowed', 'comment':'Allocation failed: Allocation disallowed',
'error_message': '', 'error_message': '',
'actor': 'ERP5TypeTestCase', 'actor': 'ERP5TypeTestCase',
'slap_state': '', 'state': 'current',
'time': addToDate(DateTime(), to_add={'day': -2}), 'time': addToDate(DateTime(), to_add={'day': -2}),
'action': 'edit' 'action': 'edit'
}) }]
instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree() self.tic()
self.assertEqual('start_requested', instance.getSlapState()) software_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
instance_tree = instance.getSpecialiseValue() self.assertEqual('start_requested', software_instance.getSlapState())
self.assertEqual('start_requested', instance_tree.getSlapState()) self.assertEqual('start_requested', instance_tree.getSlapState())
def test_tryToGarbageCollect_complex_tree(self): def test_tryToGarbageCollectNonAllocatedRootTree_script_oldAllocationTryFoundAllocationDisallowed(self):
instance = self.createInstance(self.project) instance_tree = self.addInstanceTree()
instance_tree = instance.getSpecialiseValue() software_instance = instance_tree.getSuccessorValue()
self.tic()
software_instance.workflow_history['edit_workflow'] = [{
'comment':'Allocation failed: Allocation disallowed',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'state': 'current',
'time': addToDate(DateTime(), to_add={'day': -4}),
'action': 'edit'
}]
software_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
self.assertEqual('destroy_requested', instance_tree.getSlapState())
self.assertEqual('archived', instance_tree.getValidationState())
self.assertEqual('start_requested', software_instance.getSlapState())
def test_tryToGarbageCollectNonAllocatedRootTree_script_complexTree(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
request_kw = dict( request_kw = dict(
software_release=\ software_release=\
self.generateNewSoftwareReleaseUrl(), self.generateNewSoftwareReleaseUrl(),
...@@ -744,24 +842,24 @@ class TestSlapOSGarbageCollectNonAllocatedRootTreeAlarm(SlapOSTestCaseMixin): ...@@ -744,24 +842,24 @@ class TestSlapOSGarbageCollectNonAllocatedRootTreeAlarm(SlapOSTestCaseMixin):
software_title="another %s" % instance_tree.getTitle(), software_title="another %s" % instance_tree.getTitle(),
state='started' state='started'
) )
instance.requestInstance(**request_kw) software_instance.requestInstance(**request_kw)
sub_instance = instance.getSuccessorValue() sub_instance = software_instance.getSuccessorValue()
self.tic() self.tic()
sub_instance.workflow_history['edit_workflow'].append({ sub_instance.workflow_history['edit_workflow'] = [{
'comment':'Allocation failed: no free Compute Partition', 'comment':'Allocation failed: no free Compute Partition',
'error_message': '', 'error_message': '',
'actor': 'ERP5TypeTestCase', 'actor': 'ERP5TypeTestCase',
'slap_state': '', 'state': 'current',
'time': addToDate(DateTime(), to_add={'day': -4}), 'time': addToDate(DateTime(), to_add={'day': -4}),
'action': 'edit' 'action': 'edit'
}) }]
sub_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree() sub_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
self.assertEqual('start_requested', instance_tree.getSlapState()) self.assertEqual('start_requested', instance_tree.getSlapState())
def test_tryToGarbageCollect_complex_tree_allocation_disallowed(self): def test_tryToGarbageCollectNonAllocatedRootTree_script_complexTreeAllocationDisallowed(self):
instance = self.createInstance(self.project) instance_tree = self.addInstanceTree()
instance_tree = instance.getSpecialiseValue() software_instance = instance_tree.getSuccessorValue()
request_kw = dict( request_kw = dict(
software_release=\ software_release=\
self.generateNewSoftwareReleaseUrl(), self.generateNewSoftwareReleaseUrl(),
...@@ -772,193 +870,127 @@ class TestSlapOSGarbageCollectNonAllocatedRootTreeAlarm(SlapOSTestCaseMixin): ...@@ -772,193 +870,127 @@ class TestSlapOSGarbageCollectNonAllocatedRootTreeAlarm(SlapOSTestCaseMixin):
software_title="another %s" % instance_tree.getTitle(), software_title="another %s" % instance_tree.getTitle(),
state='started' state='started'
) )
instance.requestInstance(**request_kw) software_instance.requestInstance(**request_kw)
sub_instance = instance.getSuccessorValue() sub_instance = software_instance.getSuccessorValue()
self.tic() self.tic()
sub_instance.workflow_history['edit_workflow'].append({ sub_instance.workflow_history['edit_workflow'] = [{
'comment':'Allocation failed: Allocation disallowed', 'comment':'Allocation failed: Allocation disallowed',
'error_message': '', 'error_message': '',
'actor': 'ERP5TypeTestCase', 'actor': 'ERP5TypeTestCase',
'slap_state': '', 'state': 'current',
'time': addToDate(DateTime(), to_add={'day': -4}), 'time': addToDate(DateTime(), to_add={'day': -2}),
'action': 'edit' 'action': 'edit'
}) }]
sub_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree() sub_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
self.assertEqual('start_requested', instance_tree.getSlapState()) self.assertEqual('start_requested', instance_tree.getSlapState())
def test_tryToGarbageCollect_old_allocation_try_found(self):
instance = self.createInstance(self.project)
instance_tree = instance.getSpecialiseValue()
self.tic()
instance.workflow_history['edit_workflow'].append({
'comment':'Allocation failed: no free Compute Partition',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': '',
'time': addToDate(DateTime(), to_add={'day': -8}),
'action': 'edit'
})
instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
self.assertEqual('destroy_requested', instance_tree.getSlapState())
self.assertEqual('archived', instance_tree.getValidationState())
class TestSlapOSInvalidateDestroyedInstance(SlapOSTestCaseMixin):
#################################################################
# slapos_cloud_invalidate_destroyed_instance
#################################################################
def test_tryToInvalidateIfDestroyed_alarm_softwareInstanceInvalidated(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
def test_tryToGarbageCollect_old_allocation_try_found_allocation_disallowed(self): self.portal.portal_workflow._jumpToStateFor(software_instance, 'invalidated')
instance = self.createInstance(self.project) self.portal.portal_workflow._jumpToStateFor(software_instance, 'destroy_requested')
instance_tree = instance.getSpecialiseValue()
self.tic() self.tic()
instance.workflow_history['edit_workflow'].append({
'comment':'Allocation failed: Allocation disallowed',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': '',
'time': addToDate(DateTime(), to_add={'day': -8}),
'action': 'edit'
})
instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
self.assertEqual('destroy_requested', instance_tree.getSlapState())
self.assertEqual('archived', instance_tree.getValidationState())
def test_alarm(self):
instance = self.createInstance(self.project)
self._test_alarm(
self.portal.portal_alarms.slapos_garbage_collect_non_allocated_root_tree,
instance,
'SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree'
)
def test_alarm_invalidated(self):
instance = self.createInstance(self.project)
instance.invalidate()
self._test_alarm_not_visited( self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_garbage_collect_non_allocated_root_tree, self.portal.portal_alarms.slapos_cloud_invalidate_destroyed_instance,
instance, software_instance,
'SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree' 'SoftwareInstance_tryToInvalidateIfDestroyed'
) )
def test_alarm_allocated(self): def test_tryToInvalidateIfDestroyed_alarm_softwareInstanceMatching(self):
instance = self.createInstance(self.project) instance_tree = self.addInstanceTree()
partition = self.createComputePartition() software_instance = instance_tree.getSuccessorValue()
instance.edit(aggregate_value=partition)
self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_garbage_collect_non_allocated_root_tree,
instance,
'SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree'
)
self.portal.portal_workflow._jumpToStateFor(software_instance, 'validated')
self.portal.portal_workflow._jumpToStateFor(software_instance, 'destroy_requested')
self.tic()
class TestSlapOSInvalidateDestroyedInstance(SlapOSTestCaseMixin): self._test_alarm(
self.portal.portal_alarms.slapos_cloud_invalidate_destroyed_instance,
software_instance,
'SoftwareInstance_tryToInvalidateIfDestroyed'
)
def afterSetUp(self): def test_tryToInvalidateIfDestroyed_alarm_softwareInstanceAllocated(self):
SlapOSTestCaseMixin.afterSetUp(self) instance_tree = self.addInstanceTree()
self.project = self.addProject() software_instance = instance_tree.getSuccessorValue()
def createSoftwareInstance(self): _, partition = self.addComputeNodeAndPartition(project=instance_tree.getFollowUpValue())
new_id = self.generateNewId() software_instance.setAggregateValue(partition)
return self.portal.software_instance_module.newContent( partition.markBusy()
portal_type='Software Instance',
title="Test instance %s" % new_id,
reference="TESTINST-%s" % new_id,
)
def createComputePartition(self): self.portal.portal_workflow._jumpToStateFor(software_instance, 'validated')
new_id = self.generateNewId() self.portal.portal_workflow._jumpToStateFor(software_instance, 'destroy_requested')
compute_node = self.portal.compute_node_module.newContent( self.tic()
portal_type='Compute Node',
title="Test compute_node %s" % new_id,
reference="TESTCOMP-%s" % new_id,
)
compute_partition = compute_node.newContent(
portal_type='Compute Partition',
)
return compute_partition
self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_cloud_invalidate_destroyed_instance,
software_instance,
'SoftwareInstance_tryToInvalidateIfDestroyed'
)
#################################################################
# SoftwareInstance_tryToInvalidateIfDestroyed
#################################################################
def test_tryToInvalidateIfDestroyed_REQUEST_disallowed(self): def test_tryToInvalidateIfDestroyed_REQUEST_disallowed(self):
instance = self.createSoftwareInstance() instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
self.assertRaises( self.assertRaises(
Unauthorized, Unauthorized,
instance.SoftwareInstance_tryToInvalidateIfDestroyed, software_instance.SoftwareInstance_tryToInvalidateIfDestroyed,
REQUEST={}) REQUEST={})
def test_tryToInvalidateIfDestroyed_unexpected_context(self): def test_tryToInvalidateIfDestroyed_script_unexpectedContext(self):
self.assertRaises( self.assertRaises(
TypeError, TypeError,
self.portal.SoftwareInstance_tryToInvalidateIfDestroyed, self.portal.SoftwareInstance_tryToInvalidateIfDestroyed,
) )
def test_tryToInvalidateIfDestroyed_expected_instance(self): def test_tryToInvalidateIfDestroyed_script_expectedInstance(self):
instance = self.createSoftwareInstance() instance_tree = self.addInstanceTree()
self.portal.portal_workflow._jumpToStateFor(instance, 'validated') software_instance = instance_tree.getSuccessorValue()
self.portal.portal_workflow._jumpToStateFor(instance, 'destroy_requested') self.portal.portal_workflow._jumpToStateFor(software_instance, 'validated')
instance.SoftwareInstance_tryToInvalidateIfDestroyed() self.portal.portal_workflow._jumpToStateFor(software_instance, 'destroy_requested')
self.assertEqual(instance.getValidationState(), "invalidated") software_instance.SoftwareInstance_tryToInvalidateIfDestroyed()
self.assertEqual(instance.getSlapState(), "destroy_requested") self.assertEqual(software_instance.getValidationState(), "invalidated")
self.assertEqual(software_instance.getSlapState(), "destroy_requested")
def test_tryToInvalidateIfDestroyed_invalidated_instance(self):
instance = self.createSoftwareInstance() def test_tryToInvalidateIfDestroyed_script_invalidatedInstance(self):
self.portal.portal_workflow._jumpToStateFor(instance, 'invalidated') instance_tree = self.addInstanceTree()
self.portal.portal_workflow._jumpToStateFor(instance, 'destroy_requested') software_instance = instance_tree.getSuccessorValue()
instance.SoftwareInstance_tryToInvalidateIfDestroyed() self.portal.portal_workflow._jumpToStateFor(software_instance, 'invalidated')
self.assertEqual(instance.getValidationState(), "invalidated") self.portal.portal_workflow._jumpToStateFor(software_instance, 'destroy_requested')
self.assertEqual(instance.getSlapState(), "destroy_requested") software_instance.SoftwareInstance_tryToInvalidateIfDestroyed()
self.assertEqual(software_instance.getValidationState(), "invalidated")
def test_tryToInvalidateIfDestroyed_not_destroyed_instance(self): self.assertEqual(software_instance.getSlapState(), "destroy_requested")
instance = self.createSoftwareInstance()
self.portal.portal_workflow._jumpToStateFor(instance, 'validated') def test_tryToInvalidateIfDestroyed_script_notDestroyedInstance(self):
self.portal.portal_workflow._jumpToStateFor(instance, 'stop_requested') instance_tree = self.addInstanceTree()
instance.SoftwareInstance_tryToInvalidateIfDestroyed() software_instance = instance_tree.getSuccessorValue()
self.assertEqual(instance.getValidationState(), "validated") self.portal.portal_workflow._jumpToStateFor(software_instance, 'validated')
self.assertEqual(instance.getSlapState(), "stop_requested") self.portal.portal_workflow._jumpToStateFor(software_instance, 'stop_requested')
software_instance.SoftwareInstance_tryToInvalidateIfDestroyed()
def test_tryToInvalidateIfDestroyed_allocated_instance(self): self.assertEqual(software_instance.getValidationState(), "validated")
instance = self.createSoftwareInstance() self.assertEqual(software_instance.getSlapState(), "stop_requested")
partition = self.createComputePartition()
instance.edit(aggregate_value=partition) def test_tryToInvalidateIfDestroyed_script_allocatedInstance(self):
self.portal.portal_workflow._jumpToStateFor(instance, 'validated') instance_tree = self.addInstanceTree()
self.portal.portal_workflow._jumpToStateFor(instance, 'destroy_requested') software_instance = instance_tree.getSuccessorValue()
instance.SoftwareInstance_tryToInvalidateIfDestroyed()
self.assertEqual(instance.getValidationState(), "validated") _, partition = self.addComputeNodeAndPartition(project=instance_tree.getFollowUpValue())
self.assertEqual(instance.getSlapState(), "destroy_requested") software_instance.setAggregateValue(partition)
partition.markBusy()
def test_alarm_software_instance_allocated(self):
instance = self.createSoftwareInstance()
partition = self.createComputePartition()
instance.edit(aggregate_value=partition)
self.portal.portal_workflow._jumpToStateFor(instance, 'validated')
self.portal.portal_workflow._jumpToStateFor(instance, 'destroy_requested')
self.tic()
self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_cloud_invalidate_destroyed_instance,
instance,
'SoftwareInstance_tryToInvalidateIfDestroyed'
)
def test_alarm_software_instance_invalidated(self):
instance = self.createSoftwareInstance()
self.createComputePartition()
self.portal.portal_workflow._jumpToStateFor(instance, 'invalidated')
self.portal.portal_workflow._jumpToStateFor(instance, 'destroy_requested')
self.tic()
self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_cloud_invalidate_destroyed_instance,
instance,
'SoftwareInstance_tryToInvalidateIfDestroyed'
)
def test_alarm_software_instance_matching(self): self.portal.portal_workflow._jumpToStateFor(software_instance, 'validated')
instance = self.createSoftwareInstance() self.portal.portal_workflow._jumpToStateFor(software_instance, 'destroy_requested')
self.createComputePartition() software_instance.SoftwareInstance_tryToInvalidateIfDestroyed()
self.portal.portal_workflow._jumpToStateFor(instance, 'validated') self.assertEqual(software_instance.getValidationState(), "validated")
self.portal.portal_workflow._jumpToStateFor(instance, 'destroy_requested') self.assertEqual(software_instance.getSlapState(), "destroy_requested")
self.tic()
self._test_alarm(
self.portal.portal_alarms.slapos_cloud_invalidate_destroyed_instance,
instance,
'SoftwareInstance_tryToInvalidateIfDestroyed'
)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment