Commit 0a57808f authored by Łukasz Nowak's avatar Łukasz Nowak

slapos_cloud: Implement Alarm to destroy deprecated Software Installation

Software Installation deprecated is:

 * SI which is start_requested
 * SI which is validated
 * SI which usage on computer is 0
 * which matches url_string of archived Software Release

Those Software Installations are going be destroyed.

Also each archived Software Release to which no validated Software Installation
is related is going to be cleaned, so it will optimise next runs of the alarm.
parent ee43c187
<?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_destroySoftwareInstallationWithArchivedSoftwareRelease</string> </value>
</item>
<item>
<key> <string>automatic_solve</string> </key>
<value> <int>0</int> </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_destroy_software_installation_with_archived_software_release</string> </value>
</item>
<item>
<key> <string>periodicity_hour</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_hour_frequency</string> </key>
<value> <int>2</int> </value>
</item>
<item>
<key> <string>periodicity_minute</string> </key>
<value>
<tuple>
<int>0</int>
</tuple>
</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>0.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>Destroy Software Installation related to archived Software Releases</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -27,4 +27,8 @@ ...@@ -27,4 +27,8 @@
<type>Software Instance</type> <type>Software Instance</type>
<workflow>edit_workflow, instance_slap_interface_workflow, item_workflow, slapos_cloud_interaction_workflow</workflow> <workflow>edit_workflow, instance_slap_interface_workflow, item_workflow, slapos_cloud_interaction_workflow</workflow>
</chain> </chain>
<chain>
<type>Software Release</type>
<workflow>slapos_software_release_cleanup_workflow</workflow>
</chain>
</workflow_chain> </workflow_chain>
\ No newline at end of file
portal = context.getPortalObject()
portal.portal_catalog.searchAndActivate(
portal_type='Software Release',
validation_state = 'archived',
simulation_state = 'draft',
method_id = 'SoftwareRelease_findAndDestroySoftwareInstallation',
method_kw = {'tag': tag},
activate_kw = {'tag':tag}
)
context.activate(after_tag=tag).getId()
<?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>_params</string> </key>
<value> <string>tag, fixit, params</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Alarm_destroySoftwareInstallationWithArchivedSoftwareRelease</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
software_installation = context
url_string = software_installation.getUrlString()
if software_installation.getValidationState() != 'validated':
return
if software_installation.getSlapState() != 'start_requested':
return
software_release = software_installation.portal_catalog.getResultValue(
portal_type='Software Release',
validation_state='archived',
url_string=url_string
)
if software_release is None:
return
computer = software_installation.getAggregateValue(portal_type='Computer')
if computer is None:
return
if computer.Computer_getSoftwareReleaseUsage(url_string) != 0:
return
software_installation.requestDestroy(
comment='Destroyed by %s as %s is archived.' % (script.id, software_release.getRelativeUrl(),))
<?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>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SoftwareInstallation_destroyWithSoftwareReleaseArchived</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
<key> <string>delegated_list</string> </key> <key> <string>delegated_list</string> </key>
<value> <value>
<list> <list>
<string>editable</string>
<string>portal_type</string> <string>portal_type</string>
<string>title</string> <string>title</string>
</list> </list>
...@@ -77,10 +76,6 @@ ...@@ -77,10 +76,6 @@
<key> <string>values</string> </key> <key> <string>values</string> </key>
<value> <value>
<dictionary> <dictionary>
<item>
<key> <string>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item> <item>
<key> <string>field_id</string> </key> <key> <string>field_id</string> </key>
<value> <string>my_multi_relation_field</string> </value> <value> <string>my_multi_relation_field</string> </value>
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
<key> <string>delegated_list</string> </key> <key> <string>delegated_list</string> </key>
<value> <value>
<list> <list>
<string>editable</string>
<string>title</string> <string>title</string>
</list> </list>
</value> </value>
...@@ -71,6 +72,10 @@ ...@@ -71,6 +72,10 @@
<key> <string>values</string> </key> <key> <string>values</string> </key>
<value> <value>
<dictionary> <dictionary>
<item>
<key> <string>editable</string> </key>
<value> <int>1</int> </value>
</item>
<item> <item>
<key> <string>field_id</string> </key> <key> <string>field_id</string> </key>
<value> <string>my_view_mode_read_only_reference</string> </value> <value> <string>my_view_mode_read_only_reference</string> </value>
......
if context.getValidationState() != 'archived':
return
if context.getSimulationState() == 'cleaned':
return
portal = context.getPortalObject()
catalog_kw = dict(
portal_type='Software Installation',
validation_state='validated',
url_string=context.getUrlString()
)
count = portal.portal_catalog.countResults(
**catalog_kw
)
if count[0][0] == 0:
context.cleanup(comment='No more validated Software Installations found')
else:
portal.portal_catalog.searchAndActivate(
method_id = 'SoftwareInstallation_destroyWithSoftwareReleaseArchived',
activate_kw = {'tag':tag},
**catalog_kw
)
<?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>_params</string> </key>
<value> <string>tag</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SoftwareRelease_findAndDestroySoftwareInstallation</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2019 Nexedi SA and Contributors. All Rights Reserved.
#
##############################################################################
from erp5.component.test.SlapOSTestCaseMixin import SlapOSTestCaseMixin
from erp5.component.test.testSlapOSAccountingAlarm import simulateByEditWorkflowMark
class TestSlapOSDestroySoftwareInstallationWithArchivedSoftwareReleaseAlarm(SlapOSTestCaseMixin):
def createInstance(self, url_string):
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=url_string,
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(self):
preference = self.portal.portal_preferences.getActiveSystemPreference()
preference.setPreferredCloudContractEnabled(True)
self.tic()
computer, partition = self._makeComputer()
archived_url_string = self.generateNewSoftwareReleaseUrl()
# create software release
archived_software_release = self.portal.software_release_module.newContent(
portal_type='Software Release',
version='1',
url_string=archived_url_string
)
archived_software_release.publish()
archived_software_release.archive()
self.assertEqual('draft', archived_software_release.getSimulationState())
# install an software release
archived_software_installation = self.portal.software_installation_module\
.newContent(portal_type='Software Installation',
url_string=archived_url_string,
aggregate=computer.getRelativeUrl())
archived_software_installation.validate()
archived_software_installation.requestStart()
archived_used_url_string = self.generateNewSoftwareReleaseUrl()
# create software release
archived_used_software_release = self.portal.software_release_module.newContent(
portal_type='Software Release',
version='1',
url_string=archived_used_url_string
)
archived_used_software_release.publish()
archived_used_software_release.archive()
self.assertEqual('draft', archived_used_software_release.getSimulationState())
# install an software release
archived_used_software_installation = self.portal.software_installation_module\
.newContent(portal_type='Software Installation',
url_string=archived_used_url_string,
aggregate=computer.getRelativeUrl())
archived_used_software_installation.validate()
archived_used_software_installation.requestStart()
# use the software release
instance = self.createInstance(archived_used_url_string)
instance.setAggregate(partition.getRelativeUrl())
partition.markBusy()
self.tic()
published_url_string = self.generateNewSoftwareReleaseUrl()
# create software release
published_software_release = self.portal.software_release_module.newContent(
portal_type='Software Release',
version='1',
url_string=published_url_string
)
published_software_release.publish()
self.assertEqual('draft', published_software_release.getSimulationState())
# install an software release
published_software_installation = self.portal.software_installation_module\
.newContent(portal_type='Software Installation',
url_string=published_url_string,
aggregate=computer.getRelativeUrl())
published_software_installation.validate()
published_software_installation.requestStart()
self.tic()
# first run touches software installation
self.stepCallSlaposDestroySoftwareInstallationWithArchivedSoftwareReleaseAlarm()
self.tic()
self.assertEqual('destroy_requested', archived_software_installation.getSlapState())
self.assertEqual('validated', archived_software_installation.getValidationState())
self.assertEqual('start_requested', published_software_installation.getSlapState())
self.assertEqual('validated', published_software_installation.getValidationState())
self.assertEqual('start_requested', archived_used_software_installation.getSlapState())
self.assertEqual('validated', archived_used_software_installation.getValidationState())
# second run, but it is still not reported that software installation is destroyed
self.stepCallSlaposDestroySoftwareInstallationWithArchivedSoftwareReleaseAlarm()
self.tic()
self.assertEqual('draft', archived_software_release.getSimulationState())
self.assertEqual('draft', published_software_release.getSimulationState())
self.assertEqual('start_requested', published_software_installation.getSlapState())
self.assertEqual('validated', archived_used_software_installation.getValidationState())
self.assertEqual('start_requested', archived_used_software_installation.getSlapState())
# simulate the computer run
archived_software_installation.invalidate()
self.tic()
self.stepCallSlaposDestroySoftwareInstallationWithArchivedSoftwareReleaseAlarm()
self.tic()
self.assertEqual('cleaned', archived_software_release.getSimulationState())
self.assertEqual('draft', published_software_release.getSimulationState())
self.assertEqual('start_requested', published_software_installation.getSlapState())
self.assertEqual('validated', archived_used_software_installation.getValidationState())
self.assertEqual('start_requested', archived_used_software_installation.getSlapState())
@simulateByEditWorkflowMark('SoftwareRelease_findAndDestroySoftwareInstallation')
def test_no_op_run_software_release(self):
archived_software_release = self.portal.software_release_module.newContent(
portal_type='Software Release',
version='1',
url_string=self.generateNewSoftwareReleaseUrl(),
)
archived_software_release.publish()
archived_software_release.archive()
self.assertEqual('draft', archived_software_release.getSimulationState())
archived_cleaned_software_release = self.portal.software_release_module.newContent(
portal_type='Software Release',
version='1',
url_string=self.generateNewSoftwareReleaseUrl(),
)
archived_cleaned_software_release.publish()
archived_cleaned_software_release.archive()
archived_cleaned_software_release.cleanup()
self.assertEqual('cleaned', archived_cleaned_software_release.getSimulationState())
published_software_release = self.portal.software_release_module.newContent(
portal_type='Software Release',
version='1',
url_string=self.generateNewSoftwareReleaseUrl(),
)
published_software_release.publish()
self.assertEqual('draft', published_software_release.getSimulationState())
self.tic()
self.stepCallSlaposDestroySoftwareInstallationWithArchivedSoftwareReleaseAlarm()
self.tic()
v = 'Visited by SoftwareRelease_findAndDestroySoftwareInstallation'
self.assertFalse(v in
[q['comment'] for q in published_software_release.workflow_history['edit_workflow']])
self.assertFalse(v in
[q['comment'] for q in archived_cleaned_software_release.workflow_history['edit_workflow']])
self.assertTrue(v in
[q['comment'] for q in archived_software_release.workflow_history['edit_workflow']])
@simulateByEditWorkflowMark('SoftwareInstallation_destroyWithSoftwareReleaseArchived')
def test_no_op_run_software_installation(self):
preference = self.portal.portal_preferences.getActiveSystemPreference()
preference.setPreferredCloudContractEnabled(True)
self.tic()
computer, partition = self._makeComputer()
partition.invalidate()
partition.markBusy()
url_string = self.generateNewSoftwareReleaseUrl()
archived_software_release = self.portal.software_release_module.newContent(
portal_type='Software Release',
version='1',
url_string=url_string,
)
archived_software_release.publish()
archived_software_release.archive()
self.assertEqual('draft', archived_software_release.getSimulationState())
software_installation_validated_request_start = self.portal.software_installation_module\
.newContent(portal_type='Software Installation',
url_string=url_string,
aggregate=computer.getRelativeUrl())
software_installation_validated_request_start.validate()
software_installation_validated_request_start.requestStart()
software_installation_validated_request_destroy = self.portal.software_installation_module\
.newContent(portal_type='Software Installation',
url_string=url_string,
aggregate=computer.getRelativeUrl())
software_installation_validated_request_destroy.validate()
software_installation_validated_request_destroy.requestStart()
software_installation_validated_request_destroy.requestDestroy()
software_installation_invalidated_request_destroy = self.portal.software_installation_module\
.newContent(portal_type='Software Installation',
url_string=url_string,
aggregate=computer.getRelativeUrl())
software_installation_invalidated_request_destroy.validate()
software_installation_invalidated_request_destroy.requestStart()
software_installation_invalidated_request_destroy.requestDestroy()
software_installation_invalidated_request_destroy.invalidate()
self.tic()
# sanity check
self.assertEqual('validated', software_installation_validated_request_start.getValidationState())
self.assertEqual('start_requested', software_installation_validated_request_start.getSlapState())
self.assertEqual('validated', software_installation_validated_request_destroy.getValidationState())
self.assertEqual('destroy_requested', software_installation_validated_request_destroy.getSlapState())
self.assertEqual('invalidated', software_installation_invalidated_request_destroy.getValidationState())
self.assertEqual('destroy_requested', software_installation_invalidated_request_destroy.getSlapState())
self.stepCallSlaposDestroySoftwareInstallationWithArchivedSoftwareReleaseAlarm()
self.tic()
v = 'Visited by SoftwareInstallation_destroyWithSoftwareReleaseArchived'
self.assertTrue(v in
[q['comment'] for q in software_installation_validated_request_start.workflow_history['edit_workflow']])
self.assertTrue(v in
[q['comment'] for q in software_installation_validated_request_destroy.workflow_history['edit_workflow']])
self.assertFalse(v in
[q['comment'] for q in software_installation_invalidated_request_destroy.workflow_history['edit_workflow']])
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Test Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>testSlapOSDestroySoftwareInstallationWithArchivedSoftwareReleaseAlarm</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test.erp5.testSlapOSDestroySoftwareInstallationWithArchivedSoftwareReleaseAlarm</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Test Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
</pickle>
<pickle>
<tuple>
<none/>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="DCWorkflowDefinition" module="Products.DCWorkflow.DCWorkflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>creation_guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>slapos_software_release_cleanup_workflow</string> </value>
</item>
<item>
<key> <string>initial_state</string> </key>
<value> <string>draft</string> </value>
</item>
<item>
<key> <string>manager_bypass</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>Access contents information</string>
<string>View</string>
<string>Add portal content</string>
<string>Modify portal content</string>
<string>Delete objects</string>
</tuple>
</value>
</item>
<item>
<key> <string>state_var</string> </key>
<value> <string>simulation_state</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Software Release Cleanup Workflow</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Scripts" module="Products.DCWorkflow.Scripts"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_mapping</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>scripts</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="States" module="Products.DCWorkflow.States"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_mapping</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>states</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="StateDefinition" module="Products.DCWorkflow.States"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>cleaned</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Cleaned</string> </value>
</item>
<item>
<key> <string>transitions</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>type_list</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="StateDefinition" module="Products.DCWorkflow.States"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>draft</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Draft</string> </value>
</item>
<item>
<key> <string>transitions</string> </key>
<value>
<tuple>
<string>cleanup</string>
</tuple>
</value>
</item>
<item>
<key> <string>type_list</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Transitions" module="Products.DCWorkflow.Transitions"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_mapping</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>transitions</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="TransitionDefinition" module="Products.DCWorkflow.Transitions"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>cleanup</string> </value>
</item>
<item>
<key> <string>new_state_id</string> </key>
<value> <string>cleaned</string> </value>
</item>
<item>
<key> <string>script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Guard" module="Products.DCWorkflow.Guard"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>Modify portal content</string>
</tuple>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Variables" module="Products.DCWorkflow.Variables"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_mapping</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variables</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="VariableDefinition" module="Products.DCWorkflow.Variables"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_expr</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_value</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Transition id</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>for_status</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>action</string> </value>
</item>
<item>
<key> <string>info_guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>update_always</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>transition/getId|nothing</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="VariableDefinition" module="Products.DCWorkflow.Variables"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_expr</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_value</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Name of the user who performed transition</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>for_status</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>actor</string> </value>
</item>
<item>
<key> <string>info_guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>update_always</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>user/getIdOrUserName</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="VariableDefinition" module="Products.DCWorkflow.Variables"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_expr</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_value</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Comment about transition</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>for_status</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>comment</string> </value>
</item>
<item>
<key> <string>info_guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>update_always</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>python:state_change.kwargs.get(\'comment\', \'\')</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="VariableDefinition" module="Products.DCWorkflow.Variables"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_expr</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>default_value</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Error message if validation failed</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>for_status</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>error_message</string> </value>
</item>
<item>
<key> <string>info_guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>update_always</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="VariableDefinition" module="Products.DCWorkflow.Variables"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_expr</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_value</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Provides access to workflow history</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>for_status</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>history</string> </value>
</item>
<item>
<key> <string>info_guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>update_always</string> </key>
<value> <int>0</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>state_change/getHistory</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="VariableDefinition" module="Products.DCWorkflow.Variables"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_expr</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>default_value</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Portal type (used as filter for worklists)</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>for_status</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>portal_type</string> </value>
</item>
<item>
<key> <string>info_guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>update_always</string> </key>
<value> <int>0</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="VariableDefinition" module="Products.DCWorkflow.Variables"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_expr</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_value</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Transition timestamp</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>for_status</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>time</string> </value>
</item>
<item>
<key> <string>info_guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>update_always</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>state_change/getDateTime</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Worklists" module="Products.DCWorkflow.Worklists"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_mapping</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>worklists</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -11,6 +11,7 @@ person_module/template_member/** ...@@ -11,6 +11,7 @@ person_module/template_member/**
portal_alarms/slapos_allocate_instance portal_alarms/slapos_allocate_instance
portal_alarms/slapos_assert_hosting_subscription_predecessor portal_alarms/slapos_assert_hosting_subscription_predecessor
portal_alarms/slapos_cloud_invalidate_destroyed_instance portal_alarms/slapos_cloud_invalidate_destroyed_instance
portal_alarms/slapos_destroy_software_installation_with_archived_software_release
portal_alarms/slapos_free_computer_partition portal_alarms/slapos_free_computer_partition
portal_alarms/slapos_garbage_collect_destroy_unlinked_instance portal_alarms/slapos_garbage_collect_destroy_unlinked_instance
portal_alarms/slapos_garbage_collect_destroyed_root_tree portal_alarms/slapos_garbage_collect_destroyed_root_tree
......
...@@ -17,3 +17,4 @@ Software Instance | edit_workflow ...@@ -17,3 +17,4 @@ Software Instance | edit_workflow
Software Instance | instance_slap_interface_workflow Software Instance | instance_slap_interface_workflow
Software Instance | item_workflow Software Instance | item_workflow
Software Instance | slapos_cloud_interaction_workflow Software Instance | slapos_cloud_interaction_workflow
Software Release | slapos_software_release_cleanup_workflow
\ No newline at end of file
...@@ -6,3 +6,4 @@ test.erp5.testSlapOSCloudConstraint ...@@ -6,3 +6,4 @@ test.erp5.testSlapOSCloudConstraint
test.erp5.testSlapOSCloudShadow test.erp5.testSlapOSCloudShadow
test.erp5.SlapOSTestCaseMixin test.erp5.SlapOSTestCaseMixin
test.erp5.SlapOSTestCaseDefaultScenarioMixin test.erp5.SlapOSTestCaseDefaultScenarioMixin
test.erp5.testSlapOSDestroySoftwareInstallationWithArchivedSoftwareReleaseAlarm
\ No newline at end of file
...@@ -5,3 +5,4 @@ installation_slap_interface_workflow ...@@ -5,3 +5,4 @@ installation_slap_interface_workflow
instance_slap_interface_workflow instance_slap_interface_workflow
person_slap_interface_workflow person_slap_interface_workflow
slapos_cloud_interaction_workflow slapos_cloud_interaction_workflow
slapos_software_release_cleanup_workflow
\ No newline at end of file
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