Commit 9bb5accb authored by Romain Courteaud's avatar Romain Courteaud

Stop all instances related to a stopped subscription.

parent bdc5ffc3
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Alarm" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>active_sense_method_id</string> </key>
<value> <string>Alarm_stopCollectInstance</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>slapos_stop_collect_instance</string> </value>
</item>
<item>
<key> <string>periodicity_hour</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_hour_frequency</string> </key>
<value> <int>6</int> </value>
</item>
<item>
<key> <string>periodicity_minute</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_minute_frequency</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>periodicity_month</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_month_day</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_start_date</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>437036400.0</float>
<string>GMT</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>periodicity_week</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Alarm</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Stop Collect Instance</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</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"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>portal = context.getPortalObject()\n
\n
portal.portal_catalog.searchAndActivate(\n
portal_type=["Slave Instance", "Software Instance"],\n
validation_state="validated",\n
specialise_validation_state="validated",\n
method_id=\'Instance_tryToStopCollect\',\n
activate_kw={\'tag\': tag}\n
)\n
\n
context.activate(after_tag=tag).getId()\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>tag, fixit, params</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Alarm_stopCollectInstance</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</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"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>from zExceptions import Unauthorized\n
if REQUEST is not None:\n
raise Unauthorized\n
\n
instance = context\n
\n
if (instance.getSlapState() == "start_requested"):\n
hosting_subscription = instance.getSpecialiseValue(portal_type="Hosting Subscription")\n
if (hosting_subscription.getSlapState() == "stop_requested"):\n
# Buildout may not propagate the stop request\n
requester = instance.getPredecessorRelatedValue()\n
if (instance.getRelativeUrl() in requester.getPredecessorList()) and \\\n
(requester.getSlapState() == "stop_requested"):\n
# For security, only stop if parent is also stopped\n
\n
if instance.getPortalType() == \'Software Instance\':\n
is_slave = False\n
elif instance.getPortalType() == \'Slave Instance\':\n
is_slave = True\n
else:\n
raise NotImplementedError, "Unknown portal type %s of %s" % \\\n
(instance.getPortalType(), instance.getRelativeUrl())\n
\n
requester.requestInstance(\n
software_release=instance.getUrlString(),\n
software_title=instance.getTitle(),\n
software_type=instance.getSourceReference(),\n
instance_xml=instance.getTextContent(),\n
sla_xml=instance.getSlaXml(),\n
shared=is_slave,\n
state="stopped",\n
comment="Stop collect %s" % instance.getRelativeUrl()\n
)\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Instance_tryToStopCollect</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -5,6 +5,7 @@ from Products.SlapOS.tests.testSlapOSMixin import \
from Products.ERP5Type.tests.utils import createZODBPythonScript
from Products.ERP5Type.tests.backportUnittest import skip
import json
from zExceptions import Unauthorized
class TestSlapOSCorePromiseSlapOSModuleIdGeneratorAlarm(testSlapOSMixin):
def test_Module_assertIdGenerator(self):
......@@ -1177,3 +1178,127 @@ portal_workflow.doActionFor(context, action='edit_action', comment='Visited by C
self.assertNotEqual(
'Visited by Computer_checkAndUpdateCapacityScope',
self.computer.workflow_history['edit_workflow'][-1]['comment'])
class TestSlapOSGarbageCollectStoppedRootTreeAlarm(testSlapOSMixin):
def createInstance(self):
hosting_subscription = self.portal.hosting_subscription_module\
.template_hosting_subscription.Base_createCloneDocument(batch_mode=1)
hosting_subscription.edit(
)
hosting_subscription.validate()
hosting_subscription.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=hosting_subscription.getTitle(),
state='started'
)
hosting_subscription.requestStart(**request_kw)
hosting_subscription.requestInstance(**request_kw)
instance = hosting_subscription.getPredecessorValue()
self.tic()
return instance
def test_Instance_tryToStopCollect_REQUEST_disallowed(self):
self.assertRaises(
Unauthorized,
self.portal.Instance_tryToStopCollect,
REQUEST={})
def test_Instance_tryToStopCollect_started_instance(self):
instance = self.createInstance()
hosting_subscription = instance.getSpecialiseValue()
self.portal.portal_workflow._jumpToStateFor(hosting_subscription,
'stop_requested')
self.assertEqual('start_requested', instance.getSlapState())
instance.Instance_tryToStopCollect()
self.assertEqual('stop_requested', instance.getSlapState())
def test_Instance_tryToStopCollect_started_instance(self):
instance = self.createInstance()
hosting_subscription = instance.getSpecialiseValue()
self.portal.portal_workflow._jumpToStateFor(hosting_subscription,
'stop_requested')
self.assertEqual('start_requested', instance.getSlapState())
instance.Instance_tryToStopCollect()
self.assertEqual('stop_requested', instance.getSlapState())
def test_Instance_tryToStopCollect_destroyed_instance(self):
instance = self.createInstance()
hosting_subscription = instance.getSpecialiseValue()
self.portal.portal_workflow._jumpToStateFor(hosting_subscription,
'stop_requested')
self.portal.portal_workflow._jumpToStateFor(instance,
'destroy_requested')
instance.Instance_tryToStopCollect()
self.assertEqual('destroy_requested', instance.getSlapState())
def test_Instance_tryToStopCollect_started_subscription(self):
instance = self.createInstance()
hosting_subscription = instance.getSpecialiseValue()
self.assertEqual('start_requested', hosting_subscription.getSlapState())
self.assertEqual('start_requested', instance.getSlapState())
instance.Instance_tryToStopCollect()
self.assertEqual('start_requested', instance.getSlapState())
def _simulateInstance_tryToStopCollect(self):
script_name = 'Instance_tryToStopCollect'
if script_name in self.portal.portal_skins.custom.objectIds():
raise ValueError('Precondition failed: %s exists in custom' % script_name)
createZODBPythonScript(self.portal.portal_skins.custom,
script_name,
'*args, **kwargs',
'# Script body\n'
"""portal_workflow = context.portal_workflow
portal_workflow.doActionFor(context, action='edit_action', comment='Visited by Instance_tryToStopCollect') """ )
transaction.commit()
def _dropInstance_tryToStopCollect(self):
script_name = 'Instance_tryToStopCollect'
if script_name in self.portal.portal_skins.custom.objectIds():
self.portal.portal_skins.custom.manage_delObjects(script_name)
transaction.commit()
def test_alarm(self):
instance = self.createInstance()
self._simulateInstance_tryToStopCollect()
try:
self.portal.portal_alarms.slapos_stop_collect_instance.activeSense()
self.tic()
finally:
self._dropInstance_tryToStopCollect()
self.assertEqual(
'Visited by Instance_tryToStopCollect',
instance.workflow_history['edit_workflow'][-1]['comment'])
def test_alarm_invalidated(self):
instance = self.createInstance()
instance.invalidate()
self.tic()
self._simulateInstance_tryToStopCollect()
try:
self.portal.portal_alarms.slapos_stop_collect_instance.activeSense()
self.tic()
finally:
self._dropInstance_tryToStopCollect()
self.assertNotEqual(
'Visited by Instance_tryToStopCollect',
instance.workflow_history['edit_workflow'][-1]['comment'])
265
\ No newline at end of file
266
\ No newline at end of file
......@@ -11,6 +11,7 @@ portal_alarms/slapos_allocate_instance
portal_alarms/slapos_assert_hosting_subscription_predecessor
portal_alarms/slapos_free_computer_partition
portal_alarms/slapos_garbage_collect_destroyed_root_tree
portal_alarms/slapos_stop_collect_instance
portal_alarms/slapos_update_computer_capacity_scope
software_installation_module/template_software_installation
software_instance_module/template_slave_instance
......
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