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 @@
<tuple/>
</value>
</item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
......
......@@ -76,12 +76,6 @@
<tuple/>
</value>
</item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
......
......@@ -12,10 +12,20 @@
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>acquire_local_roles</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>content_icon</string> </key>
<value> <string>folder_icon.gif</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>factory</string> </key>
<value> <string>addFolder</string> </value>
......@@ -32,6 +42,18 @@
<key> <string>id</string> </key>
<value> <string>Allocation Supply Module</string> </value>
</item>
<item>
<key> <string>init_script</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>permission</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Base Type</string> </value>
......@@ -40,6 +62,12 @@
<key> <string>type_class</string> </key>
<value> <string>Folder</string> </value>
</item>
<item>
<key> <string>type_interface</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
......
......@@ -60,12 +60,6 @@
<tuple/>
</value>
</item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
......
......@@ -58,12 +58,6 @@
<tuple/>
</value>
</item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
......
......@@ -58,12 +58,6 @@
<tuple/>
</value>
</item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
......
......@@ -6,18 +6,18 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple/>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
......
......@@ -6,18 +6,18 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple/>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
......
......@@ -6,18 +6,18 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple/>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
......
......@@ -11,9 +11,13 @@
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple/>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
......
......@@ -6,18 +6,18 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple/>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
......
......@@ -6,18 +6,18 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple/>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
......
......@@ -11,9 +11,13 @@
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple/>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
......
......@@ -6,18 +6,18 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple/>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
......
service = context
item = context
portal = context.getPortalObject()
if (item.getPortalType() == 'Instance Tree') and (item.getSlapState() == "destroy_requested"):
return 'todestroy'
# If no open order, subscription must be approved
open_sale_order_movement_list = portal.portal_catalog(
portal_type=['Open Sale Order Line', 'Open Sale Order Cell'],
aggregate__uid=service.getUid(),
aggregate__uid=item.getUid(),
validation_state='validated',
limit=1
)
context.log("%s %s" % (service.getRelativeUrl(), len(open_sale_order_movement_list)))
if len(open_sale_order_movement_list) == 0:
return "not_subscribed"
......
......@@ -6,18 +6,18 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple/>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
......
......@@ -6,18 +6,18 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple/>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
......
......@@ -11,9 +11,13 @@
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple/>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
......
......@@ -248,6 +248,36 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
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'):
new_id = self.generateNewId()
......@@ -322,6 +352,37 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
def _makeSlaveTree(self, project, requested_template_id='template_slave_instance'):
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'):
self.compute_node = self.portal.compute_node_module.template_compute_node\
.Base_createCloneDocument(batch_mode=1)
......@@ -436,6 +497,7 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
project_reference=project.getReference()
)
instance_tree.requestStart(**kw)
with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
instance_tree.requestInstance(**kw)
self.start_requested_software_instance = instance_tree.getSuccessorValue()
......@@ -462,6 +524,7 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
project_reference=project.getReference()
)
instance_tree.requestStart(**slave_kw)
with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
instance_tree.requestInstance(**slave_kw)
self.start_requested_slave_instance = instance_tree.getSuccessorValue()
......@@ -488,6 +551,7 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
project_reference=project.getReference()
)
instance_tree.requestStop(**kw)
with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
instance_tree.requestInstance(**kw)
self.stop_requested_software_instance = instance_tree.getSuccessorValue()
......@@ -515,6 +579,7 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
project_reference=project.getReference()
)
instance_tree.requestStop(**kw)
with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
instance_tree.requestInstance(**kw)
kw['state'] = 'destroyed'
......@@ -546,6 +611,7 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
project_reference=project.getReference()
)
instance_tree.requestStop(**kw)
with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
instance_tree.requestInstance(**kw)
kw['state'] = 'destroyed'
......@@ -647,9 +713,12 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
# behaviour.
compute_node.edit(capacity_scope='open')
elif node == "remote":
remote_project = self.addProject(is_accountable=False)
compute_node = self.portal.compute_node_module.newContent(
portal_type="Remote Node",
follow_up_value=project
follow_up_value=project,
destination_project_value=remote_project,
destination_section_value=person
)
elif node == "instance":
compute_node = self.portal.compute_node_module.newContent(
......@@ -733,7 +802,10 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
partition.markBusy()
# 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(
portal_type="Open Sale Order",
ledger="automated",
......
# Copyright (c) 2002-2012 Nexedi SA and Contributors. All Rights Reserved.
import transaction
from erp5.component.test.SlapOSTestCaseMixin import SlapOSTestCaseMixin
from erp5.component.test.SlapOSTestCaseMixin import SlapOSTestCaseMixin, TemporaryAlarmScript
from zExceptions import Unauthorized
from DateTime import DateTime
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):
instance_tree = self.portal.instance_tree_module.newContent(
portal_type='Instance Tree'
......@@ -79,661 +23,815 @@ class TestSlapOSCoreSlapOSAssertInstanceTreeSuccessorAlarm(
)
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.portal.portal_alarms.slapos_assert_instance_tree_successor,
self.instance_tree,
instance_tree,
'InstanceTree_assertSuccessor'
)
def test_InstanceTree_assertSuccessor_alarm_not_renamed(self):
self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_assert_instance_tree_successor,
self.instance_tree,
self.addInstanceTree(),
'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):
SlapOSTestCaseMixin.afterSetUp(self)
self.project = self.addProject()
self._makeTree(self.project)
with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
instance_tree.InstanceTree_assertSuccessor()
def test_SoftwareInstance_tryToUnallocatePartition(self):
self._makeComputeNode(self.project)
self.software_instance.setAggregate(self.partition.getRelativeUrl())
self.partition.markBusy()
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
'destroy_requested')
self.tic()
self.assertNotEqual(instance_tree.getTitle(), software_instance.getTitle())
self.assertTrue(instance_tree.getTitle() in
instance_tree.getSuccessorTitleList())
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.assertEqual(None, self.software_instance.getAggregate())
self.assertEqual('free', self.partition.getSlapState())
def test_SoftwareInstance_tryToUnallocatePartition_concurrency(self):
self._makeComputeNode(self.project)
self.software_instance.setAggregate(self.partition.getRelativeUrl())
self.partition.markBusy()
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
# 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())
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')
self.tic()
self.partition.activate(tag="allocate_%s" % self.partition.getRelativeUrl()\
).getId()
transaction.commit()
self.software_instance.SoftwareInstance_tryToUnallocatePartition()
# 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())
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.assertEqual(self.partition.getRelativeUrl(),
self.software_instance.getAggregate())
self.assertEqual('busy', self.partition.getSlapState())
def test_SoftwareInstance_tryToUnallocatePartition_twoInstances(self):
software_instance = self.portal.software_instance_module\
.template_software_instance.Base_createCloneDocument(batch_mode=1)
# 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())
with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
instance_tree.InstanceTree_assertSuccessor()
self._makeComputeNode(self.project)
self.software_instance.setAggregate(self.partition.getRelativeUrl())
software_instance.setAggregate(self.partition.getRelativeUrl())
self.partition.markBusy()
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
self.assertNotEqual(instance_tree.getTitle(), software_instance.getTitle())
self.assertFalse(instance_tree.getTitle() in
instance_tree.getSuccessorTitleList())
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')
self.tic()
# invalidate transition triggers the alarm
self.portal.portal_workflow._jumpToStateFor(software_instance,
'invalidated')
self.software_instance.SoftwareInstance_tryToUnallocatePartition()
self.tic()
self.assertEqual(None, self.software_instance.getAggregate())
self.assertEqual('busy', self.partition.getSlapState())
self.assertEqual(self.partition.getRelativeUrl(), software_instance.getAggregate())
self._test_alarm(
self.portal.portal_alarms.slapos_free_compute_partition,
software_instance,
'SoftwareInstance_tryToUnallocatePartition'
)
def test_alarm_allocated(self):
self._makeComputeNode(self.project)
self.software_instance.setAggregate(self.partition.getRelativeUrl())
self.partition.markBusy()
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
def test_SoftwareInstance_tryToUnallocatePartition_alarm_sharedAndAllocated(self):
instance_tree = self.addInstanceTree(shared=True)
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')
self.software_instance.invalidate()
# invalidate transition triggers the alarm
self.portal.portal_workflow._jumpToStateFor(software_instance,
'invalidated')
self.tic()
self._test_alarm(
self.portal.portal_alarms.slapos_free_compute_partition,
self.software_instance,
software_instance,
'SoftwareInstance_tryToUnallocatePartition'
)
def test_alarm_unallocated(self):
self._makeComputeNode(self.project)
self.partition.markBusy()
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
def test_SoftwareInstance_tryToUnallocatePartition_alarm_unallocated(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
_, partition = self.addComputeNodeAndPartition(project=instance_tree.getFollowUpValue())
partition.markBusy()
self.portal.portal_workflow._jumpToStateFor(software_instance,
'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.portal.portal_alarms.slapos_free_compute_partition,
self.software_instance,
software_instance,
'SoftwareInstance_tryToUnallocatePartition'
)
def test_alarm_validated(self):
self._makeComputeNode(self.project)
self.software_instance.setAggregate(self.partition.getRelativeUrl())
self.partition.markBusy()
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
def test_SoftwareInstance_tryToUnallocatePartition_alarm_allocatedAndValidated(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')
self.tic()
self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_free_compute_partition,
self.software_instance,
software_instance,
'SoftwareInstance_tryToUnallocatePartition'
)
def test_alarm_start_requested(self):
self._makeComputeNode(self.project)
self.software_instance.setAggregate(self.partition.getRelativeUrl())
self.partition.markBusy()
def test_SoftwareInstance_tryToUnallocatePartition_alarm_allocatedAndStarted(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._test_alarm_not_visited(
self.portal.portal_alarms.slapos_free_compute_partition,
self.software_instance,
software_instance,
'SoftwareInstance_tryToUnallocatePartition'
)
class TestSlapOSFreeComputePartitionAlarmWithSlave(SlapOSTestCaseMixin):
def afterSetUp(self):
SlapOSTestCaseMixin.afterSetUp(self)
self.project = self.addProject()
self._makeTree(self.project,
requested_template_id='template_slave_instance')
#################################################################
# SoftwareInstance_tryToUnallocatePartition
#################################################################
def test_SoftwareInstance_tryToUnallocatePartition_script_allocated(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
_, partition = self.addComputeNodeAndPartition(project=instance_tree.getFollowUpValue())
def test_SoftwareInstance_tryToUnallocatePartition(self):
self._makeComputeNode(self.project)
self.software_instance.setAggregate(self.partition.getRelativeUrl())
self.partition.markBusy()
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
software_instance.setAggregateValue(partition)
partition.markBusy()
self.portal.portal_workflow._jumpToStateFor(software_instance,
'destroy_requested')
self.tic()
self.software_instance.SoftwareInstance_tryToUnallocatePartition()
self.tic()
self.assertEqual(None, self.software_instance.getAggregate())
self.assertEqual('free', self.partition.getSlapState())
software_instance.SoftwareInstance_tryToUnallocatePartition()
self.assertEqual(None, software_instance.getAggregate())
self.assertEqual('free', partition.getSlapState())
def test_SoftwareInstance_tryToUnallocatePartition_nonDestroyed(self):
self._makeComputeNode(self.project)
self.software_instance.setAggregate(self.partition.getRelativeUrl())
self.partition.markBusy()
def test_SoftwareInstance_tryToUnallocatePartition_script_sharedAndAllocated(self):
instance_tree = self.addInstanceTree(shared=True)
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')
self.tic()
self.software_instance.SoftwareInstance_tryToUnallocatePartition()
software_instance.SoftwareInstance_tryToUnallocatePartition()
self.assertEqual(None, software_instance.getAggregate())
self.assertEqual('free', partition.getSlapState())
def test_SoftwareInstance_tryToUnallocatePartition_script_concurrency(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')
self.tic()
self.assertEqual(self.partition.getRelativeUrl(),
self.software_instance.getAggregate())
self.assertEqual('busy', self.partition.getSlapState())
partition.activate(tag="allocate_%s" % partition.getRelativeUrl()\
).getId()
transaction.commit()
software_instance.SoftwareInstance_tryToUnallocatePartition()
self.assertEqual(partition.getRelativeUrl(),
software_instance.getAggregate())
self.assertEqual('busy', partition.getSlapState())
class TestSlapOSGarbageCollectDestroyedRootTreeAlarm(SlapOSTestCaseMixin):
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 afterSetUp(self):
SlapOSTestCaseMixin.afterSetUp(self)
self.project = self.addProject()
self._makeTree(self.project)
self.tic()
def test_SoftwareInstance_tryToGarbageCollect(self):
self.instance_tree.archive()
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
'destroy_requested')
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
try:
# Prevent calling interaction workflows
software_instance.setCategoryList(
software_instance.getCategoryList() + ['aggregate/%s' % partition.getRelativeUrl()]
)
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()
self.requested_software_instance.SoftwareInstance_tryToGarbageCollect()
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.assertEqual('destroy_requested',
self.requested_software_instance.getSlapState())
self.assertEqual('validated',
self.requested_software_instance.getValidationState())
def test_SoftwareInstance_tryToGarbageCollect_not_destroy_requested(self):
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.assertEqual('start_requested',
self.requested_software_instance.getSlapState())
self.assertEqual('validated',
self.requested_software_instance.getValidationState())
def test_SoftwareInstance_tryToGarbageCollect_not_archived(self):
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
'destroy_requested')
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
software_instance.SoftwareInstance_tryToUnallocatePartition()
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')
self.tic()
self.assertEqual('validated',
software_instance.getValidationState())
self.requested_software_instance.SoftwareInstance_tryToGarbageCollect()
self.tic()
self.assertEqual('start_requested',
self.requested_software_instance.getSlapState())
software_instance.SoftwareInstance_tryToGarbageCollect()
self.assertEqual('destroy_requested',
software_instance.getSlapState())
self.assertEqual('validated',
self.requested_software_instance.getValidationState())
software_instance.getValidationState())
def test_SoftwareInstance_tryToGarbageCollect_only_instance_destroy_requested(self):
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
'destroy_requested')
self.tic()
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()
software_instance.SoftwareInstance_tryToGarbageCollect()
self.assertEqual('start_requested',
self.requested_software_instance.getSlapState())
software_instance.getSlapState())
self.assertEqual('validated',
self.requested_software_instance.getValidationState())
software_instance.getValidationState())
def test_SoftwareInstance_tryToGarbageCollect_unlinked_successor(self):
self.requested_software_instance.edit(successor_list=[])
self.instance_tree.archive()
self.portal.portal_workflow._jumpToStateFor(self.instance_tree,
'destroy_requested')
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
def test_SoftwareInstance_tryToGarbageCollect_script_notArchived(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
self.portal.portal_workflow._jumpToStateFor(instance_tree,
'destroy_requested')
self.tic()
self.requested_software_instance.SoftwareInstance_tryToGarbageCollect()
self.tic()
self.assertEqual('destroy_requested',
self.requested_software_instance.getSlapState())
software_instance.SoftwareInstance_tryToGarbageCollect()
self.assertEqual('start_requested',
software_instance.getSlapState())
self.assertEqual('validated',
self.requested_software_instance.getValidationState())
software_instance.getValidationState())
def test_SoftwareInstance_tryToGarbageCollect_destroy_unlinked_with_child(self):
instance_kw = dict(software_release=self.generateNewSoftwareReleaseUrl(),
software_type=self.generateNewSoftwareType(),
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)
def test_SoftwareInstance_tryToGarbageCollect_script_unlinkedSuccessor(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
self.requested_software_instance.edit(successor_list=[])
self.instance_tree.archive()
self.portal.portal_workflow._jumpToStateFor(self.instance_tree,
'destroy_requested')
self.portal.portal_workflow._jumpToStateFor(self.software_instance,
instance_tree.edit(successor_list=[])
instance_tree.archive()
self.portal.portal_workflow._jumpToStateFor(instance_tree,
'destroy_requested')
self.tic()
self.requested_software_instance.SoftwareInstance_tryToGarbageCollect()
self.tic()
software_instance.SoftwareInstance_tryToGarbageCollect()
self.assertEqual('destroy_requested',
self.requested_software_instance.getSlapState())
software_instance.getSlapState())
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):
self.instance_tree.archive()
class TestSlapOSUpdateComputeNodeCapacityScopeAlarm(SlapOSTestCaseMixin):
#################################################################
# 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.portal.portal_alarms.slapos_garbage_collect_destroyed_root_tree,
self.software_instance,
'SoftwareInstance_tryToGarbageCollect'
self.portal.portal_alarms.slapos_update_compute_node_capacity_scope,
compute_node,
'ComputeNode_checkAndUpdateCapacityScope'
)
def test_alarm_invalidated(self):
self.instance_tree.archive()
self.software_instance.invalidate()
self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_garbage_collect_destroyed_root_tree,
self.software_instance,
'SoftwareInstance_tryToGarbageCollect'
def test_ComputeNode_checkAndUpdateCapacityScope_alarm_close(self):
compute_node, _ = self.addComputeNodeAndPartition()
compute_node.edit(
allocation_scope='close',
)
def test_alarm_not_archived(self):
self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_garbage_collect_destroyed_root_tree,
self.software_instance,
'SoftwareInstance_tryToGarbageCollect'
self.portal.portal_alarms.slapos_update_compute_node_capacity_scope,
compute_node,
'ComputeNode_checkAndUpdateCapacityScope'
)
class TestSlapOSUpdateComputeNodeCapacityScopeAlarm(SlapOSTestCaseMixin):
def afterSetUp(self):
SlapOSTestCaseMixin.afterSetUp(self)
self.project = self.addProject()
self.compute_node = self.portal.compute_node_module.template_compute_node\
.Base_createCloneDocument(batch_mode=1)
self.compute_node.edit(
def test_ComputeNode_checkAndUpdateCapacityScope_alarm_invalidated(self):
compute_node, _ = self.addComputeNodeAndPartition()
compute_node.invalidate()
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())
self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_update_compute_node_capacity_scope,
compute_node,
'ComputeNode_checkAndUpdateCapacityScope'
)
def _newComputerModel(self, quantity=None):
computer_model = self.portal.computer_model_module.\
template_computer_model.Base_createCloneDocument(batch_mode=1)
computer_model.edit(capacity_quantity=quantity,
#################################################################
# 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())
def addComputerModel(self, capacity_quantity=None):
return self.portal.computer_model_module.newContent(
portal_type="Computer Model",
reference='TESTCM-%s' % self.generateNewId(),
capacity_quantity=capacity_quantity
)
return computer_model
def _addPartitionToComputeNode(self):
partition = self.compute_node.newContent(portal_type='Compute Partition',
reference='part1')
partition.markFree()
partition.markBusy()
partition.validate()
self.software_instance.setAggregate(partition.getRelativeUrl())
self.tic()
def test_ComputeNode_checkAndUpdateCapacityScope_model(self):
computer_model = self._newComputerModel(9999)
def test_ComputeNode_checkAndUpdateCapacityScope_script_model(self):
compute_node, _ = self.addComputeNodeAndPartition()
compute_node.edit(allocation_scope='open')
compute_node.edit(capacity_scope='open')
compute_node.setAccessStatus("#access ok")
self.compute_node.edit(specialise_value=computer_model,
capacity_quantity=None)
transaction.commit()
computer_model = self.addComputerModel(9999)
compute_node.edit(specialise_value=computer_model, capacity_quantity=None)
self.compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('open', self.compute_node.getCapacityScope())
compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('open', compute_node.getCapacityScope())
self.assertEqual(computer_model.getCapacityQuantity(),
self.compute_node.getCapacityQuantity())
compute_node.getCapacityQuantity())
def test_ComputeNode_checkAndUpdateCapacityScope_model_no_capacity(self):
self._makeTree(self.project)
def test_ComputeNode_checkAndUpdateCapacityScope_script_modelNoCapacity(self):
compute_node, partition = self.addComputeNodeAndPartition()
compute_node.edit(allocation_scope='open')
compute_node.edit(capacity_scope='open')
compute_node.setAccessStatus("#access ok")
computer_model = self._newComputerModel(1)
self.compute_node.edit(specialise_value=computer_model,
capacity_quantity=None)
computer_model = self.addComputerModel(1)
compute_node.edit(specialise_value=computer_model, capacity_quantity=None)
self._addPartitionToComputeNode()
self.compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('close', self.compute_node.getCapacityScope())
self.assertEqual('Compute Node capacity limit exceeded',
self.compute_node.workflow_history['edit_workflow'][-1]['comment'])
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',
compute_node.workflow_history['edit_workflow'][-1]['comment'])
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.
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.compute_node.edit(specialise_value=computer_model,
capacity_quantity=2)
self.tic()
self._addPartitionToComputeNode()
self.compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('open', self.compute_node.getCapacityScope())
compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('open', 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:
self.pinDateTime(addToDate(DateTime(),to_add={'minute': -11}))
self.compute_node.setAccessStatus("#access ok")
compute_node.setAccessStatus("#access ok")
finally:
self.unpinDateTime()
self.compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('close', self.compute_node.getCapacityScope())
compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('close', compute_node.getCapacityScope())
self.assertEqual("Compute Node didn't contact for more than 10 minutes",
self.compute_node.workflow_history['edit_workflow'][-1]['comment'])
def test_ComputeNode_checkAndUpdateCapacityScope_no_capacity_quantity(self):
self._makeTree(self.project)
self.compute_node.edit(capacity_quantity=1)
self._addPartitionToComputeNode()
self.compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('close', self.compute_node.getCapacityScope())
compute_node.workflow_history['edit_workflow'][-1]['comment'])
def test_ComputeNode_checkAndUpdateCapacityScope_script_noCapacityQuantity(self):
compute_node, partition = self.addComputeNodeAndPartition()
compute_node.edit(allocation_scope='open')
compute_node.edit(capacity_scope='open')
compute_node.setAccessStatus("#access ok")
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.compute_node.workflow_history['edit_workflow'][-1]['comment'])
compute_node.workflow_history['edit_workflow'][-1]['comment'])
def test_ComputeNode_checkAndUpdateCapacityScope_script_noAccess(self):
compute_node, _ = self.addComputeNodeAndPartition()
compute_node.edit(allocation_scope='open')
compute_node.edit(capacity_scope='open')
def test_ComputeNode_checkAndUpdateCapacityScope_no_access(self):
self.compute_node.edit(reference='TESTC-%s' % self.generateNewId())
self.compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('close', self.compute_node.getCapacityScope())
compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('close', compute_node.getCapacityScope())
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):
self.compute_node.edit(capacity_scope='close')
self.compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('open', self.compute_node.getCapacityScope())
def test_ComputeNode_checkAndUpdateCapacityScope_script_capacityClose(self):
compute_node, _ = self.addComputeNodeAndPartition()
compute_node.edit(allocation_scope='open')
compute_node.setAccessStatus("#access ok")
compute_node.edit(capacity_scope='close')
def test_ComputeNode_checkAndUpdateCapacityScope_with_error(self):
self.compute_node.setAccessStatus('#error not ok')
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'])
compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('open', compute_node.getCapacityScope())
def test_alarm(self):
self._test_alarm(
self.portal.portal_alarms.slapos_update_compute_node_capacity_scope,
self.compute_node,
'ComputeNode_checkAndUpdateCapacityScope'
)
def test_ComputeNode_checkAndUpdateCapacityScope_script_withError(self):
compute_node, _ = self.addComputeNodeAndPartition()
compute_node.edit(allocation_scope='open')
compute_node.edit(capacity_scope='open')
compute_node.setAccessStatus('#error not ok')
def test_alarm_non_public(self):
self.compute_node.edit(allocation_scope='close')
self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_update_compute_node_capacity_scope,
self.compute_node,
'ComputeNode_checkAndUpdateCapacityScope'
)
compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('close', compute_node.getCapacityScope())
self.assertEqual("Compute Node reported an error",
compute_node.workflow_history['edit_workflow'][-1]['comment'])
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):
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.getReference()
#################################################################
# slapos_stop_collect_instance
#################################################################
def test_SoftwareInstance_tryToStopCollect_alarm(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
self._test_alarm(
self.portal.portal_alarms.slapos_stop_collect_instance,
software_instance,
'SoftwareInstance_tryToStopCollect'
)
instance_tree.requestStart(**request_kw)
instance_tree.requestInstance(**request_kw)
instance = instance_tree.getSuccessorValue()
self.tic()
return instance
def test_SoftwareInstance_tryToStopCollect_alarm_invalidated(self):
instance_tree = self.addInstanceTree()
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):
self.assertRaises(
Unauthorized,
self.portal.SoftwareInstance_tryToStopCollect,
REQUEST={})
def test_SoftwareInstance_tryToStopCollect_started_instance(self):
instance = self.createInstance(self.project)
instance_tree = instance.getSpecialiseValue()
def test_SoftwareInstance_tryToStopCollect_script_startedInstance(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
self.portal.portal_workflow._jumpToStateFor(instance_tree,
'stop_requested')
self.assertEqual('start_requested', instance.getSlapState())
self.assertEqual('start_requested', software_instance.getSlapState())
instance.SoftwareInstance_tryToStopCollect()
self.assertEqual('stop_requested', instance.getSlapState())
software_instance.SoftwareInstance_tryToStopCollect()
self.assertEqual('stop_requested', software_instance.getSlapState())
def test_SoftwareInstance_tryToStopCollect_destroyed_instance(self):
instance = self.createInstance(self.project)
instance_tree = instance.getSpecialiseValue()
def test_SoftwareInstance_tryToStopCollect_script_destroyedInstance(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
self.portal.portal_workflow._jumpToStateFor(instance_tree,
'stop_requested')
self.portal.portal_workflow._jumpToStateFor(instance,
self.portal.portal_workflow._jumpToStateFor(software_instance,
'destroy_requested')
instance.SoftwareInstance_tryToStopCollect()
self.assertEqual('destroy_requested', instance.getSlapState())
software_instance.SoftwareInstance_tryToStopCollect()
self.assertEqual('destroy_requested', software_instance.getSlapState())
def test_SoftwareInstance_tryToStopCollect_started_subscription(self):
instance = self.createInstance(self.project)
instance_tree = instance.getSpecialiseValue()
def test_SoftwareInstance_tryToStopCollect_script_startedInstanceTree(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
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):
instance = self.createInstance(self.project)
class TestSlapOSGarbageCollectNonAllocatedRootTreeAlarm(SlapOSTestCaseMixin):
#################################################################
# 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.portal.portal_alarms.slapos_stop_collect_instance,
instance,
'SoftwareInstance_tryToStopCollect'
self.portal.portal_alarms.slapos_garbage_collect_non_allocated_root_tree,
software_instance,
'SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree'
)
def test_alarm_invalidated(self):
instance = self.createInstance(self.project)
instance.invalidate()
def test_tryToGarbageCollectNonAllocatedRootTree_alarm_invalidated(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
software_instance.invalidate()
self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_stop_collect_instance,
instance,
'SoftwareInstance_tryToStopCollect'
)
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
self.portal.portal_alarms.slapos_garbage_collect_non_allocated_root_tree,
software_instance,
'SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree'
)
instance_tree.requestStart(**request_kw)
instance_tree.requestInstance(**request_kw)
instance = instance_tree.getSuccessorValue()
return instance
def test_tryToGarbageCollectNonAllocatedRootTree_alarm_allocated(self):
_, partition = self.addComputeNodeAndPartition()
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
software_instance.setAggregateValue(partition)
partition.markBusy()
def createComputePartition(self):
compute_node = self.portal.compute_node_module\
.template_compute_node.Base_createCloneDocument(batch_mode=1)
compute_node.validate()
compute_node.edit(
title=self.generateNewSoftwareTitle(),
reference="TESTCOMP-%s" % self.generateNewId(),
self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_garbage_collect_non_allocated_root_tree,
software_instance,
'SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree'
)
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(
Unauthorized,
self.portal.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree,
REQUEST={})
def test_tryToGarbageCollect_invalidated_instance(self):
instance = self.createInstance(self.project)
instance.invalidate()
self.tic()
def test_tryToGarbageCollectNonAllocatedRootTree_script_invalidatedInstance(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
software_instance.invalidate()
instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
self.assertEqual('start_requested', instance.getSlapState())
instance_tree = instance.getSpecialiseValue()
self.tic()
software_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
self.assertEqual('start_requested', software_instance.getSlapState())
self.assertEqual('start_requested', instance_tree.getSlapState())
def test_tryToGarbageCollect_destroyed_instance(self):
instance = self.createInstance(self.project)
self.portal.portal_workflow._jumpToStateFor(instance, 'destroy_requested')
self.tic()
def test_tryToGarbageCollectNonAllocatedRootTree_script_destroyedInstance(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
self.portal.portal_workflow._jumpToStateFor(software_instance, 'destroy_requested')
instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
self.assertEqual('destroy_requested', instance.getSlapState())
instance_tree = instance.getSpecialiseValue()
self.tic()
software_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
self.assertEqual('destroy_requested', software_instance.getSlapState())
self.assertEqual('start_requested', instance_tree.getSlapState())
def test_tryToGarbageCollect_allocated_instance(self):
instance = self.createInstance(self.project)
partition = self.createComputePartition()
instance.edit(aggregate_value=partition)
self.tic()
def test_tryToGarbageCollectNonAllocatedRootTree_script_allocatedInstance(self):
_, partition = self.addComputeNodeAndPartition()
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
software_instance.setAggregateValue(partition)
partition.markBusy()
instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
self.assertEqual('start_requested', instance.getSlapState())
instance_tree = instance.getSpecialiseValue()
self.tic()
software_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
self.assertEqual('start_requested', software_instance.getSlapState())
self.assertEqual('start_requested', instance_tree.getSlapState())
def test_tryToGarbageCollect_no_allocation_try_found(self):
instance = self.createInstance(self.project)
self.tic()
def test_tryToGarbageCollectNonAllocatedRootTree_script_noAllocationTryFound(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
self.assertEqual('start_requested', instance.getSlapState())
instance_tree = instance.getSpecialiseValue()
self.tic()
software_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
self.assertEqual('start_requested', software_instance.getSlapState())
self.assertEqual('start_requested', instance_tree.getSlapState())
def test_tryToGarbageCollect_recent_allocation_try_found(self):
instance = self.createInstance(self.project)
self.tic()
instance.workflow_history['edit_workflow'].append({
def test_tryToGarbageCollectNonAllocatedRootTree_script_recentAllocationTryFound(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
software_instance.workflow_history['edit_workflow'] = [{
'comment':'Allocation failed: no free Compute Partition',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': '',
'state': 'current',
'time': addToDate(DateTime(), to_add={'day': -2}),
'action': 'edit'
})
}]
instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
self.assertEqual('start_requested', instance.getSlapState())
instance_tree = instance.getSpecialiseValue()
self.tic()
software_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
self.assertEqual('start_requested', software_instance.getSlapState())
self.assertEqual('start_requested', instance_tree.getSlapState())
def test_tryToGarbageCollect_recent_allocation_try_found_allocation_disallowed(self):
instance = self.createInstance(self.project)
def test_tryToGarbageCollectNonAllocatedRootTree_script_oldAllocationTryFound(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
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',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': '',
'state': 'current',
'time': addToDate(DateTime(), to_add={'day': -2}),
'action': 'edit'
})
}]
instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
self.assertEqual('start_requested', instance.getSlapState())
instance_tree = instance.getSpecialiseValue()
self.tic()
software_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
self.assertEqual('start_requested', software_instance.getSlapState())
self.assertEqual('start_requested', instance_tree.getSlapState())
def test_tryToGarbageCollect_complex_tree(self):
instance = self.createInstance(self.project)
instance_tree = instance.getSpecialiseValue()
def test_tryToGarbageCollectNonAllocatedRootTree_script_oldAllocationTryFoundAllocationDisallowed(self):
instance_tree = self.addInstanceTree()
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(
software_release=\
self.generateNewSoftwareReleaseUrl(),
......@@ -744,24 +842,24 @@ class TestSlapOSGarbageCollectNonAllocatedRootTreeAlarm(SlapOSTestCaseMixin):
software_title="another %s" % instance_tree.getTitle(),
state='started'
)
instance.requestInstance(**request_kw)
sub_instance = instance.getSuccessorValue()
software_instance.requestInstance(**request_kw)
sub_instance = software_instance.getSuccessorValue()
self.tic()
sub_instance.workflow_history['edit_workflow'].append({
sub_instance.workflow_history['edit_workflow'] = [{
'comment':'Allocation failed: no free Compute Partition',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': '',
'state': 'current',
'time': addToDate(DateTime(), to_add={'day': -4}),
'action': 'edit'
})
}]
sub_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
self.assertEqual('start_requested', instance_tree.getSlapState())
def test_tryToGarbageCollect_complex_tree_allocation_disallowed(self):
instance = self.createInstance(self.project)
instance_tree = instance.getSpecialiseValue()
def test_tryToGarbageCollectNonAllocatedRootTree_script_complexTreeAllocationDisallowed(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
request_kw = dict(
software_release=\
self.generateNewSoftwareReleaseUrl(),
......@@ -772,193 +870,127 @@ class TestSlapOSGarbageCollectNonAllocatedRootTreeAlarm(SlapOSTestCaseMixin):
software_title="another %s" % instance_tree.getTitle(),
state='started'
)
instance.requestInstance(**request_kw)
sub_instance = instance.getSuccessorValue()
software_instance.requestInstance(**request_kw)
sub_instance = software_instance.getSuccessorValue()
self.tic()
sub_instance.workflow_history['edit_workflow'].append({
sub_instance.workflow_history['edit_workflow'] = [{
'comment':'Allocation failed: Allocation disallowed',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': '',
'time': addToDate(DateTime(), to_add={'day': -4}),
'state': 'current',
'time': addToDate(DateTime(), to_add={'day': -2}),
'action': 'edit'
})
}]
sub_instance.SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree()
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):
instance = self.createInstance(self.project)
instance_tree = instance.getSpecialiseValue()
self.portal.portal_workflow._jumpToStateFor(software_instance, 'invalidated')
self.portal.portal_workflow._jumpToStateFor(software_instance, 'destroy_requested')
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.portal.portal_alarms.slapos_garbage_collect_non_allocated_root_tree,
instance,
'SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree'
self.portal.portal_alarms.slapos_cloud_invalidate_destroyed_instance,
software_instance,
'SoftwareInstance_tryToInvalidateIfDestroyed'
)
def test_alarm_allocated(self):
instance = self.createInstance(self.project)
partition = self.createComputePartition()
instance.edit(aggregate_value=partition)
self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_garbage_collect_non_allocated_root_tree,
instance,
'SoftwareInstance_tryToGarbageCollectNonAllocatedRootTree'
)
def test_tryToInvalidateIfDestroyed_alarm_softwareInstanceMatching(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
self.portal.portal_workflow._jumpToStateFor(software_instance, 'validated')
self.portal.portal_workflow._jumpToStateFor(software_instance, 'destroy_requested')
self.tic()
self._test_alarm(
self.portal.portal_alarms.slapos_cloud_invalidate_destroyed_instance,
software_instance,
'SoftwareInstance_tryToInvalidateIfDestroyed'
)
class TestSlapOSInvalidateDestroyedInstance(SlapOSTestCaseMixin):
def test_tryToInvalidateIfDestroyed_alarm_softwareInstanceAllocated(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
def afterSetUp(self):
SlapOSTestCaseMixin.afterSetUp(self)
self.project = self.addProject()
_, partition = self.addComputeNodeAndPartition(project=instance_tree.getFollowUpValue())
software_instance.setAggregateValue(partition)
partition.markBusy()
def createSoftwareInstance(self):
new_id = self.generateNewId()
return self.portal.software_instance_module.newContent(
portal_type='Software Instance',
title="Test instance %s" % new_id,
reference="TESTINST-%s" % new_id,
)
self.portal.portal_workflow._jumpToStateFor(software_instance, 'validated')
self.portal.portal_workflow._jumpToStateFor(software_instance, 'destroy_requested')
self.tic()
def createComputePartition(self):
new_id = self.generateNewId()
compute_node = self.portal.compute_node_module.newContent(
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',
self._test_alarm_not_visited(
self.portal.portal_alarms.slapos_cloud_invalidate_destroyed_instance,
software_instance,
'SoftwareInstance_tryToInvalidateIfDestroyed'
)
return compute_partition
#################################################################
# SoftwareInstance_tryToInvalidateIfDestroyed
#################################################################
def test_tryToInvalidateIfDestroyed_REQUEST_disallowed(self):
instance = self.createSoftwareInstance()
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
self.assertRaises(
Unauthorized,
instance.SoftwareInstance_tryToInvalidateIfDestroyed,
software_instance.SoftwareInstance_tryToInvalidateIfDestroyed,
REQUEST={})
def test_tryToInvalidateIfDestroyed_unexpected_context(self):
def test_tryToInvalidateIfDestroyed_script_unexpectedContext(self):
self.assertRaises(
TypeError,
self.portal.SoftwareInstance_tryToInvalidateIfDestroyed,
)
def test_tryToInvalidateIfDestroyed_expected_instance(self):
instance = self.createSoftwareInstance()
self.portal.portal_workflow._jumpToStateFor(instance, 'validated')
self.portal.portal_workflow._jumpToStateFor(instance, 'destroy_requested')
instance.SoftwareInstance_tryToInvalidateIfDestroyed()
self.assertEqual(instance.getValidationState(), "invalidated")
self.assertEqual(instance.getSlapState(), "destroy_requested")
def test_tryToInvalidateIfDestroyed_invalidated_instance(self):
instance = self.createSoftwareInstance()
self.portal.portal_workflow._jumpToStateFor(instance, 'invalidated')
self.portal.portal_workflow._jumpToStateFor(instance, 'destroy_requested')
instance.SoftwareInstance_tryToInvalidateIfDestroyed()
self.assertEqual(instance.getValidationState(), "invalidated")
self.assertEqual(instance.getSlapState(), "destroy_requested")
def test_tryToInvalidateIfDestroyed_not_destroyed_instance(self):
instance = self.createSoftwareInstance()
self.portal.portal_workflow._jumpToStateFor(instance, 'validated')
self.portal.portal_workflow._jumpToStateFor(instance, 'stop_requested')
instance.SoftwareInstance_tryToInvalidateIfDestroyed()
self.assertEqual(instance.getValidationState(), "validated")
self.assertEqual(instance.getSlapState(), "stop_requested")
def test_tryToInvalidateIfDestroyed_allocated_instance(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')
instance.SoftwareInstance_tryToInvalidateIfDestroyed()
self.assertEqual(instance.getValidationState(), "validated")
self.assertEqual(instance.getSlapState(), "destroy_requested")
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_tryToInvalidateIfDestroyed_script_expectedInstance(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
self.portal.portal_workflow._jumpToStateFor(software_instance, 'validated')
self.portal.portal_workflow._jumpToStateFor(software_instance, 'destroy_requested')
software_instance.SoftwareInstance_tryToInvalidateIfDestroyed()
self.assertEqual(software_instance.getValidationState(), "invalidated")
self.assertEqual(software_instance.getSlapState(), "destroy_requested")
def test_tryToInvalidateIfDestroyed_script_invalidatedInstance(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
self.portal.portal_workflow._jumpToStateFor(software_instance, 'invalidated')
self.portal.portal_workflow._jumpToStateFor(software_instance, 'destroy_requested')
software_instance.SoftwareInstance_tryToInvalidateIfDestroyed()
self.assertEqual(software_instance.getValidationState(), "invalidated")
self.assertEqual(software_instance.getSlapState(), "destroy_requested")
def test_tryToInvalidateIfDestroyed_script_notDestroyedInstance(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
self.portal.portal_workflow._jumpToStateFor(software_instance, 'validated')
self.portal.portal_workflow._jumpToStateFor(software_instance, 'stop_requested')
software_instance.SoftwareInstance_tryToInvalidateIfDestroyed()
self.assertEqual(software_instance.getValidationState(), "validated")
self.assertEqual(software_instance.getSlapState(), "stop_requested")
def test_tryToInvalidateIfDestroyed_script_allocatedInstance(self):
instance_tree = self.addInstanceTree()
software_instance = instance_tree.getSuccessorValue()
_, partition = self.addComputeNodeAndPartition(project=instance_tree.getFollowUpValue())
software_instance.setAggregateValue(partition)
partition.markBusy()
def test_alarm_software_instance_matching(self):
instance = self.createSoftwareInstance()
self.createComputePartition()
self.portal.portal_workflow._jumpToStateFor(instance, 'validated')
self.portal.portal_workflow._jumpToStateFor(instance, 'destroy_requested')
self.tic()
self.portal.portal_workflow._jumpToStateFor(software_instance, 'validated')
self.portal.portal_workflow._jumpToStateFor(software_instance, 'destroy_requested')
software_instance.SoftwareInstance_tryToInvalidateIfDestroyed()
self.assertEqual(software_instance.getValidationState(), "validated")
self.assertEqual(software_instance.getSlapState(), "destroy_requested")
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