Commit df2f22d0 authored by Rafael Monnerat's avatar Rafael Monnerat

extend *slap-interface-workflow API to CRM/PDM

See merge request nexedi/slapos.core!360
parents 1d1bcf8b 4eeac9b7
......@@ -1253,3 +1253,208 @@ class TestSlapOSCorePersonRequestToken(SlapOSTestCaseMixin):
self.assertEqual(
token.getPortalType(), "One Time Restricted Access Token")
self.assertEqual(token.getUrlMethod(), "POST")
class TestSlapOSCorePersonNotify(SlapOSTestCaseMixin):
def afterSetUp(self):
SlapOSTestCaseMixin.afterSetUp(self)
self.person = self.makePerson()
self.tic()
def beforeTearDown(self):
pass
def test_Person_notify_mandatory_argument(self):
self.assertRaises(TypeError, self.person.notify)
self.assertRaises(TypeError, self.person.notify, support_request_title="a")
self.assertRaises(TypeError, self.person.notify, support_request_title="a", support_request_description="b")
def test_Person_notify_unknown_aggregate(self):
self.assertRaises(KeyError, self.person.notify,
support_request_title="a", support_request_description="b", aggregate="c")
def test_Person_notify_computer_node(self):
compute_node, _ = self._makeComputeNode()
self._test_Person_notify(compute_node)
def test_Person_notify_instance_tree(self):
person = self.portal.person_module.template_member\
.Base_createCloneDocument(batch_mode=1)
instance_tree = self.portal\
.instance_tree_module.template_instance_tree\
.Base_createCloneDocument(batch_mode=1)
instance_tree.validate()
new_id = self.generateNewId()
instance_tree.edit(
title= "Test hosting sub ticket %s" % new_id,
reference="TESTHST-%s" % new_id,
destination_section_value=person
)
self._test_Person_notify(instance_tree)
def test_Person_notify_software_installation(self):
self._makeComputeNode()
software_installation = self.portal\
.software_installation_module.template_software_installation\
.Base_createCloneDocument(batch_mode=1)
software_installation.edit(
url_string=self.generateNewSoftwareReleaseUrl(),
aggregate=self.compute_node.getRelativeUrl(),
reference='TESTSOFTINSTS-%s' % self.generateNewId(),
title='Start requested for %s' % self.compute_node.getUid()
)
software_installation.validate()
software_installation.requestStart()
self._test_Person_notify(software_installation)
def _test_Person_notify(self, aggregate_value):
# Step 1: Notify
self.person.notify(
support_request_title="A",
support_request_description="B",
aggregate=aggregate_value.getRelativeUrl()
)
# Step 2: Check return
support_request_relative_url = self.person.REQUEST.get(
"support_request_relative_url", None)
self.assertNotEqual(None, support_request_relative_url)
support_request_in_progress = self.person.REQUEST.get(
"support_request_in_progress", None)
self.assertEqual(support_request_in_progress, support_request_relative_url)
support_request = self.portal.restrictedTraverse(support_request_in_progress)
self.assertEqual(support_request.getSimulationState(),
"validated")
self.assertEqual(support_request.getTitle(), "A")
self.assertEqual(support_request.getDescription(), "B")
self.assertNotEqual(support_request.getStartDate(), None)
self.assertEqual(support_request.getDestinationDecision(),
self.person.getRelativeUrl())
self.assertEqual(support_request.getAggregateValue(),
aggregate_value)
self.assertEqual(support_request.getResource(),
"service_module/slapos_crm_monitoring")
# Step 3: Reset REQUEST and check in progress before catalog
self.person.REQUEST.set(
"support_request_relative_url", None)
support_request_relative_url = self.person.REQUEST.get(
"support_request_relative_url", None)
self.assertEqual(None, support_request_relative_url)
self.person.notify(
support_request_title="A",
support_request_description="B",
aggregate=aggregate_value.getRelativeUrl()
)
support_request_relative_url = self.person.REQUEST.get(
"support_request_relative_url", None)
self.assertNotEqual(None, support_request_relative_url)
self.assertEqual(support_request_in_progress, support_request_relative_url)
self.tic()
# Step 4: Reset parameters and check if the support request is got again.
self.person.REQUEST.set(
"support_request_relative_url", None)
support_request_relative_url = self.person.REQUEST.get(
"support_request_relative_url", None)
self.assertEqual(None, support_request_relative_url)
support_request_in_progress = self.person.REQUEST.set(
"support_request_in_progress", None)
support_request_in_progress = self.person.REQUEST.set(
"support_request_in_progress", None)
self.assertEqual(support_request_in_progress, None)
self.commit()
self.person.notify(
support_request_title="A",
support_request_description="B",
aggregate=aggregate_value.getRelativeUrl()
)
support_request_relative_url = self.person.REQUEST.get(
"support_request_relative_url", None)
self.assertNotEqual(None, support_request_relative_url)
support_request_in_progress = self.person.REQUEST.get(
"support_request_in_progress", None)
self.assertEqual(support_request_in_progress, support_request_relative_url)
# Check if it is the same Support Request as before
self.assertEqual(support_request.getRelativeUrl(),
support_request_relative_url)
# Step 5: Retry the same thing, but now on suspended state
support_request.suspend()
self.tic()
self.person.REQUEST.set(
"support_request_relative_url", None)
support_request_relative_url = self.person.REQUEST.get(
"support_request_relative_url", None)
self.assertEqual(None, support_request_relative_url)
support_request_in_progress = self.person.REQUEST.set(
"support_request_in_progress", None)
support_request_in_progress = self.person.REQUEST.set(
"support_request_in_progress", None)
self.assertEqual(support_request_in_progress, None)
self.commit()
self.person.notify(
support_request_title="A",
support_request_description="B",
aggregate=aggregate_value.getRelativeUrl()
)
support_request_relative_url = self.person.REQUEST.get(
"support_request_relative_url", None)
self.assertNotEqual(None, support_request_relative_url)
support_request_in_progress = self.person.REQUEST.get(
"support_request_in_progress", None)
self.assertEqual(support_request_in_progress, support_request_relative_url)
# Check if it is the same Support Request as before and still suspended
self.assertEqual(support_request.getRelativeUrl(),
support_request_relative_url)
self.assertEqual(support_request.getSimulationState(), "suspended")
# Step 6: If the support request is closed, create indeed a new one.
support_request.invalidate()
self.tic()
self.person.REQUEST.set("support_request_relative_url", None)
support_request_relative_url = self.person.REQUEST.get(
"support_request_relative_url", None)
self.assertEqual(None, support_request_relative_url)
support_request_in_progress = self.person.REQUEST.set(
"support_request_in_progress", None)
support_request_in_progress = self.person.REQUEST.set(
"support_request_in_progress", None)
self.assertEqual(support_request_in_progress, None)
self.commit()
self.person.notify(
support_request_title="A",
support_request_description="B",
aggregate=aggregate_value.getRelativeUrl()
)
support_request_relative_url = self.person.REQUEST.get(
"support_request_relative_url", None)
self.assertNotEqual(None, support_request_relative_url)
support_request_in_progress = self.person.REQUEST.get(
"support_request_in_progress", None)
self.assertEqual(support_request_in_progress, support_request_relative_url)
# Check if it is the another Support Request
self.assertEqual(support_request.getSimulationState(), "invalidated")
self.assertNotEqual(support_request.getRelativeUrl(),
support_request_relative_url)
from DateTime import DateTime
portal = context.getPortalObject()
aggregate_value = portal.restrictedTraverse(source_relative_url)
if aggregate_value.getPortalType() == "Compute Node":
destination_decision = aggregate_value.getSourceAdministration()
elif aggregate_value.getPortalType() == "Software Instance":
destination_decision = aggregate_value.getSpecialiseValue().getDestinationSection()
elif aggregate_value.getPortalType() == "Instance Tree":
destination_decision = aggregate_value.getDestinationSection()
elif aggregate_value.getPortalType() == "Software Installation":
destination_decision = aggregate_value.getDestinationSection()
else:
destination_decision = None
if portal.ERP5Site_isSupportRequestCreationClosed(destination_decision):
# Stop ticket creation
return
person = state_change['object']
portal = person.getPortalObject()
# Get required arguments
kwargs = state_change.kwargs
# Required args
# Raise TypeError if all parameters are not provided
try:
support_request_title = kwargs['support_request_title']
description = kwargs['support_request_description']
# Aggregate can be None, so it isn't included on the kwargs
aggregate = kwargs["aggregate"]
except KeyError:
raise TypeError, "Person_requestSupportRequest takes exactly 3 arguments"
aggregate_value = portal.restrictedTraverse(aggregate)
support_request_in_progress = portal.portal_catalog.getResultValue(
portal_type = 'Support Request',
title = title,
title = support_request_title,
simulation_state = ["validated", "submitted", "suspended"],
default_aggregate_uid = aggregate_value.getUid(),
)
if support_request_in_progress is not None:
return support_request_in_progress
context.REQUEST.set("support_request_relative_url",
support_request_in_progress.getRelativeUrl())
context.REQUEST.set("support_request_in_progress",
support_request_in_progress.getRelativeUrl())
return
support_request_in_progress = context.REQUEST.get("support_request_in_progress", None)
if support_request_in_progress is not None:
support_request = portal.restrictedTraverse(support_request_in_progress, None)
if support_request and support_request.getTitle() == title and \
if support_request and support_request.getTitle() == support_request_title and \
support_request.getAggregateUid() == aggregate_value.getUid():
return portal.restrictedTraverse(support_request_in_progress)
context.REQUEST.set("support_request_relative_url", support_request_in_progress)
return
# Ensure resoure is Monitoring
resource = portal.service_module.\
......@@ -45,15 +47,14 @@ support_request = portal.restrictedTraverse(
.Base_createCloneDocument(batch_mode=1)
support_request.edit(
title = title,
title = support_request_title,
description = description,
start_date = DateTime(),
destination_decision=destination_decision,
aggregate_value = aggregate_value,
destination_decision=person.getRelativeUrl(),
aggregate_value=aggregate_value,
resource=resource
)
support_request.validate()
context.REQUEST.set("support_request_relative_url", support_request.getRelativeUrl())
context.REQUEST.set("support_request_in_progress", support_request.getRelativeUrl())
return support_request
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
<global name="Workflow Script" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......@@ -50,11 +50,25 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>message_title, message, destination_relative_url</string> </value>
<value> <string>state_change</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SupportRequest_trySendNotificationMessage</string> </value>
<value> <string>script_Person_notify</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Script</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Person_notify</string> </value>
</item>
</dictionary>
</pickle>
......
person = state_change['object']
portal = person.getPortalObject()
# Get required arguments
kwargs = state_change.kwargs
# Required args
# Raise TypeError if all parameters are not provided
try:
support_request_title = kwargs['support_request_title']
resource = kwargs['support_request_resource']
description = kwargs['support_request_description']
# Aggregate can be None, so it isn't included on the kwargs
aggregate = kwargs.get("support_request_aggregate", None)
except KeyError:
raise TypeError, "Person_requestSupportRequest takes exactly 4 arguments"
tag = "%s_%s_SupportRequestInProgress" % (person.getUid(),
support_request_title)
if (portal.portal_activities.countMessageWithTag(tag) > 0):
# The software instance is already under creation but can not be fetched from catalog
# As it is not possible to fetch informations, it is better to raise an error
raise NotImplementedError(tag)
support_request_portal_type = "Support Request"
module = portal.getDefaultModule(portal_type=support_request_portal_type)
support_request = module.newContent(
portal_type=support_request_portal_type,
title=support_request_title,
description=description,
resource=resource,
destination_decision_value=person,
aggregate=aggregate,
specialise="sale_trade_condition_module/slapos_ticket_trade_condition",
activate_kw={'tag': tag}
)
context.REQUEST.set("support_request_relative_url", support_request.getRelativeUrl())
support_request.approveRegistration()
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
<global name="Workflow Script" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......@@ -50,11 +50,25 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
<value> <string>state_change</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>UpgradeDecision_upgradeInstanceTree</string> </value>
<value> <string>script_Person_requestSupportRequest</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Script</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Person_requestSupportRequest</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -16,12 +16,14 @@
<key> <string>categories</string> </key>
<value>
<tuple>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_request_network</string>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_notify</string>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_request_compute_node</string>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_request_network</string>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_request_organisation</string>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_request_project</string>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_request_site</string>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_request_software_instance</string>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_request_support</string>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_request_token</string>
</tuple>
</value>
......
......@@ -17,10 +17,14 @@
<value>
<tuple>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_draft</string>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_notify</string>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_request_compute_node</string>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_request_network</string>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_request_organisation</string>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_request_project</string>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_request_site</string>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_request_software_instance</string>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_request_support</string>
<string>destination/portal_workflow/person_slap_interface_workflow/transition_request_token</string>
</tuple>
</value>
......
......@@ -2,61 +2,61 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Interaction Workflow Interaction" module="erp5.portal_type"/>
<global name="Workflow Transition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>categories</string> </key>
<key> <string>action</string> </key>
<value>
<tuple>
<string>before_commit_script/portal_workflow/slapos_erp5_interaction_workflow/script_WebMessage_stopAndReopenTicket</string>
</tuple>
<none/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<key> <string>action_name</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>interaction_WebMessage_setFollowUp</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Interaction Workflow Interaction</string> </value>
</item>
<item>
<key> <string>portal_type_filter</string> </key>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>Web Message</string>
<string>action_type/workflow</string>
<string>before_script/portal_workflow/person_slap_interface_workflow/script_Person_checkConsistency</string>
<string>after_script/portal_workflow/person_slap_interface_workflow/script_Person_notify</string>
</tuple>
</value>
</item>
<item>
<key> <string>portal_type_group_filter</string> </key>
<key> <string>description</string> </key>
<value>
<tuple/>
<none/>
</value>
</item>
<item>
<key> <string>temporary_document_disallowed</string> </key>
<value> <int>0</int> </value>
<key> <string>guard_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>trigger_method_id</string> </key>
<key> <string>icon</string> </key>
<value>
<tuple>
<string>_setFollowUp*</string>
</tuple>
<none/>
</value>
</item>
<item>
<key> <string>trigger_once_per_transaction</string> </key>
<value> <int>1</int> </value>
<key> <string>id</string> </key>
<value> <string>transition_notify</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Transition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Notify</string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
......
......@@ -2,61 +2,61 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Interaction Workflow Interaction" module="erp5.portal_type"/>
<global name="Workflow Transition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>categories</string> </key>
<key> <string>action</string> </key>
<value>
<tuple>
<string>before_commit_script/portal_workflow/slapos_erp5_interaction_workflow/script_SupportRequest_createInitialWebMessage</string>
</tuple>
<none/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<key> <string>action_name</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>interaction_SupportRequest_setSpecialise</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Interaction Workflow Interaction</string> </value>
</item>
<item>
<key> <string>portal_type_filter</string> </key>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>Support Request</string>
<string>action_type/workflow</string>
<string>before_script/portal_workflow/person_slap_interface_workflow/script_Person_checkConsistency</string>
<string>after_script/portal_workflow/person_slap_interface_workflow/script_Person_requestSupportRequest</string>
</tuple>
</value>
</item>
<item>
<key> <string>portal_type_group_filter</string> </key>
<key> <string>description</string> </key>
<value>
<tuple/>
<none/>
</value>
</item>
<item>
<key> <string>temporary_document_disallowed</string> </key>
<value> <int>0</int> </value>
<key> <string>guard_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>trigger_method_id</string> </key>
<key> <string>icon</string> </key>
<value>
<tuple>
<string>_setSpecialise*</string>
</tuple>
<none/>
</value>
</item>
<item>
<key> <string>trigger_once_per_transaction</string> </key>
<value> <int>1</int> </value>
<key> <string>id</string> </key>
<value> <string>transition_request_support</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Transition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Request Support</string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
......
......@@ -7,4 +7,8 @@
<type>Regularisation Request</type>
<workflow>edit_workflow, pricing_interaction_workflow, ticket_interaction_workflow, ticket_workflow</workflow>
</chain>
<chain>
<type>Support Request</type>
<workflow>ticket_slap_interface_workflow</workflow>
</chain>
</workflow_chain>
\ No newline at end of file
......@@ -29,11 +29,12 @@ request_title = 'Allocation scope of %s changed to %s' % (compute_node_reference
request_description = 'Allocation scope has been changed to ' \
'%s for %s' % (target_allocation_scope, compute_node_reference)
support_request = context.Base_generateSupportRequestForSlapOS(
request_title,
request_description,
compute_node.getRelativeUrl()
)
person.notify(support_request_title=request_title,
support_request_description=request_description,
aggregate=context.getRelativeUrl())
support_request_relative_url = context.REQUEST.get("support_request_relative_url")
support_request = portal.restrictedTraverse(support_request_relative_url)
if support_request is not None:
if support_request.getSimulationState() != "validated":
......@@ -53,8 +54,8 @@ if support_request is not None:
message = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict': mapping_dict})
event = support_request.SupportRequest_trySendNotificationMessage(
request_title, message, person.getRelativeUrl())
support_request.notify(message_title=request_title, message=message)
event = support_request.REQUEST.get("ticket_notified_item")
if event is not None:
# event added, suspend ticket
......
from DateTime import DateTime
portal = context.getPortalObject()
if portal.ERP5Site_isSupportRequestCreationClosed():
# Stop ticket creation
return
if context.getMonitorScope() == "disabled":
person = context.getSourceAdministrationValue(portal_type="Person")
if not person or \
context.getMonitorScope() == "disabled" or \
portal.ERP5Site_isSupportRequestCreationClosed():
return
software_installation_list = portal.portal_catalog(
......@@ -50,15 +49,13 @@ for software_installation in software_installation_list:
(software_installation.getUrlString(), compute_node_title, software_installation.getCreationDate())
if should_notify:
support_request = context.Base_generateSupportRequestForSlapOS(
ticket_title,
description,
software_installation.getRelativeUrl()
)
person.notify(support_request_title=ticket_title,
support_request_description=description,
aggregate=software_installation.getRelativeUrl())
person = context.getSourceAdministrationValue(portal_type="Person")
if not person:
return support_request
support_request = context.REQUEST.get("support_request_relative_url")
if support_request is None:
return
# Send Notification message
notification_reference = 'slapos-crm-compute_node_software_installation_state.notification'
......@@ -75,10 +72,7 @@ for software_installation in software_installation_list:
message = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict':mapping_dict})
support_request.SupportRequest_trySendNotificationMessage(
ticket_title,
message, person.getRelativeUrl())
support_request.notify(message_title=ticket_title, message=message)
support_request_list.append(support_request)
return support_request_list
from DateTime import DateTime
portal = context.getPortalObject()
if portal.ERP5Site_isSupportRequestCreationClosed():
# Stop ticket creation
return
if context.getMonitorScope() == "disabled":
person = context.getSourceAdministrationValue(portal_type="Person")
if not person or \
context.getMonitorScope() == "disabled" or \
portal.ERP5Site_isSupportRequestCreationClosed():
return
if context.getAllocationScope("open").startswith("close"):
......@@ -18,7 +17,6 @@ ticket_title = "[MONITORING] Lost contact with compute_node %s" % reference
description = ""
last_contact = "No Contact Information"
d = context.getAccessStatus()
# Ignore if data isn't present.
if d.get("no_data") == 1:
......@@ -33,20 +31,19 @@ else:
# Nothing to notify.
return
support_request = context.Base_generateSupportRequestForSlapOS(
ticket_title,
description,
context.getRelativeUrl()
)
person.notify(support_request_title=ticket_title,
support_request_description=description,
aggregate=context.getRelativeUrl())
person = context.getSourceAdministrationValue(portal_type="Person")
if not person:
return support_request
support_request_relative_url = context.REQUEST.get("support_request_relative_url")
if support_request_relative_url is None:
return
support_request = portal.restrictedTraverse(support_request_relative_url)
# Send Notification message
notification_reference = 'slapos-crm-compute_node_check_state.notification'
notification_message = portal.portal_notifications.getDocumentValue(
reference=notification_reference)
reference='slapos-crm-compute_node_check_state.notification')
if notification_message is None:
message = """%s""" % description
......@@ -55,10 +52,8 @@ else:
'compute_node_id':reference,
'last_contact':last_contact}
message = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict':mapping_dict})
substitution_method_parameter_dict={'mapping_dict': mapping_dict})
support_request.SupportRequest_trySendNotificationMessage(
ticket_title,
message, person.getRelativeUrl())
support_request.notify(message_title=ticket_title, message=message)
return support_request
portal = context.getPortalObject()
person = context.getDestinationSectionValue()
if person is None or portal.ERP5Site_isSupportRequestCreationClosed(person.getRelativeUrl()):
# Stop ticket creation
return
ticket_title = "Instance Tree %s is failing." % context.getTitle()
error_message = instance.SoftwareInstance_hasReportedError(include_message=True)
......@@ -10,27 +16,23 @@ if error_message:
else:
error_message = "No message!"
support_request = context.Base_generateSupportRequestForSlapOS(
ticket_title,
description,
context.getRelativeUrl())
person.notify(support_request_title=ticket_title,
support_request_description=description,
aggregate=context.getRelativeUrl())
if support_request is None:
support_request_relative_url = context.REQUEST.get("support_request_relative_url")
if support_request_relative_url is None:
return
person = context.getDestinationSectionValue(portal_type="Person")
if not person:
return
support_request = portal.restrictedTraverse(support_request_relative_url)
if support_request.getSimulationState() not in ["validated", "suspended"]:
support_request.validate()
# Send Notification message
message = description
notification_reference = notification_message_reference
notification_message = portal.portal_notifications.getDocumentValue(
reference=notification_reference)
reference=notification_message_reference)
if notification_message is not None:
mapping_dict = {'instance_tree_title':context.getTitle(),
'instance': instance.getTitle(),
......@@ -39,5 +41,5 @@ if notification_message is not None:
message = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict':mapping_dict})
return support_request.SupportRequest_trySendNotificationMessage(
ticket_title, message, person.getRelativeUrl())
support_request.notify(message_title=ticket_title, message=message)
return context.REQUEST.get("ticket_notified_item")
""" Close Support Request which are related to a Destroy Requested Instance. """
portal = context.getPortalObject()
if context.getSimulationState() == "invalidated":
return
document = context.getAggregateValue()
if document is not None and document.getSlapState() == "destroy_requested":
person = context.getDestinationDecision(portal_type="Person")
if not person:
return
if context.getSimulationState() != "invalidated":
context.invalidate()
# Send Notification message
message = """ Closing this ticket as the Instance Tree was destroyed by the user.
"""
notification_reference = "slapos-crm-support-request-close-destroyed-notification"
portal = context.getPortalObject()
notification_message = portal.portal_notifications.getDocumentValue(
reference=notification_reference)
reference="slapos-crm-support-request-close-destroyed-notification")
if notification_message is not None:
mapping_dict = {'instance_tree_title':document.getTitle()}
mapping_dict = {'instance_tree_title': document.getTitle()}
message = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict':mapping_dict})
return context.SupportRequest_trySendNotificationMessage(
"Instance Tree was destroyed was destroyed by the user", message, person)
context.notify(message_title="Instance Tree was destroyed was destroyed by the user",
message=message)
context.invalidate()
return context.REQUEST.get("ticket_notified_item")
......@@ -2,7 +2,6 @@ if context.getSimulationState() == "invalidated":
return
document = context.getAggregateValue(portal_type="Instance Tree")
if document is None:
return
......
......@@ -27,8 +27,6 @@ from erp5.component.test.SlapOSTestCaseMixin import \
from DateTime import DateTime
from App.Common import rfc1123_date
from Products.ERP5Type.Cache import DEFAULT_CACHE_SCOPE
from Products.ERP5Type.tests.utils import createZODBPythonScript
import json
import feedparser
......@@ -655,13 +653,6 @@ class TestSlapOSComputeNode_notifyWrongAllocationScope(TestCRMSkinsMixin):
'assert reference == "slapos-crm-compute_node_allocation_scope.notification"\n' \
'return context.restrictedTraverse(' \
'context.REQUEST["test_ComputeNodeNotAllowedAllocationScope_OpenPublic"])')
@simulate('SupportRequest_trySendNotificationMessage',
'message_title, message, destination_relative_url',
'context.portal_workflow.doActionFor(' \
'context, action="edit_action", ' \
'comment="Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s" % (message_title, message, destination_relative_url))\n' \
'return 1')
def test_ComputeNodeNotAllowedAllocationScope_OpenPublic(self):
compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0]
person = compute_node.getSourceAdministrationValue()
......@@ -677,13 +668,14 @@ class TestSlapOSComputeNode_notifyWrongAllocationScope(TestCRMSkinsMixin):
self.assertNotEqual(None, ticket)
self.assertEqual(ticket.getSimulationState(), 'suspended')
self.assertEqual('Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s' % \
('Allocation scope of %s changed to %s' % (compute_node.getReference(),
'open/personal'),
'Test NM content\n%s\n' % compute_node.getReference(), person.getRelativeUrl()),
ticket.workflow_history['edit_workflow'][-1]['comment'])
event_list = ticket.getFollowUpRelatedValueList()
self.assertEqual(len(event_list), 1)
event = event_list[0]
self.assertEqual(event.getTitle(),
'Allocation scope of %s changed to %s' % (compute_node.getReference(), 'open/personal'))
self.assertIn(compute_node.getReference(), event.getTextContent())
self.assertEqual(event.getDestination(), person.getRelativeUrl())
@simulate('ERP5Site_isSupportRequestCreationClosed', '*args, **kwargs','return 0')
@simulate('NotificationTool_getDocumentValue',
......@@ -691,13 +683,6 @@ class TestSlapOSComputeNode_notifyWrongAllocationScope(TestCRMSkinsMixin):
'assert reference == "slapos-crm-compute_node_allocation_scope.notification"\n' \
'return context.restrictedTraverse(' \
'context.REQUEST["test_ComputeNodeNotAllowedAllocationScope_OpenFriend"])')
@simulate('SupportRequest_trySendNotificationMessage',
'message_title, message, destination_relative_url',
'context.portal_workflow.doActionFor(' \
'context, action="edit_action", ' \
'comment="Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s" % (message_title, message, destination_relative_url))\n' \
'return 1')
def test_ComputeNodeNotAllowedAllocationScope_OpenFriend(self):
compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0]
person = compute_node.getSourceAdministrationValue()
......@@ -712,12 +697,15 @@ class TestSlapOSComputeNode_notifyWrongAllocationScope(TestCRMSkinsMixin):
self.tic()
self.assertEqual(compute_node.getAllocationScope(), 'open/personal')
self.assertEqual(ticket.getSimulationState(), 'suspended')
self.assertEqual('Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s' % \
('Allocation scope of %s changed to %s' % (compute_node.getReference(),
'open/personal'),
'Test NM content\n%s\n' % compute_node.getReference(), person.getRelativeUrl()),
ticket.workflow_history['edit_workflow'][-1]['comment'])
event_list = ticket.getFollowUpRelatedValueList()
self.assertEqual(len(event_list), 1)
event = event_list[0]
self.assertEqual(event.getTitle(),
'Allocation scope of %s changed to %s' % (compute_node.getReference(), 'open/personal'))
self.assertIn(compute_node.getReference(), event.getTextContent())
self.assertEqual(event.getDestination(), person.getRelativeUrl())
@simulate('ERP5Site_isSupportRequestCreationClosed', '*args, **kwargs','return 0')
@simulate('ComputeNode_hasContactedRecently', '*args, **kwargs','return False')
......@@ -726,13 +714,6 @@ class TestSlapOSComputeNode_notifyWrongAllocationScope(TestCRMSkinsMixin):
'assert reference == "slapos-crm-compute-node-allocation-scope-closed.notification"\n' \
'return context.restrictedTraverse(' \
'context.REQUEST["test_ComputeNodeToCloseAllocationScope_OpenPersonal"])')
@simulate('SupportRequest_trySendNotificationMessage',
'message_title, message, destination_relative_url',
'context.portal_workflow.doActionFor(' \
'context, action="edit_action", ' \
'comment="Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s" % (message_title, message, destination_relative_url))\n' \
'return 1')
def test_ComputeNodeToCloseAllocationScope_OpenPersonal(self):
compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0]
person = compute_node.getSourceAdministrationValue()
......@@ -747,12 +728,16 @@ class TestSlapOSComputeNode_notifyWrongAllocationScope(TestCRMSkinsMixin):
self.assertEqual('suspended', support_request.getSimulationState())
self.assertEqual(compute_node.getAllocationScope(), target_allocation_scope)
self.assertEqual('Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s' % \
('Allocation scope of %s changed to %s' % (compute_node.getReference(),
target_allocation_scope),
'Test NM content\n%s\n' % compute_node.getReference(), person.getRelativeUrl()),
support_request.workflow_history['edit_workflow'][-1]['comment'])
event_list = support_request.getFollowUpRelatedValueList()
self.assertEqual(len(event_list), 1)
event = event_list[0]
self.assertEqual(event.getTitle(),
'Allocation scope of %s changed to %s' % \
(compute_node.getReference(), target_allocation_scope))
self.assertIn(compute_node.getReference(), event.getTextContent())
self.assertEqual(event.getDestination(), person.getRelativeUrl())
def test_ComputeNodeNormalAllocationScope_OpenPersonal(self):
compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0]
......@@ -988,189 +973,6 @@ class TestSlapOSisSupportRequestCreationClosed(TestCRMSkinsMixin):
self.assertFalse(self.portal.ERP5Site_isSupportRequestCreationClosed())
class TestSlapOSGenerateSupportRequestForSlapOS(TestCRMSkinsMixin):
def afterSetUp(self):
TestCRMSkinsMixin.afterSetUp(self)
self.tic()
self._cancelTestSupportRequestList()
def test_compute_node_Base_generateSupportRequestForSlapOS(self):
self._makeComputeNode()
title = "Test Support Request %s" % self.compute_node.getReference()
support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl()
)
self.tic()
self.assertNotEqual(support_request, None)
self.assertEqual(support_request.getSimulationState(), "validated")
self.assertEqual(support_request.getRelativeUrl(),
self.portal.REQUEST.get("support_request_in_progress", None))
# The support request is added to compute_node owner.
self.assertEqual(support_request.getDestinationDecision(),
self.compute_node.getSourceAdministration())
self.assertEqual(support_request.getTitle(), title)
self.assertEqual(support_request.getDescription(), title)
self.assertEqual(support_request.getAggregateValue(),
self.compute_node)
def test_software_instance_Base_generateSupportRequestForSlapOS(self):
instance_tree = self._makeInstanceTree()
self._makeSoftwareInstance(instance_tree,
self.generateNewSoftwareReleaseUrl())
instance = instance_tree.getSuccessorValue()
title = "Test Support Request %s" % instance.getReference()
support_request = instance.Base_generateSupportRequestForSlapOS(
title, title, instance.getRelativeUrl()
)
self.tic()
self.assertNotEqual(support_request, None)
self.assertEqual(support_request.getSimulationState(), "validated")
self.assertEqual(support_request.getRelativeUrl(),
self.portal.REQUEST.get("support_request_in_progress", None))
# The support request is added to compute_node owner.
self.assertEqual(support_request.getDestinationDecision(),
instance_tree.getDestinationSection())
self.assertEqual(support_request.getTitle(), title)
self.assertEqual(support_request.getDescription(), title)
self.assertEqual(support_request.getAggregateValue(),
instance)
def test_instance_tree_Base_generateSupportRequestForSlapOS(self):
instance_tree = self._makeInstanceTree()
title = "Test Support Request %s" % instance_tree.getReference()
support_request = instance_tree.Base_generateSupportRequestForSlapOS(
title, title, instance_tree.getRelativeUrl()
)
self.tic()
self.assertNotEqual(support_request, None)
self.assertEqual(support_request.getSimulationState(), "validated")
self.assertEqual(support_request.getRelativeUrl(),
self.portal.REQUEST.get("support_request_in_progress", None))
# The support request is added to compute_node owner.
self.assertEqual(support_request.getDestinationDecision(),
instance_tree.getDestinationSection())
self.assertEqual(support_request.getTitle(), title)
self.assertEqual(support_request.getDescription(), title)
self.assertEqual(support_request.getAggregateValue(),
instance_tree)
def test_software_installation_Base_generateSupportRequestForSlapOS(self):
software_installation = self._makeSoftwareInstallation()
title = "Test Support Request %s" % software_installation.generateNewId()
support_request = software_installation.Base_generateSupportRequestForSlapOS(
title, title, software_installation.getRelativeUrl()
)
self.tic()
self.assertNotEqual(support_request, None)
self.assertEqual(support_request.getSimulationState(), "validated")
self.assertEqual(support_request.getRelativeUrl(),
self.portal.REQUEST.get("support_request_in_progress", None))
# The support request is added to compute_node owner.
self.assertEqual(support_request.getDestinationDecision(),
software_installation.getDestinationSection())
self.assertEqual(support_request.getTitle(), title)
self.assertEqual(support_request.getDescription(), title)
self.assertEqual(support_request.getAggregateValue(),
software_installation)
def test_Base_generateSupportRequestForSlapOS_do_not_recreate_if_open(self):
self._makeComputeNode(owner=self.makePerson(user=0))
title = "Test Support Request %s" % self.compute_node.getReference()
support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl()
)
self.tic()
self.portal.REQUEST.set("support_request_in_progress", None)
same_support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl()
)
self.assertEqual(support_request, same_support_request)
def test_Base_generateSupportRequestForSlapOS_do_not_recreate_if_suspended(self):
self._makeComputeNode(owner=self.makePerson(user=0))
title = "Test Support Request %s" % self.compute_node.getReference()
support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl()
)
support_request.suspend()
self.tic()
self.portal.REQUEST.set("support_request_in_progress", None)
same_support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl()
)
self.assertEqual(support_request, same_support_request)
def test_Base_generateSupportRequestForSlapOS_recreate_if_closed(self):
self._makeComputeNode(owner=self.makePerson(user=0))
title = "Test Support Request %s" % self.compute_node.getReference()
support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl())
self.tic()
support_request.invalidate()
self.tic()
self.portal.REQUEST.set("support_request_in_progress", None)
support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl()
)
self.tic()
self.assertNotEqual(support_request, None)
def test_Base_generateSupportRequestForSlapOS_recreate(self):
self._makeComputeNode(owner=self.makePerson(user=0))
title = "Test Support Request %s" % self.compute_node.getRelativeUrl()
support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl())
same_support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl()
)
self.assertEqual(support_request, same_support_request)
def test_Base_generateSupportRequestForSlapOS_inprogress(self):
self._makeComputeNode(owner=self.makePerson(user=0))
title = "Test Support Request %s" % self.compute_node.getRelativeUrl()
support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl())
in_progress = support_request.getRelativeUrl()
self.portal.REQUEST.set("support_request_in_progress", in_progress)
title = "Test Support Request %s" % self.compute_node.getRelativeUrl()
support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl())
self.assertEqual(support_request.getRelativeUrl(), in_progress)
class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin):
def beforeTearDown(self):
......@@ -1181,11 +983,6 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin):
TestCRMSkinsMixin.afterSetUp(self)
self._cancelTestSupportRequestList("% TESTCOMPT-%")
def _makeSupportRequest(self):
return self.portal.restrictedTraverse(
self.portal.portal_preferences.getPreferredSupportRequestTemplate()).\
Base_createCloneDocument(batch_mode=1)
def _makeNotificationMessage(self, reference):
notification_message = self.portal.notification_message_module.newContent(
portal_type="Notification Message",
......@@ -1205,56 +1002,36 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin):
)
return support_request
def _simulateBase_generateSupportRequestForSlapOS(self):
script_name = 'Base_generateSupportRequestForSlapOS'
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, **kw',
'# Script body\n'
"""return context.getPortalObject().REQUEST['_simulateBase_generateSupportRequestForSlapOS']""")
transaction.commit()
@simulate('ERP5Site_isSupportRequestCreationClosed', '*args, **kwargs','return 0')
def test_ComputeNode_checkState_call_support_request(self):
compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0]
try:
self.pinDateTime(DateTime()-1.1)
d = DateTime() - 1.1
self.pinDateTime(d)
compute_node.setAccessStatus("#access ")
finally:
self.unpinDateTime()
self._simulateBase_generateSupportRequestForSlapOS()
support_request = self._makeSupportRequest()
self.portal.REQUEST.set('_simulateBase_generateSupportRequestForSlapOS',
support_request)
try:
compute_node_support_request = compute_node.ComputeNode_checkState()
finally:
self._dropScript("Base_generateSupportRequestForSlapOS")
self.assertEqual(support_request,
compute_node_support_request)
self.assertNotEqual(compute_node_support_request, None)
self.assertIn("[MONITORING] Lost contact with compute_node",
compute_node_support_request.getTitle())
self.assertIn("has not contacted the server for more than 30 minutes",
compute_node_support_request.getDescription())
self.assertIn(d.strftime("%Y/%m/%d %H:%M:%S"),
compute_node_support_request.getDescription())
@simulate('ERP5Site_isSupportRequestCreationClosed', '*args, **kwargs','return 0')
def test_ComputeNode_checkState_empty_cache(self):
compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0]
self._simulateBase_generateSupportRequestForSlapOS()
support_request = self._makeSupportRequest()
self.portal.REQUEST.set('_simulateBase_generateSupportRequestForSlapOS',
support_request)
try:
compute_node_support_request = compute_node.ComputeNode_checkState()
finally:
self._dropScript("Base_generateSupportRequestForSlapOS")
self.assertEqual(support_request,
compute_node_support_request)
compute_node_support_request = compute_node.ComputeNode_checkState()
self.assertNotEqual(compute_node_support_request, None)
self.assertIn("[MONITORING] Lost contact with compute_node",
compute_node_support_request.getTitle())
self.assertIn("has not contacted the server (No Contact Information)",
compute_node_support_request.getDescription())
@simulate('ERP5Site_isSupportRequestCreationClosed', '*args, **kwargs','return 0')
@simulate('NotificationTool_getDocumentValue',
......@@ -1262,12 +1039,6 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin):
'assert reference == "slapos-crm-compute_node_check_state.notification"\n' \
'return context.restrictedTraverse(' \
'context.REQUEST["test_ComputeNode_checkState_notify"])')
@simulate('SupportRequest_trySendNotificationMessage',
'message_title, message, destination_relative_url',
'context.portal_workflow.doActionFor(' \
'context, action="edit_action", ' \
'comment="Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s" % (message_title, message, destination_relative_url))')
def test_ComputeNode_checkState_notify(self):
compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0]
person = compute_node.getSourceAdministrationValue()
......@@ -1286,14 +1057,15 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin):
ticket_title = "[MONITORING] Lost contact with compute_node %s" % compute_node.getReference()
ticket = self._getGeneratedSupportRequest(compute_node.getUid(), ticket_title)
self.assertNotEqual(ticket, None)
self.assertEqual('Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s' % ( \
ticket_title,
'Test NM content\n%s\n' % compute_node.getReference(),
person.getRelativeUrl()),
ticket.workflow_history['edit_workflow'][-1]['comment'])
event_list = ticket.getFollowUpRelatedValueList()
self.assertEqual(len(event_list), 1)
event = event_list[0]
self.assertEqual(event.getTitle(), ticket.getTitle())
self.assertIn(compute_node.getReference(), event.getTextContent())
self.assertEqual(event.getDestination(), person.getRelativeUrl())
@simulate('ERP5Site_isSupportRequestCreationClosed', '*args, **kwargs','return 0')
@simulate('NotificationTool_getDocumentValue',
......@@ -1301,12 +1073,6 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin):
'assert reference == "slapos-crm-compute_node_check_state.notification"\n' \
'return context.restrictedTraverse(' \
'context.REQUEST["test_ComputeNode_checkState_empty_cache_notify"])')
@simulate('SupportRequest_trySendNotificationMessage',
'message_title, message, destination_relative_url',
'context.portal_workflow.doActionFor(' \
'context, action="edit_action", ' \
'comment="Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s" % (message_title, message, destination_relative_url))')
def test_ComputeNode_checkState_empty_cache_notify(self):
compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0]
person = compute_node.getSourceAdministrationValue()
......@@ -1320,13 +1086,13 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin):
ticket_title = "[MONITORING] Lost contact with compute_node %s" % compute_node.getReference()
ticket = self._getGeneratedSupportRequest(compute_node.getUid(), ticket_title)
self.assertNotEqual(ticket, None)
self.assertEqual('Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s' % ( \
ticket_title,
'Test NM content\n%s\n' % compute_node.getReference(),
person.getRelativeUrl()),
ticket.workflow_history['edit_workflow'][-1]['comment'])
event_list = ticket.getFollowUpRelatedValueList()
self.assertEqual(len(event_list), 1)
event = event_list[0]
self.assertEqual(event.getTitle(), ticket.getTitle())
self.assertIn(compute_node.getReference(), event.getTextContent())
self.assertEqual(event.getDestination(), person.getRelativeUrl())
class TestSlapOSInstanceTree_createSupportRequestEvent(SlapOSTestCaseMixin):
......@@ -1341,8 +1107,7 @@ class TestSlapOSInstanceTree_createSupportRequestEvent(SlapOSTestCaseMixin):
return notification_message.getRelativeUrl()
def _makeInstanceTree(self):
person = self.portal.person_module.template_member\
.Base_createCloneDocument(batch_mode=1)
person = self.makePerson(user=1)
instance_tree = self.portal\
.instance_tree_module.template_instance_tree\
.Base_createCloneDocument(batch_mode=1)
......@@ -1371,12 +1136,6 @@ class TestSlapOSInstanceTree_createSupportRequestEvent(SlapOSTestCaseMixin):
'assert reference == "test-slapos-crm-check.notification"\n' \
'return context.restrictedTraverse(' \
'context.REQUEST["testInstanceTree_createSupportRequestEvent"])')
@simulate('SupportRequest_trySendNotificationMessage',
'message_title, message, destination_relative_url',
'context.portal_workflow.doActionFor(' \
'context, action="edit_action", ' \
'comment="Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s" % (message_title, message, destination_relative_url))')
def testInstanceTree_createSupportRequestEvent(self):
instance_tree = self._makeInstanceTree()
person = instance_tree.getDestinationSectionValue()
......@@ -1392,12 +1151,14 @@ class TestSlapOSInstanceTree_createSupportRequestEvent(SlapOSTestCaseMixin):
instance_tree.getUid())
self.assertNotEqual(ticket, None)
self.assertEqual(ticket.getSimulationState(), "validated")
self.assertEqual('Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s' % ( \
ticket_title,
'Test NM content\n%s\n' % instance_tree.getReference(),
person.getRelativeUrl()),
ticket.workflow_history['edit_workflow'][-1]['comment'])
self.assertNotEqual(ticket, None)
event_list = ticket.getFollowUpRelatedValueList()
self.assertEqual(len(event_list), 1)
event = event_list[0]
self.assertEqual(event.getTitle(), ticket_title)
self.assertIn(instance_tree.getReference(), event.getTextContent())
self.assertEqual(event.getDestination(), person.getRelativeUrl())
ticket.suspend()
self.tic()
......@@ -1734,95 +1495,6 @@ class TestSlapOSHasError(SlapOSTestCaseMixin):
None,
instance_tree.InstanceTree_checkSoftwareInstanceState())
class TestSupportRequestTrySendNotificationMessage(SlapOSTestCaseMixin):
def test_SupportRequest_trySendNotificationMessage(self):
self._makeComputeNode(owner=self.makePerson(user=0))
person = self.compute_node.getSourceAdministrationValue()
title = "Test Support Request %s" % self.compute_node.getReference()
text_content='Test NM content<br/>%s<br/>' % self.compute_node.getReference()
support_request = self.portal.support_request_module.newContent(\
title=title, description=title,
destination_decision=self.compute_node.getSourceAdministration(),
aggregate_value=self.compute_node.getRelativeUrl())
support_request.validate()
self.tic()
first_event = support_request.SupportRequest_trySendNotificationMessage(
message_title=title, message=text_content,
destination_relative_url=person.getRelativeUrl()
)
self.assertNotEqual(first_event, None)
self.tic()
self.assertEqual(
support_request.getFollowUpRelatedList(),
[first_event.getRelativeUrl()])
self.assertEqual(title, first_event.getTitle())
self.assertEqual(text_content, first_event.getTextContent())
self.assertNotEqual(None, first_event.getStartDate())
self.assertEqual("service_module/slapos_crm_information",
first_event.getResource())
self.assertEqual(first_event.getDestination(), person.getRelativeUrl())
self.assertEqual(first_event.getFollowUp(), support_request.getRelativeUrl())
event = support_request.SupportRequest_trySendNotificationMessage(
message_title=title, message=text_content,
destination_relative_url=person.getRelativeUrl()
)
self.assertEqual(event, first_event)
self.assertEqual(title, event.getTitle())
self.assertEqual(text_content, event.getTextContent())
self.assertNotEqual(None, event.getStartDate())
self.assertEqual("service_module/slapos_crm_information",
event.getResource())
self.assertEqual(event.getDestination(), person.getRelativeUrl())
title += "__zz"
event = support_request.SupportRequest_trySendNotificationMessage(
message_title=title, message=text_content,
destination_relative_url=person.getRelativeUrl(),
)
self.assertEqual(event.getTitle(), title)
self.assertEqual(text_content, event.getTextContent())
self.assertNotEqual(None, event.getStartDate())
self.assertEqual("service_module/slapos_crm_information",
event.getResource())
self.assertEqual(event.getDestination(), person.getRelativeUrl())
another_support_request = self.portal.support_request_module.newContent(\
title=title, description=title,
destination_decision=self.compute_node.getSourceAdministration(),
aggregate_value=self.compute_node.getRelativeUrl())
another_support_request.validate()
self.tic()
another_first_event = \
another_support_request.SupportRequest_trySendNotificationMessage(
message_title=title, message=text_content,
destination_relative_url=person.getRelativeUrl())
self.assertNotEqual(another_first_event, None)
self.tic()
self.assertEqual(
another_support_request.getFollowUpRelatedList(),
[another_first_event.getRelativeUrl()])
self.assertEqual(title, another_first_event.getTitle())
self.assertEqual(text_content, another_first_event.getTextContent())
self.assertNotEqual(None, another_first_event.getStartDate())
self.assertEqual("service_module/slapos_crm_information",
another_first_event.getResource())
self.assertEqual(another_first_event.getDestination(), person.getRelativeUrl())
self.assertEqual(another_first_event.getFollowUp(),
another_support_request.getRelativeUrl())
class TestSupportRequestUpdateMonitoringState(SlapOSTestCaseMixin):
def _makeInstanceTree(self):
......@@ -1873,10 +1545,6 @@ class TestSupportRequestUpdateMonitoringState(SlapOSTestCaseMixin):
support_request.SupportRequest_updateMonitoringState())
@simulate('ERP5Site_isSupportRequestCreationClosed', '','return 0')
@simulate('SupportRequest_trySendNotificationMessage',
"message_title, message, source_relative_url",
"""assert "destroyed" in message
return "Visited by SupportRequest_trySendNotificationMessage %s %s" % (message_title, source_relative_url)""")
def testSupportRequest_updateMonitoringDestroyRequestedState(self):
support_request = self._makeSupportRequest()
self.assertEqual(None,
......@@ -1887,20 +1555,29 @@ return "Visited by SupportRequest_trySendNotificationMessage %s %s" % (message_t
support_request.setAggregateValue(
self._makeComputeNode(owner=self.makePerson(user=0))[0])
support_request.setDestinationDecisionValue(self.makePerson(user=0))
self.assertEqual(None,
support_request.SupportRequest_updateMonitoringDestroyRequestedState())
hs = self._makeInstanceTree()
support_request.setAggregateValue(hs)
self.tic()
hs.getSlapState = getFakeSlapState
self.commit()
support_request.setDestinationDecisionValue(self.makePerson(user=0))
expected_text = """Visited by SupportRequest_trySendNotificationMessage Instance Tree was destroyed was destroyed by the user %s""" % support_request.getDestinationDecision()
self.assertEqual(expected_text,
self.assertNotEqual(None,
support_request.SupportRequest_updateMonitoringDestroyRequestedState())
self.tic()
event_list = support_request.getFollowUpRelatedValueList()
self.assertEqual(len(event_list), 1)
event = event_list[0]
self.assertEqual(event.getTitle(), 'Instance Tree was destroyed was destroyed by the user')
self.assertEqual(event.getDestination(), support_request.getDestinationDecision())
self.assertEqual("invalidated",
support_request.getSimulationState())
......
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2002-2012 Nexedi SA and Contributors. All Rights Reserved.
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from erp5.component.test.SlapOSTestCaseMixin import SlapOSTestCaseMixin #, simulate
import transaction
class TestSlapOSCoreTicketSlapInterfaceWorkflow(SlapOSTestCaseMixin):
def afterSetUp(self):
SlapOSTestCaseMixin.afterSetUp(self)
portal = self.getPortalObject()
self.ticket_trade_condition = portal.sale_trade_condition_module.slapos_ticket_trade_condition
person_user = self.makePerson()
self.tic()
# Login as new user
self.login(person_user.getUserId())
new_person = self.portal.portal_membership.getAuthenticatedMember().getUserValue()
self.assertEqual(person_user.getRelativeUrl(), new_person.getRelativeUrl())
self.support_request = portal.support_request_module.newContent(
portal_type="Support Request",
destination_decision=person_user.getRelativeUrl(),
specialise=self.ticket_trade_condition.getRelativeUrl()
)
# Value set by the init
self.assertTrue(self.support_request.getReference().startswith("SR-"),
"Reference don't start with SR- : %s" % self.support_request.getReference())
def beforeTearDown(self):
transaction.abort()
def test_SupportRequest_approveRegistration_no_reference(self):
self.support_request.setReference(None)
self.assertRaises(ValueError, self.support_request.approveRegistration)
def test_SupportRequest_approveRegistration_already_validated(self):
# Login as admin since user cannot re-approve a validated project
self.login()
self.support_request.validate()
# Don't raise if support request is validated
self.assertEqual(self.support_request.approveRegistration(), None)
def test_SupportRequest_approveRegistration(self):
person = self.portal.portal_membership.getAuthenticatedMember().getUserValue()
self.support_request.approveRegistration()
self.tic()
self.logout()
self.login(person.getUserId())
self.assertEqual(self.support_request.getSimulationState(),
'validated')
self.assertEqual(self.support_request.getSourceSection(),
self.ticket_trade_condition.getSourceSection())
self.assertEqual(self.support_request.getSourceTrade(),
self.ticket_trade_condition.getSourceSection())
self.assertEqual(self.support_request.getSource(),
self.ticket_trade_condition.getSource())
self.assertNotEqual(self.support_request.getStartDate(),
None)
event = self.support_request.getCausalityValue()
self.assertNotEqual(event, None)
event_relative_url = self.support_request.REQUEST.get("event_relative_url")
self.assertEqual(event.getRelativeUrl(), event_relative_url)
self.assertEqual(event.getTitle(), self.support_request.getTitle())
def test_SupportRequest_requestEvent_noParameter(self):
self.assertRaises(TypeError, self.support_request.requestEvent)
self.assertRaises(TypeError, self.support_request.requestEvent, event_title="A")
self.assertRaises(TypeError, self.support_request.requestEvent, event_content="A")
def test_SupportRequest_requestEvent(self):
person = self.portal.portal_membership.getAuthenticatedMember().getUserValue()
self.support_request.approveRegistration()
self.tic()
self.logout()
self.login(person.getUserId())
self.support_request.requestEvent(
event_title="A",
event_content="B"
)
self.tic()
event_relative_url = self.support_request.REQUEST.get("event_relative_url")
event = self.portal.restrictedTraverse(event_relative_url)
self.assertEqual(event.getSimulationState(), "stopped")
self.assertEqual(self.support_request.getSimulationState(),
'validated')
self.assertEqual(self.support_request.getDestinationDecision(),
event.getSource())
self.assertEqual(person, event.getSourceValue())
self.assertEqual(self.support_request.getResource(),
event.getResource())
self.assertEqual(self.support_request,
event.getFollowUpValue())
self.assertEqual(event.getTitle(), "A")
self.assertEqual(event.getTextContent(), "B")
self.assertEqual(event.getContentType(), "text/plain")
self.assertEqual(event.getPortalType(), "Web Message")
self.assertEqual(event.getDestination(),
self.support_request.getSource())
def test_SupportRequest_notify_noParameter(self):
self.assertRaises(TypeError, self.support_request.notify)
self.assertRaises(TypeError, self.support_request.notify, message_title="A")
self.assertRaises(TypeError, self.support_request.notify, message="A")
self.assertRaises(TypeError, self.support_request.notify, destination_relative_url="A")
def test_SupportRequest_notify(self):
person = self.portal.portal_membership.getAuthenticatedMember().getUserValue()
self.support_request.approveRegistration()
self.tic()
self.logout()
self.login()
self.support_request.notify(
message_title="A",
message="B")
event = self.support_request.REQUEST.get("ticket_notified_item")
self.assertEqual(event.getSimulationState(), "delivered")
self.assertEqual(self.support_request.getSimulationState(),
'validated')
self.assertEqual(self.support_request.getDestinationDecision(),
event.getDestination())
self.assertEqual(person, event.getDestinationValue())
self.assertEqual("service_module/slapos_crm_information",
event.getResource())
self.assertEqual(self.support_request,
event.getFollowUpValue())
self.assertEqual(event.getTitle(), "A")
self.assertEqual(event.getTextContent(), "B")
self.assertEqual(event.getContentType(), "text/html")
self.assertEqual(event.getPortalType(), "Web Message")
self.assertEqual(event.getSource(),
self.support_request.getSource())
# Retry now to see if doesn't create a new message
self.support_request.notify(
message_title="A",
message="B")
self.tic()
self.assertEqual(event,
self.support_request.REQUEST.get("ticket_notified_item"))
# Retry, now it must create a new one
self.support_request.notify(
message_title="C",
message="B")
self.tic()
self.assertNotEqual(event,
self.support_request.REQUEST.get("ticket_notified_item"))
# Remove completly the ticket_notified_item and try to create a new one
# It should find it anyway from catalog.
self.support_request.REQUEST.set("ticket_notified_item", None)
self.commit()
# Retry, now it must create a new one
self.support_request.notify(
message_title="A",
message="B")
self.tic()
self.assertEqual(event,
self.support_request.REQUEST.get("ticket_notified_item"))
<?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>testSlapOSCloudTicketSlapInterfaceWorkflow</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test.erp5.testSlapOSCloudTicketSlapInterfaceWorkflow</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.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<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>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_count</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>source/portal_workflow/ticket_slap_interface_workflow/state_draft</string>
</tuple>
</value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>person_slap_interface_workflow</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ticket_slap_interface_workflow</string> </value>
</item>
<item>
<key> <string>language</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>manager_bypass</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow</string> </value>
</item>
<item>
<key> <string>state_variable</string> </key>
<value> <string>slap_state</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Ticket Slap Interface Workflow</string> </value>
</item>
<item>
<key> <string>workflow_managed_permission</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Length" module="BTrees.Length"/>
</pickle>
<pickle> <int>0</int> </pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
</ZopeData>
ticket = state_object["object"]
ticket = state_change["object"]
from DateTime import DateTime
portal = context.getPortalObject()
# XXX unhardcode the trade condition, by adding a preference
if ticket.getSpecialise() != "sale_trade_condition_module/slapos_ticket_trade_condition":
if ticket.getSimulationState() != "draft":
return
if ticket.getSimulationState() != "draft":
if ticket.getReference() in [None, ""]:
raise ValueError("Reference is missing on the Ticket")
# Get the user id of the context owner.
local_role_list = ticket.get_local_roles()
for group, role_list in local_role_list:
if 'Owner' in role_list:
user_id = group
break
person = portal.portal_catalog.getResultValue(user_id=user_id)
if person is None:
# Value was created by super user, so there isn't a point on continue
return
ticket.validate()
# XXX unhardcode the trade condition, by adding a preference
if ticket.getSpecialise() != "sale_trade_condition_module/slapos_ticket_trade_condition":
return
trade_condition = portal.sale_trade_condition_module.slapos_ticket_trade_condition
web_message = context.Ticket_createInitialEvent(state_object)
ticket.edit(
source_section = trade_condition.getSourceSection(),
source_section=trade_condition.getSourceSection(),
source_trade=trade_condition.getSourceSection(),
source=trade_condition.getSource(),
causality_value=web_message)
source=trade_condition.getSource())
ticket.setStartDate(DateTime())
# Copy original post into the original message.
web_message.edit(
title=ticket.getTitle(),
# content_type="text/plain",
text_content=ticket.getDescription(),
source=ticket.getDestinationDecision(),
# destination=trade_condition.getSource(),
# resource=ticket.getResource(),
# start_date=DateTime(),
follow_up_value=ticket,
ticket.requestEvent(
event_title=ticket.getTitle(),
event_content=ticket.getDescription()
)
event_relative_url = context.REQUEST.get("event_relative_url")
ticket.setCausality(event_relative_url)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Script" module="erp5.portal_type"/>
</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>state_change</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>script_Ticket_approveRegistration</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Script</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Ticket_approveRegistration</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>state_object</string> </value>
<value> <string>state_change</string> </value>
</item>
<item>
<key> <string>description</string> </key>
......@@ -60,7 +60,7 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>script_Ticket_createInitialEvent</string> </value>
<value> <string>script_Ticket_checkConsistency</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
......
ticket = state_change["object"]
from DateTime import DateTime
portal = ticket.getPortalObject()
# Get required arguments
kwargs = state_change.kwargs
# Required args
# Raise TypeError if all parameters are not provided
try:
message_title = kwargs['message_title']
message = kwargs['message']
except KeyError:
raise TypeError("Ticket_notify takes exactly 2 arguments")
resource = portal.service_module.slapos_crm_information.getRelativeUrl()
# create Web message if needed for this ticket
last_event = ticket.portal_catalog.getResultValue(
title=message_title,
follow_up_uid=ticket.getUid(),
sort_on=[('delivery.start_date', 'DESC')],
)
if last_event:
# User has already been notified for this problem.
ticket.REQUEST.set("ticket_notified_item", last_event)
return
transactional_event = ticket.REQUEST.get("ticket_notified_item", None)
if transactional_event is not None:
if (transactional_event.getFollowUpUid() == ticket.getUid()) and \
(transactional_event.getTitle() == message_title):
ticket.REQUEST.set("ticket_notified_item", transactional_event)
return
template = portal.restrictedTraverse(
portal.portal_preferences.getPreferredWebMessageTemplate())
event = template.Base_createCloneDocument(batch_mode=1)
event.edit(
title=message_title,
text_content=message,
start_date = DateTime(),
resource = resource,
source=ticket.getSource(),
destination=ticket.getDestinationDecision(),
follow_up=ticket.getRelativeUrl(),
)
event.stop()
event.deliver()
ticket.serialize()
ticket.REQUEST.set("ticket_notified_item", event)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Script" module="erp5.portal_type"/>
</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>state_change</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>script_Ticket_notify</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Script</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Ticket_notify</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
ticket = state_change["object"]
from DateTime import DateTime
portal = context.getPortalObject()
# Get required arguments
kwargs = state_change.kwargs
# Required args
# Raise TypeError if all parameters are not provided
try:
title = kwargs['event_title']
text_content = kwargs['event_content']
except KeyError:
raise TypeError, "Ticket_requestEvent takes exactly 2 argument"
web_message = portal.event_module.newContent(
portal_type="Web Message",
title=title,
text_content=text_content,
source=ticket.getDestinationDecision(),
content_type="text/plain",
destination=ticket.getSource(),
resource=ticket.getResource(),
follow_up=ticket.getRelativeUrl()
)
web_message.stop(comment="Submitted from the renderjs app")
if portal.portal_workflow.isTransitionPossible(ticket, "validate"):
ticket.validate(comment="See %s" % web_message.getRelativeUrl())
ticket.REQUEST.set("event_relative_url", web_message.getRelativeUrl())
......@@ -50,13 +50,14 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>state_object</string> </value>
<value> <string>state_change</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -68,7 +69,7 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>script_SupportRequest_createInitialWebMessage</string> </value>
<value> <string>script_Ticket_requestEvent</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
......@@ -76,9 +77,7 @@
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
<value> <string>Ticket_requestEvent</string> </value>
</item>
</dictionary>
</pickle>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow State" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>acquire_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>destination/portal_workflow/ticket_slap_interface_workflow/transition_approve_registration</string>
<string>destination/portal_workflow/ticket_slap_interface_workflow/transition_notify</string>
<string>destination/portal_workflow/ticket_slap_interface_workflow/transition_request_event</string>
</tuple>
</value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>state_draft</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow State</string> </value>
</item>
<item>
<key> <string>state_permission_role_list_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>state_type</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Draft</string> </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>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Transition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>action_name</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/workflow</string>
<string>before_script/portal_workflow/ticket_slap_interface_workflow/script_Ticket_checkConsistency</string>
<string>after_script/portal_workflow/ticket_slap_interface_workflow/script_Ticket_approveRegistration</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>guard_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>transition_approve_registration</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Transition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Approve Registration</string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Transition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>action_name</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/workflow</string>
<string>before_script/portal_workflow/ticket_slap_interface_workflow/script_Ticket_checkConsistency</string>
<string>after_script/portal_workflow/ticket_slap_interface_workflow/script_Ticket_notify</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>guard_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>transition_notify</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Transition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Notify</string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Transition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>action_name</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/workflow</string>
<string>before_script/portal_workflow/ticket_slap_interface_workflow/script_Ticket_checkConsistency</string>
<string>after_script/portal_workflow/ticket_slap_interface_workflow/script_Ticket_requestEvent</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>guard_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>transition_request_event</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Transition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Request Event</string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>The last transition</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_action</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</string> </key>
<value> <string>transition/getReference|nothing</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>The name of the user who performed the last transition</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_actor</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</string> </key>
<value> <string>user/getUserName</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Comments about the last transition</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_comment</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</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="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </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>id</string> </key>
<value> <string>variable_error_message</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>0</int> </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>id</string> </key>
<value> <string>variable_history</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</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="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>portal type (use as filter for worklists)</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_portal_type</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Time of the last transition</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_time</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</string> </key>
<value> <string>state_change/getDateTime</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -32,6 +32,12 @@
</tuple>
</value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>ticket_workflow</string> </value>
......
......@@ -4,3 +4,4 @@ Regularisation Request | edit_workflow
Regularisation Request | pricing_interaction_workflow
Regularisation Request | ticket_interaction_workflow
Regularisation Request | ticket_workflow
Support Request | ticket_slap_interface_workflow
\ No newline at end of file
test.erp5.testSlapOSCRMSkins
test.erp5.testSlapOSCRMRegularisationRequestSkins
test.erp5.testSlapOSCRMAlarm
test.erp5.testSlapOSCloudTicketSlapInterfaceWorkflow
\ No newline at end of file
ticket_slap_interface_workflow
ticket_workflow
\ No newline at end of file
......@@ -123,14 +123,6 @@
<type>Software Instance</type>
<workflow>local_permission_slapos_interaction_workflow</workflow>
</chain>
<chain>
<type>Support Request</type>
<workflow>slapos_erp5_interaction_workflow</workflow>
</chain>
<chain>
<type>Web Message</type>
<workflow>slapos_erp5_interaction_workflow</workflow>
</chain>
<chain>
<type>Wechat Event</type>
<workflow>local_permission_slapos_interaction_workflow</workflow>
......
# Added this script to be running as Owner
portal = context.getPortalObject()
return portal.event_module.newContent(
portal_type="Web Message",
)
web_message = state_object["object"]
portal = context.getPortalObject()
person = portal.portal_membership.getAuthenticatedMember().getUserValue()
if person is None:
return
if web_message.getSimulationState() != "draft":
return
if not web_message.hasStartDate():
web_message.setStartDate(DateTime())
# The user isn't the customer, so it is not comming from the user
# interface.
ticket = web_message.getFollowUpValue()
if ticket.getDestinationDecision() != person.getRelativeUrl():
return
# The user isn't the sender, so it is not comming from UI, but from
# an alarm.
source = web_message.getSource()
if source != person.getRelativeUrl():
return
edit_kw = {"content_type":"text/plain"}
# Copy destination and resource from ticket.
if web_message.getDestination() is None:
edit_kw["destination"] = ticket.getSource()
if web_message.getResource() is None:
edit_kw["resource"] = ticket.getResource()
web_message.edit(**edit_kw)
web_message.stop(comment="Submitted from the renderjs app")
if portal.portal_workflow.isTransitionPossible(ticket, "validate"):
ticket.validate(comment="See %s" % web_message.getRelativeUrl())
......@@ -34,6 +34,4 @@ Sale Packing List | local_permission_slapos_interaction_workflow
Slave Instance | local_permission_slapos_interaction_workflow
Software Installation | local_permission_slapos_interaction_workflow
Software Instance | local_permission_slapos_interaction_workflow
Support Request | slapos_erp5_interaction_workflow
Web Message | slapos_erp5_interaction_workflow
Wechat Event | local_permission_slapos_interaction_workflow
\ No newline at end of file
......@@ -11,9 +11,10 @@
.declareAcquiredMethod("updatePanel", "updatePanel")
.declareAcquiredMethod("jio_getAttachment", "jio_getAttachment")
.declareAcquiredMethod("getSetting", "getSetting")
.declareAcquiredMethod("getSettingList", "getSettingList")
.declareAcquiredMethod("getUrlFor", "getUrlFor")
.declareAcquiredMethod("redirect", "redirect")
.declareAcquiredMethod("jio_post", "jio_post")
.declareAcquiredMethod("jio_putAttachment", "jio_putAttachment")
.declareAcquiredMethod("jio_get", "jio_get")
.declareAcquiredMethod("notifySubmitting", "notifySubmitting")
.declareAcquiredMethod("notifySubmitted", 'notifySubmitted')
......@@ -26,6 +27,7 @@
return this.triggerSubmit();
})
.onEvent('submit', function () {
var gadget = this;
return gadget.notifySubmitting()
......@@ -33,28 +35,31 @@
return gadget.getDeclaredGadget('form_view');
})
.push(function (form_gadget) {
return form_gadget.getContent();
return RSVP.all([form_gadget.getContent(),
gadget.getSettingList(['me', 'hateoas_url'])]);
})
.push(function (content) {
var property, doc = {};
for (property in content) {
if ((content.hasOwnProperty(property)) &&
// Remove undefined keys added by Gadget fields
(property !== "undefined") &&
// Remove default_*:int keys added by ListField
!(property.endsWith(":int") && property.startsWith("default_"))) {
doc[property] = content[property];
}
}
return gadget.jio_post(doc);
.push(function (result) {
var doc = result[0],
me = result[1][0],
url = result[1][1];
return gadget.jio_putAttachment(me,
url + me + "/Person_requestSupport",
{title: doc.title,
description: doc.description,
resource: doc.resource});
})
.push(function (attachment) {
return jIO.util.readBlobAsText(attachment.target.response);
})
.push(function (key) {
.push(function (response) {
return JSON.parse(response.target.result);
})
.push(function (result) {
return gadget.notifySubmitted({message: gadget.message_translation, status: 'success'})
.push(function () {
// Workaround, find a way to open document without break gadget.
return gadget.redirect({"command": "change",
"options": {"jio_key": key, "page": "slap_controller"}});
"options": {"jio_key": result.relative_url, "page": "slap_controller"}});
});
});
})
......@@ -88,20 +93,19 @@
gadget.getDeclaredGadget('form_view'),
gadget.jio_getAttachment("ticket_resource_list",
hateoas_url + "Ticket_getResourceItemListAsJSON"),
window.getSettingMe(gadget),
gadget.getTranslationList(translation_list)
]);
})
.push(function (result) {
gadget.message_translation = result[3][0];
page_title_translation = result[3][10];
gadget.message_translation = result[2][0];
page_title_translation = result[2][10];
return result[0].render({
erp5_document: {
"_embedded": {"_view": {
"my_title": {
"description": result[3][1],
"title": result[3][2],
"description": result[2][1],
"title": result[2][2],
"default": "",
"css_class": "",
"required": 1,
......@@ -112,7 +116,7 @@
},
"my_description": {
"description": "",
"title": result[3][3],
"title": result[2][3],
"default": "",
"css_class": "",
"required": 1,
......@@ -122,8 +126,8 @@
"type": "TextAreaField"
},
"my_resource": {
"description": result[3][0],
"title": result[3][4],
"description": result[2][0],
"title": result[2][4],
"default": "",
"items": result[1],
"css_class": "",
......@@ -132,52 +136,6 @@
"key": "resource",
"hidden": 0,
"type": "ListField"
},
"my_destination_decision": {
"description": result[3][0],
"title": result[3][5],
"default": result[2],
"css_class": "",
"required": 1,
"editable": 1,
"key": "destination_decision",
"hidden": 1,
"type": "StringField"
},
"my_specialise": {
"description": "",
"title": result[3][6],
// Auto Set a hardcoded trade Condition
// Please replace it by a getSetting.
"default": "sale_trade_condition_module/slapos_ticket_trade_condition",
"css_class": "",
"required": 1,
"editable": 1,
"key": "specialise",
"hidden": 1,
"type": "StringField"
},
"my_portal_type": {
"description": result[3][0],
"title": result[3][7],
"default": "Support Request",
"css_class": "",
"required": 1,
"editable": 1,
"key": "portal_type",
"hidden": 1,
"type": "StringField"
},
"my_parent_relative_url": {
"description": "",
"title": result[3][9],
"default": "support_request_module",
"css_class": "",
"required": 1,
"editable": 1,
"key": "parent_relative_url",
"hidden": 1,
"type": "StringField"
}
}},
"_links": {
......@@ -193,7 +151,7 @@
[["my_resource"]]
], [
"center",
[["my_title"], ["my_description"], ["my_specialise"], ["my_destination_decision"], ["my_portal_type"], ["my_parent_relative_url"]]
[["my_title"], ["my_description"]]
]]
}
});
......
......@@ -279,7 +279,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>987.11835.35244.22135</string> </value>
<value> <string>997.18055.28455.10120</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -297,7 +297,7 @@
</tuple>
<state>
<tuple>
<float>1602260862.83</float>
<float>1641264462.37</float>
<string>UTC</string>
</tuple>
</state>
......
import json
portal = context.getPortalObject()
person = portal.portal_membership.getAuthenticatedMember().getUserValue()
request = context.REQUEST
response = request.RESPONSE
if person is None:
response.setStatus(403)
else:
request_kw = {"support_request_title": title,
"support_request_description": description,
"support_request_resource": resource,
"support_request_aggregate": aggregate}
person.requestSupport(**request_kw)
support_relative_url = request.get('support_request_relative_url')
response.setHeader('Content-Type', "application/json")
return json.dumps({
"relative_url": support_relative_url
})
......@@ -50,11 +50,11 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
<value> <string>title, description, resource, aggregate=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>UpgradeDecision_getComputeNode</string> </value>
<value> <string>Person_requestSupport</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -2,14 +2,10 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
<global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
......@@ -24,18 +20,6 @@
<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>
......@@ -49,12 +33,24 @@
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>expand</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>UpgradeDecision_getInstanceTree</string> </value>
<value> <string>testSlapOSJSServerTicketRelated</string> </value>
</item>
<item>
<key> <string>output_encoding</string> </key>
<value> <string>utf-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <unicode></unicode> </value>
</item>
</dictionary>
</pickle>
......
<html xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test SlapOS JS Server</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr>
<td rowspan="1" colspan="3">Test SlapOS JS Server Add related Ticket</td>
</tr>
</thead>
<tbody>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/slapos_init" />
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/set_default_available_language"/>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/slapos_login" />
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/slapos_wait_for_front_page" />
<tal:block define="document_title python: 'TEST-SLAPOSJS-COMPUTER 0';">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/create_simple_compute_node" />
</tal:block>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/slapos_wait_for_activities_and_front_page" />
<tal:block define="menu_item python: 'Servers'; header menu_item">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/access_menu_item" />
</tal:block>
<tal:block tal:define="pagination_configuration python: {'header': '(1)', 'footer': '${count} Records'};
dummy python: context.REQUEST.set('mapping', {'count': '1'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/check_listbox_pagination_text" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-COMPUTER 0"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-COMPUTER 0"]</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//a[text()="TEST-SLAPOSJS-COMPUTER 0"]</td>
<td></td>
</tr>
<tal:block tal:define="header python: 'Compute Node: ${title}';
dummy python: context.REQUEST.set('mapping', {'title': 'TEST-SLAPOSJS-COMPUTER 0'}) ">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/assert_page_header" />
</tal:block>
<tr>
<td colspan="3"><b tal:content="python: 'Add an Support Request'"> Menu Item </b></td>
</tr>
<tal:block define="menu_action python: 'Add Ticket'">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/click_submenu_action" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//input[@id="title"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//input[@id="title"]</td>
<td></td>
</tr>
<tr>
<td>type</td>
<td>//input[@id="title"]</td>
<td>TEST-SLAPOSJS-SUPPORT-REQUEST-SERVER-RELATED 0</td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//textarea[@id="description"]</td>
<td></td>
</tr>
<tr>
<td>type</td>
<td>//textarea[@id="description"]</td>
<td>TEST-SLAPOSJS-SUPPORT-REQUEST-SERVER-RELATED DESCRIPTION</td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//select[@id="resource"]</td>
<td></td>
</tr>
<tr>
<td>select</td>
<td>//select[@id="resource"]</td>
<td>Complaint</td>
</tr>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/click_proceed" />
<tal:block tal:define="notification_configuration python: {'class': 'success',
'text': 'New Ticket created.'}">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/wait_for_notification" />
</tal:block>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/wait_for_content_loaded" />
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/slapos_wait_for_activities_and_front_page" />
<tal:block define="menu_item python: 'Servers'; header menu_item">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/access_menu_item" />
</tal:block>
<tal:block tal:define="pagination_configuration python: {'header': '(1)', 'footer': '${count} Records'};
dummy python: context.REQUEST.set('mapping', {'count': '1'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/check_listbox_pagination_text" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-COMPUTER 0"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-COMPUTER 0"]</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//a[text()="TEST-SLAPOSJS-COMPUTER 0"]</td>
<td></td>
</tr>
<tal:block tal:define="pagination_configuration python: {'header': '(1)', 'footer': '${count} Records'};
dummy python: context.REQUEST.set('mapping', {'count': '1'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/check_listbox_pagination_text" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-SUPPORT-REQUEST-SERVER-RELATED 0"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-SUPPORT-REQUEST-SERVER-RELATED 0"]</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//a[text()="TEST-SLAPOSJS-SUPPORT-REQUEST-SERVER-RELATED 0"]</td>
<td></td>
</tr>
<tal:block tal:define="header python: 'Support Request : ${title}';
dummy python: context.REQUEST.set('mapping', {'title': 'TEST-SLAPOSJS-SUPPORT-REQUEST-SERVER-RELATED 0'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/assert_page_header" />
</tal:block>
<tal:block tal:define="pagination_configuration python: {'header': '(1)', 'footer': '${count} Records'};
dummy python: context.REQUEST.set('mapping', {'count': '1'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/check_listbox_pagination_text" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//div[contains(@data-gadget-url, 'gadget_slapos_event_discussion_entry.html')]//div[@class="slapos-event-discussion-message-header"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//div[contains(@data-gadget-url, 'gadget_slapos_event_discussion_entry.html')]//div[@class="slapos-event-discussion-message-header"]</td>
<td></td>
</tr>
<tr>
<td>verifyTextPresent</td>
<td>Demo User Functional</td>
<td></td>
</tr>
<tr>
<td>verifyTextPresent</td>
<td>TEST-SLAPOSJS-SUPPORT-REQUEST-SERVER-RELATED 0</td>
<td></td>
</tr>
<tr>
<td>verifyTextPresent</td>
<td>TEST-SLAPOSJS-SUPPORT-REQUEST-SERVER-RELATED DESCRIPTION</td>
<td></td>
</tr>
<tal:block tal:define="menu_action python: 'Add'">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/click_submenu_action" />
</tal:block>
<tal:block tal:define="header python: 'New Message'">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/assert_page_header" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//textarea[@id="text_content"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//textarea[@id="text_content"]</td>
<td></td>
</tr>
<tr>
<td>type</td>
<td>//textarea[@id="text_content"]</td>
<td>TEST-SLAPOSJS-SUPPORT-REQUEST-SERVER-RELATED NEW MESSAGE</td>
</tr>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/click_proceed" />
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/wait_for_content_loaded" />
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/slapos_wait_for_activities_and_front_page" />
<tal:block define="menu_item python: 'Servers'; header menu_item">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/access_menu_item" />
</tal:block>
<tal:block tal:define="pagination_configuration python: {'header': '(1)', 'footer': '${count} Records'};
dummy python: context.REQUEST.set('mapping', {'count': '1'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/check_listbox_pagination_text" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-COMPUTER 0"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-COMPUTER 0"]</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//a[text()="TEST-SLAPOSJS-COMPUTER 0"]</td>
<td></td>
</tr>
<tal:block tal:define="header python: 'Compute Node: ${title}';
dummy python: context.REQUEST.set('mapping', {'title': 'TEST-SLAPOSJS-COMPUTER 0'}) ">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/assert_page_header" />
</tal:block>
<tal:block tal:define="pagination_configuration python: {'header': '(1)', 'footer': '${count} Records'};
dummy python: context.REQUEST.set('mapping', {'count': '1'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/check_listbox_pagination_text" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-SUPPORT-REQUEST-SERVER-RELATED 0"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-SUPPORT-REQUEST-SERVER-RELATED 0"]</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//a[text()="TEST-SLAPOSJS-SUPPORT-REQUEST-SERVER-RELATED 0"]</td>
<td></td>
</tr>
<tal:block tal:define="header python: 'Support Request : ${title}';
dummy python: context.REQUEST.set('mapping', {'title': 'TEST-SLAPOSJS-SUPPORT-REQUEST-SERVER-RELATED 0'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/assert_page_header" />
</tal:block>
<tal:block tal:define="pagination_configuration python: {'header': '(2)', 'footer': '${count} Records'};
dummy python: context.REQUEST.set('mapping', {'count': '2'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/check_listbox_pagination_text" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//div[contains(@data-gadget-url, 'gadget_slapos_event_discussion_entry.html')]//div[@class="slapos-event-discussion-message-header"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//div[contains(@data-gadget-url, 'gadget_slapos_event_discussion_entry.html')]//div[@class="slapos-event-discussion-message-header"]</td>
<td></td>
</tr>
<tr>
<td>verifyTextPresent</td>
<td>TEST-SLAPOSJS-SUPPORT-REQUEST-SERVER-RELATED NEW MESSAGE</td>
<td></td>
</tr>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/slapos_wait_for_activities_and_front_page" />
<tal:block define="menu_item python: 'Servers'; header menu_item">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/access_menu_item" />
</tal:block>
<tal:block tal:define="pagination_configuration python: {'header': '(1)', 'footer': '${count} Records'};
dummy python: context.REQUEST.set('mapping', {'count': '1'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/check_listbox_pagination_text" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-COMPUTER 0"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-COMPUTER 0"]</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//a[text()="TEST-SLAPOSJS-COMPUTER 0"]</td>
<td></td>
</tr>
<tal:block tal:define="header python: 'Compute Node: ${title}';
dummy python: context.REQUEST.set('mapping', {'title': 'TEST-SLAPOSJS-COMPUTER 0'}) ">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/assert_page_header" />
</tal:block>
<tr>
<td colspan="3"><b> Update Allocation Scope</b></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//select[@id="allocation_scope"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//select[@id="allocation_scope"]</td>
<td></td>
</tr>
<tr>
<td>select</td>
<td>//select[@id="allocation_scope"]</td>
<td tal:content="python: '%s' % (here.Base_translateString('Closed forever', lang=lang))"></td>
</tr>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/save" />
<tal:block define="menu_item python: 'Servers'; header menu_item">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/access_menu_item" />
</tal:block>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/slapos_wait_for_activities_and_front_page" />
<tal:block define="menu_item python: 'Servers'; header menu_item">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/access_menu_item" />
</tal:block>
<tal:block tal:define="pagination_configuration python: {'header': '(0)', 'footer': 'No records'}">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/check_listbox_pagination_text" />
</tal:block>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/slapos_logout" />
</tbody>
</table>
</body>
</html>
\ No newline at end of file
......@@ -2,14 +2,10 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
<global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
......@@ -24,18 +20,6 @@
<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>
......@@ -49,12 +33,24 @@
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>expand</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>UpgradeDecision_upgradeComputeNode</string> </value>
<value> <string>testSlapOSJSServiceTicketRelated</string> </value>
</item>
<item>
<key> <string>output_encoding</string> </key>
<value> <string>utf-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <unicode></unicode> </value>
</item>
</dictionary>
</pickle>
......
<html xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test SlapOS JS Service</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr>
<td rowspan="1" colspan="3">Test SlapOS JS Service</td>
</tr>
</thead>
<tbody>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/slapos_init" />
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/set_default_available_language"/>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/slapos_login" />
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/slapos_wait_for_front_page" />
<tal:block define="menu_item python: 'Services'; header menu_item">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/access_menu_item" />
</tal:block>
<tal:block tal:define="pagination_configuration python: {'header': '(0)', 'footer': 'No records'}">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/check_listbox_pagination_text" />
</tal:block>
<tal:block define="menu_action python: 'Add'">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/click_submenu_action" />
</tal:block>
<tr>
<td colspan="3"><b> Request a Software </b></td>
</tr>
<tal:block define="software_product python: 'Frontend'">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/select_software_product" />
</tal:block>
<tal:block define="software_release python: 'Frontend'">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/select_software_release" />
</tal:block>
<tr>
<td colspan="3"><b> Fill Request form </b></td>
</tr>
<tal:block tal:define="header python: '3/3 Request Service: ${title}';
dummy python: context.REQUEST.set('mapping', {'title': 'Frontend'}) ">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/assert_page_header" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//input[@id="title"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//input[@id="title"]</td>
<td></td>
</tr>
<tr>
<td>type</td>
<td>//input[@id="title"]</td>
<td>TEST-SLAPOSJS-SERVICE-FRONTEND 0</td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//div[contains(@data-gadget-url,
'gadget_erp5_page_slap_parameter_form.html')]//select[@name="software_type"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//div[contains(@data-gadget-url,
'gadget_erp5_page_slap_parameter_form.html')]//select[@name="software_type"]</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//div[contains(@data-gadget-url,
'gadget_erp5_page_slap_parameter_form.html')]//select[@name="software_type"]//option[text()="Custom Personal"]
</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//div[contains(@data-gadget-url,
'gadget_erp5_page_slap_parameter_form.html')]//select[@name="software_type"]//option[text()="Custom Personal"]
</td>
<td></td>
</tr>
<tr>
<td>select</td>
<td>//div[contains(@data-gadget-url,
'gadget_erp5_page_slap_parameter_form.html')]//select[@name="software_type"]</td>
<td>Custom Personal</td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//input[@name="//domain"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//input[@name="//domain"]</td>
<td></td>
</tr>
<tr>
<td>type</td>
<td>//input[@name="//domain"]</td>
<td>www.erp5.com</td>
</tr>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/click_proceed" />
<tal:block tal:define="notification_configuration python: {'class': 'success',
'text': 'New service created.'}">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/wait_for_notification" />
</tal:block>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/slapos_wait_for_activities_and_front_page" />
<tal:block define="menu_item python: 'Services'; header menu_item">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/access_menu_item" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//div[contains(@data-gadget-url,
'gadget_slapos_panel.html')]//img[contains(@src, 'gadget_slapos_panel.png?format=png')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//div[contains(@data-gadget-url,
'gadget_slapos_panel.html')]//img[contains(@src, 'gadget_slapos_panel.png?format=png')]</td>
<td></td>
</tr>
<tal:block tal:define="pagination_configuration python: {'header': '(1)', 'footer': '${count} Records'};
dummy python: context.REQUEST.set('mapping', {'count': '1'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/check_listbox_pagination_text" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-SERVICE-FRONTEND 0"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-SERVICE-FRONTEND 0"]</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//a[text()="TEST-SLAPOSJS-SERVICE-FRONTEND 0"]</td>
<td></td>
</tr>
<tr tal:define="dummy python: context.REQUEST.set('mapping', {'title': 'TEST-SLAPOSJS-SERVICE-FRONTEND 0'})">
<td>waitForElementPresent</td>
<td tal:content="python: '//a[@data-i18n= \'%s\']' % (here.Base_translateString('Instance Tree: ${title}', mapping=context.REQUEST.get('mapping', {}), lang=lang))"></td>
<td></td>
</tr>
<tr tal:define="dummy python: context.REQUEST.set('mapping', {'title': 'TEST-SLAPOSJS-SERVICE-FRONTEND 0'})">
<td>assertElementPresent</td>
<td tal:content="python: '//a[@data-i18n= \'%s\']' % (here.Base_translateString('Instance Tree: ${title}', mapping=context.REQUEST.get('mapping', {}), lang=lang))"></td>
<td></td>
</tr>
<tr>
<td colspan="3"><b tal:content="python: 'Add an Support Request'"> Menu Item </b></td>
</tr>
<tal:block define="menu_action python: 'Add Ticket'">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/click_submenu_action" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//input[@id="title"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//input[@id="title"]</td>
<td></td>
</tr>
<tr>
<td>type</td>
<td>//input[@id="title"]</td>
<td>TEST-SLAPOSJS-SUPPORT-REQUEST-SERVICE-RELATED 0</td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//textarea[@id="description"]</td>
<td></td>
</tr>
<tr>
<td>type</td>
<td>//textarea[@id="description"]</td>
<td>TEST-SLAPOSJS-SUPPORT-REQUEST-SERVICE-RELATED DESCRIPTION</td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//select[@id="resource"]</td>
<td></td>
</tr>
<tr>
<td>select</td>
<td>//select[@id="resource"]</td>
<td>Complaint</td>
</tr>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/click_proceed" />
<tal:block tal:define="notification_configuration python: {'class': 'success',
'text': 'New Ticket created.'}">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/wait_for_notification" />
</tal:block>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/wait_for_content_loaded" />
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/slapos_wait_for_activities_and_front_page" />
<tal:block define="menu_item python: 'Services'; header menu_item">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/access_menu_item" />
</tal:block>
<tal:block tal:define="pagination_configuration python: {'header': '(1)', 'footer': '${count} Records'};
dummy python: context.REQUEST.set('mapping', {'count': '1'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/check_listbox_pagination_text" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-SERVICE-FRONTEND 0"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-SERVICE-FRONTEND 0"]</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//a[text()="TEST-SLAPOSJS-SERVICE-FRONTEND 0"]</td>
<td></td>
</tr>
<tal:block tal:define="pagination_configuration python: {'header': '(1)', 'footer': '${count} Records'};
dummy python: context.REQUEST.set('mapping', {'count': '1'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/check_listbox_pagination_text" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-SUPPORT-REQUEST-SERVICE-RELATED 0"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-SUPPORT-REQUEST-SERVICE-RELATED 0"]</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//a[text()="TEST-SLAPOSJS-SUPPORT-REQUEST-SERVICE-RELATED 0"]</td>
<td></td>
</tr>
<tal:block tal:define="header python: 'Support Request : ${title}';
dummy python: context.REQUEST.set('mapping', {'title': 'TEST-SLAPOSJS-SUPPORT-REQUEST-SERVICE-RELATED 0'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/assert_page_header" />
</tal:block>
<tal:block tal:define="pagination_configuration python: {'header': '(1)', 'footer': '${count} Records'};
dummy python: context.REQUEST.set('mapping', {'count': '1'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/check_listbox_pagination_text" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//div[contains(@data-gadget-url, 'gadget_slapos_event_discussion_entry.html')]//div[@class="slapos-event-discussion-message-header"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//div[contains(@data-gadget-url, 'gadget_slapos_event_discussion_entry.html')]//div[@class="slapos-event-discussion-message-header"]</td>
<td></td>
</tr>
<tr>
<td>verifyTextPresent</td>
<td>Demo User Functional</td>
<td></td>
</tr>
<tr>
<td>verifyTextPresent</td>
<td>TEST-SLAPOSJS-SUPPORT-REQUEST-SERVICE-RELATED 0</td>
<td></td>
</tr>
<tr>
<td>verifyTextPresent</td>
<td>TEST-SLAPOSJS-SUPPORT-REQUEST-SERVICE-RELATED DESCRIPTION</td>
<td></td>
</tr>
<tal:block tal:define="menu_action python: 'Add'">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/click_submenu_action" />
</tal:block>
<tal:block tal:define="header python: 'New Message'">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/assert_page_header" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//textarea[@id="text_content"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//textarea[@id="text_content"]</td>
<td></td>
</tr>
<tr>
<td>type</td>
<td>//textarea[@id="text_content"]</td>
<td>TEST-SLAPOSJS-SUPPORT-REQUEST-SERVICE-RELATED NEW MESSAGE</td>
</tr>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/click_proceed" />
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/wait_for_content_loaded" />
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/slapos_wait_for_activities_and_front_page" />
<tal:block define="menu_item python: 'Services'; header menu_item">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/access_menu_item" />
</tal:block>
<tal:block tal:define="pagination_configuration python: {'header': '(1)', 'footer': '${count} Records'};
dummy python: context.REQUEST.set('mapping', {'count': '1'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/check_listbox_pagination_text" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-SERVICE-FRONTEND 0"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-SERVICE-FRONTEND 0"]</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//a[text()="TEST-SLAPOSJS-SERVICE-FRONTEND 0"]</td>
<td></td>
</tr>
<tr tal:define="dummy python: context.REQUEST.set('mapping', {'title': 'TEST-SLAPOSJS-SERVICE-FRONTEND 0'})">
<td>waitForElementPresent</td>
<td tal:content="python: '//a[@data-i18n= \'%s\']' % (here.Base_translateString('Instance Tree: ${title}', mapping=context.REQUEST.get('mapping', {}), lang=lang))"></td>
<td></td>
</tr>
<tr tal:define="dummy python: context.REQUEST.set('mapping', {'title': 'TEST-SLAPOSJS-SERVICE-FRONTEND 0'})">
<td>assertElementPresent</td>
<td tal:content="python: '//a[@data-i18n= \'%s\']' % (here.Base_translateString('Instance Tree: ${title}', mapping=context.REQUEST.get('mapping', {}), lang=lang))"></td>
<td></td>
</tr>
<tal:block tal:define="pagination_configuration python: {'header': '(1)', 'footer': '${count} Records'};
dummy python: context.REQUEST.set('mapping', {'count': '1'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/check_listbox_pagination_text" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-SUPPORT-REQUEST-SERVICE-RELATED 0"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-SUPPORT-REQUEST-SERVICE-RELATED 0"]</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//a[text()="TEST-SLAPOSJS-SUPPORT-REQUEST-SERVICE-RELATED 0"]</td>
<td></td>
</tr>
<tal:block tal:define="header python: 'Support Request : ${title}';
dummy python: context.REQUEST.set('mapping', {'title': 'TEST-SLAPOSJS-SUPPORT-REQUEST-SERVICE-RELATED 0'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/assert_page_header" />
</tal:block>
<tal:block tal:define="pagination_configuration python: {'header': '(2)', 'footer': '${count} Records'};
dummy python: context.REQUEST.set('mapping', {'count': '2'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/check_listbox_pagination_text" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//div[contains(@data-gadget-url, 'gadget_slapos_event_discussion_entry.html')]//div[@class="slapos-event-discussion-message-header"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//div[contains(@data-gadget-url, 'gadget_slapos_event_discussion_entry.html')]//div[@class="slapos-event-discussion-message-header"]</td>
<td></td>
</tr>
<tr>
<td>verifyTextPresent</td>
<td>TEST-SLAPOSJS-SUPPORT-REQUEST-SERVICE-RELATED NEW MESSAGE</td>
<td></td>
</tr>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/slapos_wait_for_activities_and_front_page" />
<tal:block define="menu_item python: 'Services'; header menu_item">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/access_menu_item" />
</tal:block>
<tal:block tal:define="pagination_configuration python: {'header': '(1)', 'footer': '${count} Records'};
dummy python: context.REQUEST.set('mapping', {'count': '1'})">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/check_listbox_pagination_text" />
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-SERVICE-FRONTEND 0"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//a[text()="TEST-SLAPOSJS-SERVICE-FRONTEND 0"]</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//a[text()="TEST-SLAPOSJS-SERVICE-FRONTEND 0"]</td>
<td></td>
</tr>
<tr tal:define="dummy python: context.REQUEST.set('mapping', {'title': 'TEST-SLAPOSJS-SERVICE-FRONTEND 0'})">
<td>waitForElementPresent</td>
<td tal:content="python: '//a[@data-i18n= \'%s\']' % (here.Base_translateString('Instance Tree: ${title}', mapping=context.REQUEST.get('mapping', {}), lang=lang))"></td>
<td></td>
</tr>
<tr tal:define="dummy python: context.REQUEST.set('mapping', {'title': 'TEST-SLAPOSJS-SERVICE-FRONTEND 0'})">
<td>assertElementPresent</td>
<td tal:content="python: '//a[@data-i18n= \'%s\']' % (here.Base_translateString('Instance Tree: ${title}', mapping=context.REQUEST.get('mapping', {}), lang=lang))"></td>
<td></td>
</tr>
<tal:block define="menu_action python: 'Destroy'">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/click_submenu_action" />
</tal:block>
<tal:block tal:define="header python: 'Destroy Instance Tree: ${title}';
dummy python: context.REQUEST.set('mapping', {'title': 'TEST-SLAPOSJS-SERVICE-FRONTEND 0'}) ">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/assert_page_header" />
</tal:block>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/click_proceed" />
<tal:block tal:define="notification_configuration python: {'class': 'success',
'text': 'Service is Destroyed.'}">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/wait_for_notification" />
</tal:block>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/slapos_wait_for_activities_and_front_page" />
<tal:block define="menu_item python: 'Services'; header menu_item">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/access_menu_item" />
</tal:block>
<tal:block tal:define="pagination_configuration python: {'header': '(0)', 'footer': 'No records'}">
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/check_listbox_pagination_text" />
</tal:block>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/slapos_logout" />
</tbody>
</table>
</body>
</html>
\ No newline at end of file
......@@ -5,6 +5,6 @@
</chain>
<chain>
<type>Upgrade Decision</type>
<workflow>edit_workflow, ticket_interaction_workflow, upgrade_decision_workflow</workflow>
<workflow>edit_workflow, ticket_interaction_workflow, upgrade_decision_workflow, upgrade_slap_interface_workflow</workflow>
</chain>
</workflow_chain>
\ No newline at end of file
portal = context.getPortalObject()
portal.portal_catalog.searchAndActivate(
portal_type="Upgrade Decision Line",
simulation_state=["confirmed", "draft", "planned"],
......
......@@ -41,22 +41,18 @@ for software_release in software_release_list:
# If exist upgrade decision in progress try to cancel it
decision_in_progress = newer_release.\
SoftwareRelease_getUpgradeDecisionInProgress(compute_node.getUid())
if decision_in_progress and \
not decision_in_progress.UpgradeDecision_tryToCancel(
newer_release.getUrlString()):
if decision_in_progress:
decision_in_progress.reviewRegistration(
software_release_url=newer_release.getUrlString())
if decision_in_progress.getSimulationState() != "cancelled":
continue
upgrade_decision = newer_release.SoftwareRelease_createUpgradeDecision(
source_url=compute_node.getRelativeUrl(),
title=title)
if context.getUpgradeScope() == "auto":
upgrade_decision.start()
elif context.getUpgradeScope("ask_confirmation") == "ask_confirmation" \
and upgrade_decision.getSimulationState() != "planned":
upgrade_decision.plan()
upgrade_decision.setStartDate(DateTime())
upgrade_decision.approveRegistration(
upgrade_scope=compute_node.getUpgradeScope("ask_confirmation"))
upgrade_decision_list.append(upgrade_decision)
return upgrade_decision_list
......@@ -2,7 +2,7 @@ from DateTime import DateTime
portal = context.getPortalObject()
instance_tree = context
upgrade_scope = context.getUpgradeScope()
upgrade_scope = context.getUpgradeScope("ask_confirmation")
if upgrade_scope in ["never", "disabled"]:
return
......@@ -22,7 +22,6 @@ if instance_tree.getSlapState() == "destroy_requested":
return
tag = "%s_requestUpgradeDecisionCreation_inProgress" % instance_tree.getUid()
activate_kw = {'tag': tag}
if portal.portal_activities.countMessageWithTag(tag) > 0:
# nothing to do
return
......@@ -52,22 +51,18 @@ if newer_release is None:
decision_in_progress = newer_release.\
SoftwareRelease_getUpgradeDecisionInProgress(instance_tree.getUid())
if decision_in_progress and \
not decision_in_progress.UpgradeDecision_tryToCancel(
newer_release.getUrlString()):
if decision_in_progress:
decision_in_progress.reviewRegistration(
software_release_url=newer_release.getUrlString())
if decision_in_progress.getSimulationState() != "cancelled":
return
upgrade_decision = newer_release.SoftwareRelease_createUpgradeDecision(
source_url=instance_tree.getRelativeUrl(),
title=decision_title
)
with upgrade_decision.defaultActivateParameterDict(activate_kw):
upgrade_decision.plan()
upgrade_decision.setStartDate(DateTime())
if upgrade_scope == "auto":
upgrade_decision.start()
# Prevent concurrent transaction to create 2 upgrade decision for the same instance_tree
instance_tree.serialize()
upgrade_decision.approveRegistration(
upgrade_scope=upgrade_scope)
return upgrade_decision
instance_tree = context.getAggregateValue(portal_type="Instance Tree")
software_release = context.getAggregateValue(portal_type="Software Release")
upgrade_decision = context.getParentValue()
if upgrade_decision.getSimulationState() == "cancelled":
return
if software_release.getValidationState() == "archived":
upgrade_decision.cancel(comment="Software Release is archived.")
return
if instance_tree is not None:
if instance_tree.getUpgradeScope() in ['never', 'disabled']:
upgrade_decision.cancel("Upgrade scope was disabled on the related Instance Tree")
elif instance_tree.getSlapState() == "destroy_requested":
upgrade_decision.cancel(comment="Instance Tree is destroyed.")
elif instance_tree.getUrlString() == software_release.getUrlString():
upgrade_decision.cancel(comment="Instance tree is already upgraded.")
return
compute_node = context.getAggregateValue(portal_type="Compute Node")
if compute_node is not None:
if compute_node.getUpgradeScope() in ['never', 'disabled']:
upgrade_decision.cancel("Upgrade scope was disabled on the related Instance Tree")
return
elif compute_node.getAllocationScope() in ["closed/forever", "closed/termination"]:
upgrade_decision.cancel(comment="Compute Node is closed.")
return
already_deployed = len(context.portal_catalog(limit=1,
portal_type="Compute Partition",
parent_reference=compute_node.getReference(),
software_release_url=software_release.getUrlString()))
if already_deployed:
upgrade_decision.cancel(comment="Compute Node already has the software release")
context.getParentValue().reviewUpgrade()
document_list = []
for decision_line in context.contentValues():
try:
document_list.extend(
decision_line.getAggregateValueList(portal_type=document_portal_type))
except:
raise ValueError(context)
if len(document_list) > 1:
raise ValueError("It is only allowed to have more them 1 %s" % document_list)
if len(document_list) == 0:
return None
return document_list[0]
......@@ -50,11 +50,11 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>title, description, source_relative_url</string> </value>
<value> <string>document_portal_type="Instance Tree"</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_generateSupportRequestForSlapOS</string> </value>
<value> <string>UpgradeDecision_getAggregateValue</string> </value>
</item>
</dictionary>
</pickle>
......
compute_node_list = []
for decision_line in context.contentValues():
compute_node_list.extend(
decision_line.getAggregateValueList(portal_type="Compute Node"))
if len(compute_node_list) > 1:
raise ValueError("It is only allowed to have more them 1 Compute Node")
if len(compute_node_list) == 0:
return None
return compute_node_list[0]
instance_tree_list = []
for decision_line in context.contentValues():
instance_tree_list.extend(
decision_line.getAggregateValueList(portal_type="Instance Tree"))
if len(instance_tree_list) > 1:
raise ValueError("It is only allowed to have more them 1 Instance Tree")
if len(instance_tree_list) == 0:
return None
return instance_tree_list[0]
software_release_list = []
for decision_line in context.contentValues():
software_release_list.extend(
decision_line.getAggregateValueList(portal_type="Software Release"))
if len(software_release_list) > 1:
raise ValueError("It is only allowed to have more them 1 Software Release")
if len(software_release_list) == 0:
return None
return software_release_list[0]
portal = context.getPortalObject()
instance_tree = context.UpgradeDecision_getInstanceTree()
compute_node = context.UpgradeDecision_getComputeNode()
software_release = context.UpgradeDecision_getSoftwareRelease()
instance_tree = context.UpgradeDecision_getAggregateValue("Instance Tree")
compute_node = context.UpgradeDecision_getAggregateValue("Compute Node")
software_release = context.UpgradeDecision_getAggregateValue("Software Release")
if instance_tree is not None:
if instance_tree.getUrlString() == software_release.getUrlString():
......
from DateTime import DateTime
# Review if the upgrade is applicable before notify.
context.reviewUpgrade()
if context.getSimulationState() != 'planned':
# XXX Don't notify the ones which are not planned.
return
......@@ -10,9 +13,9 @@ person = context.getDestinationDecisionValue(portal_type="Person")
if not person:
raise ValueError("Inconsistent Upgrade Decision, No Destination Decision")
instance_tree = context.UpgradeDecision_getInstanceTree()
compute_node = context.UpgradeDecision_getComputeNode()
software_release = context.UpgradeDecision_getSoftwareRelease()
instance_tree = context.UpgradeDecision_getAggregateValue("Instance Tree")
compute_node = context.UpgradeDecision_getAggregateValue("Compute Node")
software_release = context.UpgradeDecision_getAggregateValue("Software Release")
software_product_title = software_release.getAggregateTitle(
portal_type="Software Product")
......@@ -21,8 +24,8 @@ mapping_dict = {
'software_release_name': software_release.getTitle(),
'software_release_reference': software_release.getReference(),
'new_software_release_url': software_release.getUrlString(),
}
if instance_tree is not None:
notification_message_reference = 'slapos-upgrade-instance-tree.notification'
title = "New Upgrade available for %s" % instance_tree.getTitle()
......@@ -30,11 +33,8 @@ if instance_tree is not None:
'instance_tree_title': instance_tree.getTitle(),
'old_software_release_url': instance_tree.getUrlString()})
elif compute_node is not None:
notification_message_reference = 'slapos-upgrade-compute-node.notification'
title = "New Software available for Installation at %s" % compute_node.getTitle()
mapping_dict.update(**{'compute_node_title': compute_node.getTitle(),
'compute_node_reference': compute_node.getReference()})
......@@ -49,8 +49,10 @@ notification_message = portal.portal_notifications.getDocumentValue(
message = notification_message.asEntireHTML(
substitution_method_parameter_dict={'mapping_dict': mapping_dict})
event = context.SupportRequest_trySendNotificationMessage(title,
message, person.getRelativeUrl())
context.notify(message_title=title,
message=message,
destination_relative_url=person.getRelativeUrl())
event = context.REQUEST.get("upgrade_decision_notified_item")
if event is not None:
context.confirm()
......@@ -12,9 +12,10 @@ person = context.getDestinationDecisionValue(portal_type="Person")
if not person:
raise ValueError("Inconsistent Upgrade Decision, No Destination Decision")
instance_tree = context.UpgradeDecision_getInstanceTree()
compute_node = context.UpgradeDecision_getComputeNode()
software_release = context.UpgradeDecision_getSoftwareRelease()
instance_tree = context.UpgradeDecision_getAggregateValue("Instance Tree")
compute_node = context.UpgradeDecision_getAggregateValue("Compute Node")
software_release = context.UpgradeDecision_getAggregateValue("Software Release")
software_product_title = software_release.getAggregateTitle(
portal_type="Software Product")
......@@ -51,8 +52,10 @@ notification_message = portal.portal_notifications.getDocumentValue(
message = notification_message.asEntireHTML(
substitution_method_parameter_dict={'mapping_dict': mapping_dict})
event = context.SupportRequest_trySendNotificationMessage(title,
message, person.getRelativeUrl())
context.notify(message_title=title,
message=message,
destination_relative_url=person.getRelativeUrl())
event = context.REQUEST.get("upgrade_decision_notified_item")
if event is not None:
context.setStopDate(DateTime())
......
if context.UpgradeDecision_upgradeInstanceTree():
return True
if context.UpgradeDecision_upgradeComputeNode():
return True
return False
return context.requestUpgrade()
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>**kw</string> </value>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
......
<?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>new_url_string</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>UpgradeDecision_tryToCancel</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
if context.getSimulationState() != 'started':
# Update Decision is not on started state, Upgrade is not possible!
return False
compute_node = context.UpgradeDecision_getComputeNode()
software_release = context.UpgradeDecision_getSoftwareRelease()
if compute_node is None:
return False
if software_release is None:
return False
software_release_url = software_release.getUrlString()
compute_node.requestSoftwareRelease(
software_release_url=software_release_url,
state="available")
context.stop()
return True
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2002-2012 Nexedi SA and Contributors. All Rights Reserved.
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from erp5.component.test.SlapOSTestCaseMixin import SlapOSTestCaseMixin, simulate
#from zExceptions import Unauthorized
import transaction
class TestSlapOSCoreProjectSlapInterfaceWorkflow(SlapOSTestCaseMixin):
def afterSetUp(self):
SlapOSTestCaseMixin.afterSetUp(self)
portal = self.getPortalObject()
person_user = self.makePerson()
self.tic()
self.login()
self.compute_node = self.portal.compute_node_module.template_compute_node\
.Base_createCloneDocument(batch_mode=1)
new_id = self.generateNewId()
self.compute_node.edit(
title="compute node %s" % (new_id, ),
reference="TESTCOMP-%s" % (new_id, ),
source_administration=person_user.getRelativeUrl()
)
self.compute_node.validate()
self.upgrade_decision = portal.upgrade_decision_module.newContent(
portal_type="Upgrade Decision",
)
# Value set by the init
self.assertTrue(self.upgrade_decision.getReference().startswith("UD-"),
"Reference don't start with UD- : %s" % self.upgrade_decision.getReference())
self.software_release = self._makeSoftwareRelease()
self.tic()
def _addUpgradeLine(self, aggregate):
self.upgrade_decision.newContent(
portal_type="Upgrade Decision Line",
aggregate_value_list=[self.software_release,
aggregate]
)
def beforeTearDown(self):
transaction.abort()
def test_upgrade_decision_approveRegistration_no_line(self):
self.assertRaises(ValueError, self.upgrade_decision.approveRegistration)
def test_upgrade_decision_approveRegistration_no_aggregate(self):
self.upgrade_decision.newContent(
portal_type="Upgrade Decision Line",
aggregate=self.software_release.getRelativeUrl()
)
self.assertRaises(ValueError, self.upgrade_decision.approveRegistration)
def test_upgrade_decision_approveRegistration_no_upgrade_scope(self):
self._addUpgradeLine(self.compute_node)
self.assertRaises(TypeError, self.upgrade_decision.approveRegistration)
def test_upgrade_decision_approveRegistration_computer(self):
self._addUpgradeLine(self.compute_node)
self.upgrade_decision.approveRegistration(
upgrade_scope="ask_confirmation"
)
self.assertEqual("planned",
self.upgrade_decision.getSimulationState())
self.commit()
tag = "%s_requestUpgradeDecisionCreation_inProgress" % self.compute_node.getUid()
self.assertEqual(2,
self.portal.portal_activities.countMessageWithTag(tag))
# Call again does nothing
self.upgrade_decision.approveRegistration(
upgrade_scope="ask_confirmation"
)
self.assertEqual("planned",
self.upgrade_decision.getSimulationState())
self.commit()
tag = "%s_requestUpgradeDecisionCreation_inProgress" % self.compute_node.getUid()
self.assertEqual(2,
self.portal.portal_activities.countMessageWithTag(tag))
self.tic()
# Call again does nothing again
self.upgrade_decision.approveRegistration(
upgrade_scope="ask_confirmation"
)
self.assertEqual("planned",
self.upgrade_decision.getSimulationState())
self.commit()
tag = "%s_requestUpgradeDecisionCreation_inProgress" % self.compute_node.getUid()
self.assertEqual(2,
self.portal.portal_activities.countMessageWithTag(tag))
def test_upgrade_decision_approveRegistration_instance_tree(self):
self._makeTree()
self._addUpgradeLine(self.instance_tree)
self.upgrade_decision.approveRegistration(
upgrade_scope="ask_confirmation"
)
self.assertEqual("planned",
self.upgrade_decision.getSimulationState())
self.commit()
tag = "%s_requestUpgradeDecisionCreation_inProgress" % self.instance_tree.getUid()
self.assertEqual(2,
self.portal.portal_activities.countMessageWithTag(tag))
# Call again does nothing
self.upgrade_decision.approveRegistration(
upgrade_scope="ask_confirmation"
)
self.assertEqual("planned",
self.upgrade_decision.getSimulationState())
self.commit()
tag = "%s_requestUpgradeDecisionCreation_inProgress" % self.instance_tree.getUid()
self.assertEqual(2,
self.portal.portal_activities.countMessageWithTag(tag))
self.tic()
# Call again does nothing again
self.upgrade_decision.approveRegistration(
upgrade_scope="ask_confirmation"
)
self.assertEqual("planned",
self.upgrade_decision.getSimulationState())
self.commit()
tag = "%s_requestUpgradeDecisionCreation_inProgress" % self.instance_tree.getUid()
self.assertEqual(2,
self.portal.portal_activities.countMessageWithTag(tag))
def test_upgrade_decision_approveRegistration_computer_auto(self):
self._addUpgradeLine(self.compute_node)
self.upgrade_decision.approveRegistration(
upgrade_scope="auto"
)
self.assertEqual("started",
self.upgrade_decision.getSimulationState())
self.commit()
tag = "%s_requestUpgradeDecisionCreation_inProgress" % self.compute_node.getUid()
self.assertEqual(2,
self.portal.portal_activities.countMessageWithTag(tag))
# Call again does nothing
self.upgrade_decision.approveRegistration(
upgrade_scope="auto"
)
self.assertEqual("started",
self.upgrade_decision.getSimulationState())
self.commit()
tag = "%s_requestUpgradeDecisionCreation_inProgress" % self.compute_node.getUid()
self.assertEqual(2,
self.portal.portal_activities.countMessageWithTag(tag))
self.tic()
# Call again does nothing again
self.upgrade_decision.approveRegistration(
upgrade_scope="auto"
)
self.assertEqual("started",
self.upgrade_decision.getSimulationState())
self.commit()
tag = "%s_requestUpgradeDecisionCreation_inProgress" % self.compute_node.getUid()
self.assertEqual(2,
self.portal.portal_activities.countMessageWithTag(tag))
def test_upgrade_decision_approveRegistration_instance_tree_auto(self):
self._makeTree()
self._addUpgradeLine(self.instance_tree)
self.upgrade_decision.approveRegistration(
upgrade_scope="auto"
)
self.assertEqual("started",
self.upgrade_decision.getSimulationState())
self.commit()
tag = "%s_requestUpgradeDecisionCreation_inProgress" % self.instance_tree.getUid()
self.assertEqual(2,
self.portal.portal_activities.countMessageWithTag(tag))
# Call again does nothing
self.upgrade_decision.approveRegistration(
upgrade_scope="auto"
)
self.assertEqual("started",
self.upgrade_decision.getSimulationState())
self.commit()
tag = "%s_requestUpgradeDecisionCreation_inProgress" % self.instance_tree.getUid()
self.assertEqual(2,
self.portal.portal_activities.countMessageWithTag(tag))
self.tic()
# Call again does nothing again
# Call again does nothing
self.upgrade_decision.approveRegistration(
upgrade_scope="auto"
)
self.assertEqual("started",
self.upgrade_decision.getSimulationState())
self.commit()
tag = "%s_requestUpgradeDecisionCreation_inProgress" % self.instance_tree.getUid()
self.assertEqual(2,
self.portal.portal_activities.countMessageWithTag(tag))
def test_upgrade_decision_reviewRegistration_no_software_release_url(self):
self.assertRaises(TypeError, self.upgrade_decision.reviewRegistration)
def test_upgrade_decision_reviewRegistration_draft(self):
# Do nothing as draft
software_release = self.generateNewSoftwareReleaseUrl()
self.upgrade_decision.reviewRegistration(software_release_url=software_release)
def test_upgrade_decision_reviewRegistration(self):
self._addUpgradeLine(self.compute_node)
software_release = self.generateNewSoftwareReleaseUrl()
self.upgrade_decision.reviewRegistration(
software_release_url=software_release)
self.assertEqual("draft",
self.upgrade_decision.getSimulationState())
self.upgrade_decision.plan()
self.tic()
self.upgrade_decision.reviewRegistration(
software_release_url=software_release)
self.assertEqual("cancelled",
self.upgrade_decision.getSimulationState())
def test_upgrade_decision_reviewRegistration_confirm(self):
self._addUpgradeLine(self.compute_node)
software_release = self.generateNewSoftwareReleaseUrl()
self.upgrade_decision.reviewRegistration(
software_release_url=software_release)
self.assertEqual("draft",
self.upgrade_decision.getSimulationState())
self.upgrade_decision.confirm()
self.tic()
self.upgrade_decision.reviewRegistration(
software_release_url=software_release)
self.assertEqual("cancelled",
self.upgrade_decision.getSimulationState())
def test_upgrade_decision_reviewRegistration_rejected(self):
self._addUpgradeLine(self.compute_node)
software_release = self.generateNewSoftwareReleaseUrl()
self.upgrade_decision.reviewRegistration(
software_release_url=software_release)
self.assertEqual("draft",
self.upgrade_decision.getSimulationState())
self.upgrade_decision.reject()
self.tic()
self.upgrade_decision.reviewRegistration(
software_release_url=software_release)
self.assertEqual("rejected",
self.upgrade_decision.getSimulationState())
def test_upgrade_decision_reviewRegistration_same_url(self):
self._addUpgradeLine(self.compute_node)
self.upgrade_decision.reviewRegistration(
software_release_url=self.software_release.getUrlString())
self.assertEqual("draft",
self.upgrade_decision.getSimulationState())
self.upgrade_decision.plan()
self.tic()
self.upgrade_decision.reviewRegistration(
software_release_url=self.software_release.getUrlString())
self.assertEqual("planned",
self.upgrade_decision.getSimulationState())
def test_upgrade_decision_reviewRegistration_confirm_same_url(self):
self._addUpgradeLine(self.compute_node)
self.upgrade_decision.reviewRegistration(
software_release_url=self.software_release.getUrlString())
self.assertEqual("draft",
self.upgrade_decision.getSimulationState())
self.upgrade_decision.confirm()
self.tic()
self.upgrade_decision.reviewRegistration(
software_release_url=self.software_release.getUrlString())
self.assertEqual("confirmed",
self.upgrade_decision.getSimulationState())
def test_upgrade_decision_reviewRegistration_rejected_same_url(self):
self._addUpgradeLine(self.compute_node)
self.upgrade_decision.reviewRegistration(
software_release_url=self.software_release.getUrlString())
self.assertEqual("draft",
self.upgrade_decision.getSimulationState())
self.upgrade_decision.reject()
self.tic()
self.upgrade_decision.reviewRegistration(
software_release_url=self.software_release.getUrlString())
self.assertEqual("rejected",
self.upgrade_decision.getSimulationState())
def test_upgrade_decision_reviewRegistration_started(self):
self._addUpgradeLine(self.compute_node)
software_release = self.generateNewSoftwareReleaseUrl()
self.upgrade_decision.reviewRegistration(
software_release_url=software_release)
self.assertEqual("draft",
self.upgrade_decision.getSimulationState())
self.upgrade_decision.plan()
self.upgrade_decision.start()
self.tic()
self.upgrade_decision.reviewRegistration(
software_release_url=software_release)
self.assertEqual("started",
self.upgrade_decision.getSimulationState())
def test_upgrade_decision_reviewRegistration_instance_tree(self):
self._makeTree()
self._addUpgradeLine(self.instance_tree)
self.upgrade_decision.reviewRegistration(
software_release_url=self.instance_tree.getUrlString())
self.assertEqual("draft",
self.upgrade_decision.getSimulationState())
self.upgrade_decision.plan()
self.tic()
self.upgrade_decision.reviewRegistration(
software_release_url=self.instance_tree.getUrlString())
self.assertEqual("cancelled",
self.upgrade_decision.getSimulationState())
def test_upgrade_decision_reviewRegistration_instance_tree_confirmed(self):
self._makeTree()
self._addUpgradeLine(self.instance_tree)
self.upgrade_decision.reviewRegistration(
software_release_url=self.instance_tree.getUrlString())
self.assertEqual("draft",
self.upgrade_decision.getSimulationState())
self.upgrade_decision.confirm()
self.tic()
self.upgrade_decision.reviewRegistration(
software_release_url=self.instance_tree.getUrlString())
self.assertEqual("cancelled",
self.upgrade_decision.getSimulationState())
def test_upgrade_decision_reviewRegistration_instance_tree_started(self):
self._makeTree()
self._addUpgradeLine(self.instance_tree)
self.upgrade_decision.reviewRegistration(
software_release_url=self.instance_tree.getUrlString())
self.assertEqual("draft",
self.upgrade_decision.getSimulationState())
self.upgrade_decision.start()
self.tic()
self.upgrade_decision.reviewRegistration(
software_release_url=self.instance_tree.getUrlString())
self.assertEqual("started",
self.upgrade_decision.getSimulationState())
@simulate('InstanceTree_isUpgradePossible',
'software_release_url', 'return 1')
def test_upgrade_decision_requestUpgrade_instance_tree(self):
self._makeTree()
self._addUpgradeLine(self.instance_tree)
self.tic()
slap_state = self.instance_tree.getSlapState()
self.upgrade_decision.requestUpgrade()
self.assertNotEqual(self.software_release.getUrlString(),
self.instance_tree.getUrlString())
self.upgrade_decision.confirm()
self.upgrade_decision.start()
# Check that url_string change, but slap state doesn't
self.assertNotEqual(self.software_release.getUrlString(),
self.instance_tree.getUrlString())
self.upgrade_decision.requestUpgrade()
self.assertEqual(self.software_release.getUrlString(),
self.instance_tree.getUrlString())
self.assertEqual(slap_state, self.instance_tree.getSlapState())
self.assertEqual('stopped', self.upgrade_decision.getSimulationState())
def test_upgrade_decision_requestUpgrade_instance_tree_no_software_release(self):
self._makeTree()
self.upgrade_decision.newContent(
portal_type="Upgrade Decision Line",
aggregate_value_list=[self.instance_tree]
)
self.upgrade_decision.confirm()
self.upgrade_decision.start()
self.tic()
self.upgrade_decision.requestUpgrade()
self.assertEqual('started', self.upgrade_decision.getSimulationState())
def test_upgrade_decision_requestUpgrade_compute_node_no_software_release(self):
self.upgrade_decision.newContent(
portal_type="Upgrade Decision Line",
aggregate_value_list=[self.compute_node]
)
self.upgrade_decision.confirm()
self.upgrade_decision.start()
self.tic()
self.upgrade_decision.requestUpgrade()
self.assertEqual('started', self.upgrade_decision.getSimulationState())
def test_upgrade_decision_requestUpgrade_only_software_release(self):
self.upgrade_decision.newContent(
portal_type="Upgrade Decision Line",
aggregate_value_list=[self.software_release]
)
self.upgrade_decision.confirm()
self.upgrade_decision.start()
self.tic()
self.upgrade_decision.requestUpgrade()
self.assertEqual('started', self.upgrade_decision.getSimulationState())
def test_upgrade_decision_requestUpgrade_duplicated(self):
self._makeTree()
self.upgrade_decision.newContent(
portal_type="Upgrade Decision Line",
aggregate_value_list=[
self.software_release,
self.instance_tree,
self.compute_node]
)
self.upgrade_decision.confirm()
self.upgrade_decision.start()
self.tic()
self.assertRaises(ValueError, self.upgrade_decision.requestUpgrade)
self.assertEqual('started', self.upgrade_decision.getSimulationState())
def test_upgrade_decision_requestUpgrade_compute_node(self):
self._addUpgradeLine(self.compute_node)
self.upgrade_decision.confirm()
self.upgrade_decision.start()
self.tic()
self.upgrade_decision.requestUpgrade()
self.tic()
self.assertEqual('stopped', self.upgrade_decision.getSimulationState())
software_installation = self.compute_node.getAggregateRelatedValue(
portal_type='Software Installation')
self.assertEqual('start_requested', software_installation.getSlapState())
self.assertEqual(self.software_release.getUrlString(),
software_installation.getUrlString())
self.assertEqual('validated', software_installation.getValidationState())
@simulate('InstanceTree_isUpgradePossible',
'software_release_url', 'return 0')
def test_upgrade_decision_requestUpgrade_instance_tree_not_possible(self):
self._makeTree()
self._addUpgradeLine(self.instance_tree)
self.assertNotEqual(self.instance_tree.getUrlString(),
self.software_release.getUrlString())
slap_state = self.instance_tree.getSlapState()
self.upgrade_decision.confirm()
self.upgrade_decision.start()
self.tic()
self.upgrade_decision.requestUpgrade()
self.tic()
self.assertEqual('started', self.upgrade_decision.getSimulationState())
self.assertNotEqual(self.instance_tree.getUrlString(),
self.software_release.getUrlString())
self.assertEqual(slap_state,
self.instance_tree.getSlapState())
<?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>testSlapOSCloudUpgradeSlapInterfaceWorkflow</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test.erp5.testSlapOSCloudUpgradeSlapInterfaceWorkflow</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.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<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>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -284,11 +284,12 @@ class TestSlapOSPDMCreateUpgradeDecisionSkins(TestSlapOSPDMMixinSkins):
self.assertNotEqual(up_decision, None)
self.assertEqual(up_decision.getSimulationState(), 'planned')
self.assertEqual(up_decision.UpgradeDecision_getInstanceTree().\
self.assertEqual(up_decision.UpgradeDecision_getAggregateValue("Instance Tree").\
getReference(), instance_tree.getReference())
self.assertEqual(up_decision.UpgradeDecision_getSoftwareRelease().\
getUrlString(), software_release2.getUrlString())
self.assertEqual(software_release2.getUrlString(),
up_decision.UpgradeDecision_getAggregateValue("Software Release").\
getUrlString())
self.tic()
up_decision2 = instance_tree.InstanceTree_createUpgradeDecision()
......@@ -331,7 +332,7 @@ class TestSlapOSPDMCreateUpgradeDecisionSkins(TestSlapOSPDMMixinSkins):
up_decision2 = instance_tree.InstanceTree_createUpgradeDecision()
self.assertEqual(up_decision2.getSimulationState(), 'planned')
self.assertEqual(up_decision.getSimulationState(), 'cancelled')
release = up_decision2.UpgradeDecision_getSoftwareRelease()
release = up_decision2.UpgradeDecision_getAggregateValue("Software Release")
self.assertEqual(release.getUrlString(),
software_release3.getUrlString())
......@@ -414,7 +415,7 @@ class TestSlapOSPDMCreateUpgradeDecisionSkins(TestSlapOSPDMMixinSkins):
decision2 = instance_tree.InstanceTree_createUpgradeDecision()
self.assertEqual(decision2.getSimulationState(), 'planned')
self.assertEqual(up_decision.getSimulationState(), 'rejected')
release = decision2.UpgradeDecision_getSoftwareRelease()
release = decision2.UpgradeDecision_getAggregateValue("Software Release")
self.assertEqual(release.getUrlString(),
software_release3.getUrlString())
\ No newline at end of file
......@@ -338,7 +338,7 @@ class TestSlapOSPDMSkins(TestSlapOSPDMMixinSkins):
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValue(compute_node)
found_compute_node = upgrade_decision.UpgradeDecision_getComputeNode()
found_compute_node = upgrade_decision.UpgradeDecision_getAggregateValue("Compute Node")
self.assertEqual(compute_node.getRelativeUrl(),
found_compute_node.getRelativeUrl())
......@@ -351,7 +351,7 @@ class TestSlapOSPDMSkins(TestSlapOSPDMMixinSkins):
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
found_compute_node = upgrade_decision.UpgradeDecision_getComputeNode()
found_compute_node = upgrade_decision.UpgradeDecision_getAggregateValue("Compute Node")
self.assertEqual(compute_node.getRelativeUrl(),
found_compute_node.getRelativeUrl())
......@@ -365,13 +365,14 @@ class TestSlapOSPDMSkins(TestSlapOSPDMMixinSkins):
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValue(compute_node)
self.assertRaises(ValueError, upgrade_decision.UpgradeDecision_getComputeNode)
self.assertRaises(ValueError, upgrade_decision.UpgradeDecision_getAggregateValue,
document_portal_type="Compute Node")
def testUpgradeDecision_getComputeNode_O_compute_node(self):
upgrade_decision = self._makeUpgradeDecision()
self._makeUpgradeDecisionLine(upgrade_decision)
found_compute_node = upgrade_decision.UpgradeDecision_getComputeNode()
found_compute_node = upgrade_decision.UpgradeDecision_getAggregateValue("Compute Node")
self.assertEqual(None, found_compute_node)
......@@ -382,7 +383,7 @@ class TestSlapOSPDMSkins(TestSlapOSPDMMixinSkins):
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValue(instance_tree)
found_instance_tree = upgrade_decision.UpgradeDecision_getInstanceTree()
found_instance_tree = upgrade_decision.UpgradeDecision_getAggregateValue("Instance Tree")
self.assertEqual(instance_tree.getRelativeUrl(),
found_instance_tree.getRelativeUrl())
......@@ -396,7 +397,7 @@ class TestSlapOSPDMSkins(TestSlapOSPDMMixinSkins):
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
found_instance_tree = upgrade_decision.UpgradeDecision_getInstanceTree()
found_instance_tree = upgrade_decision.UpgradeDecision_getAggregateValue("Instance Tree")
self.assertEqual(instance_tree.getRelativeUrl(),
found_instance_tree.getRelativeUrl())
......@@ -411,28 +412,29 @@ class TestSlapOSPDMSkins(TestSlapOSPDMMixinSkins):
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValue(instance_tree)
self.assertRaises(ValueError, upgrade_decision.UpgradeDecision_getInstanceTree)
self.assertRaises(ValueError, upgrade_decision.UpgradeDecision_getAggregateValue,
document_portal_type="Instance Tree")
def testUpgradeDecision_getInstanceTree_O_hosting(self):
upgrade_decision = self._makeUpgradeDecision()
self._makeUpgradeDecisionLine(upgrade_decision)
found_instance_tree = upgrade_decision.UpgradeDecision_getInstanceTree()
found_instance_tree = upgrade_decision.UpgradeDecision_getAggregateValue("Instance Tree")
self.assertEqual(None, found_instance_tree)
def testUpgradeDecision_getSoftwareRelease(self):
def testUpgradeDecision_getAggregateValue_SoftwareRelease(self):
software_release = self._makeSoftwareRelease()
upgrade_decision = self._makeUpgradeDecision()
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValue(software_release)
found_software_release = upgrade_decision.UpgradeDecision_getSoftwareRelease()
found_software_release = upgrade_decision.UpgradeDecision_getAggregateValue("Software Release")
self.assertEqual(software_release.getRelativeUrl(),
found_software_release.getRelativeUrl())
def testUpgradeDecision_getSoftwareRelease_2_lines(self):
def testUpgradeDecision_getAggregateValue_SoftwareRelease_2_lines(self):
software_release = self._makeSoftwareRelease()
upgrade_decision = self._makeUpgradeDecision()
......@@ -441,11 +443,11 @@ class TestSlapOSPDMSkins(TestSlapOSPDMMixinSkins):
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
found_software_release = upgrade_decision.UpgradeDecision_getSoftwareRelease()
found_software_release = upgrade_decision.UpgradeDecision_getAggregateValue("Software Release")
self.assertEqual(software_release.getRelativeUrl(),
found_software_release.getRelativeUrl())
def testUpgradeDecision_getSoftwareRelease_2_sr(self):
def testUpgradeDecision_getAggregateValue_SoftwareRelease_2_sr(self):
software_release = self._makeSoftwareRelease()
upgrade_decision = self._makeUpgradeDecision()
......@@ -455,212 +457,16 @@ class TestSlapOSPDMSkins(TestSlapOSPDMMixinSkins):
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValue(software_release)
self.assertRaises(ValueError, upgrade_decision.UpgradeDecision_getSoftwareRelease)
self.assertRaises(ValueError, upgrade_decision.UpgradeDecision_getAggregateValue,
document_portal_type="Software Release")
def testUpgradeDecision_getSoftwareRelease_O_sr(self):
def testUpgradeDecision_getAggregateValue_SoftwareRelease_O_sr(self):
upgrade_decision = self._makeUpgradeDecision()
self._makeUpgradeDecisionLine(upgrade_decision)
found_software_release = upgrade_decision.UpgradeDecision_getSoftwareRelease()
found_software_release = upgrade_decision.UpgradeDecision_getAggregateValue("Software Release")
self.assertEqual(None, found_software_release)
@simulate('InstanceTree_isUpgradePossible',
'software_release_url', 'return 1')
def testUpgradeDecision_upgradeInstanceTree(self):
person = self._makePerson()
instance_tree = self._makeInstanceTree()
instance_tree.edit(
destination_section_value = person.getRelativeUrl())
self._makeSoftwareInstance(instance_tree,
instance_tree.getUrlString())
software_release = self._makeSoftwareRelease()
upgrade_decision = self._makeUpgradeDecision()
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValueList(
[software_release, instance_tree])
self.tic()
slap_state = instance_tree.getSlapState()
self.assertFalse(upgrade_decision.UpgradeDecision_upgradeInstanceTree())
self.assertNotEqual(software_release.getUrlString(),
instance_tree.getUrlString())
upgrade_decision.confirm()
upgrade_decision.start()
# Check that url_string change, but slap state doesn't
self.assertNotEqual(software_release.getUrlString(),
instance_tree.getUrlString())
self.assertTrue(upgrade_decision.UpgradeDecision_upgradeInstanceTree())
self.assertEqual(software_release.getUrlString(),
instance_tree.getUrlString())
self.assertEqual(slap_state, instance_tree.getSlapState())
self.assertEqual('stopped', upgrade_decision.getSimulationState())
@simulate('InstanceTree_isUpgradePossible',
'software_release_url', 'return 1')
def testUpgradeDecision_processUpgradeeInstanceTree(self):
person = self._makePerson()
instance_tree = self._makeInstanceTree()
instance_tree.edit(
destination_section_value = person.getRelativeUrl())
self._makeSoftwareInstance(instance_tree,
instance_tree.getUrlString())
software_release = self._makeSoftwareRelease()
upgrade_decision = self._makeUpgradeDecision()
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValueList(
[software_release, instance_tree])
self.tic()
slap_state = instance_tree.getSlapState()
self.assertFalse(upgrade_decision.UpgradeDecision_processUpgrade())
self.assertNotEqual(software_release.getUrlString(),
instance_tree.getUrlString())
upgrade_decision.confirm()
upgrade_decision.start()
# Check that url_string change, but slap state doesn't
self.assertNotEqual(software_release.getUrlString(),
instance_tree.getUrlString())
self.assertTrue(upgrade_decision.UpgradeDecision_processUpgrade())
self.assertEqual(software_release.getUrlString(),
instance_tree.getUrlString())
self.assertEqual(slap_state, instance_tree.getSlapState())
self.assertEqual('stopped', upgrade_decision.getSimulationState())
def testUpgradeDecision_upgradeInstanceTree_no_software_release(self):
person = self._makePerson()
instance_tree = self._makeInstanceTree()
instance_tree.edit(
destination_section_value = person.getRelativeUrl())
self._makeSoftwareInstance(instance_tree,
instance_tree.getUrlString())
upgrade_decision = self._makeUpgradeDecision()
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValueList([instance_tree])
self.tic()
upgrade_decision.confirm()
upgrade_decision.start()
self.assertFalse(upgrade_decision.UpgradeDecision_upgradeInstanceTree())
self.assertEqual('started', upgrade_decision.getSimulationState())
def testUpgradeDecision_upgradeInstanceTree_no_hosting_subscripion(self):
software_release = self._makeSoftwareRelease()
upgrade_decision = self._makeUpgradeDecision()
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValueList([software_release])
self.tic()
upgrade_decision.confirm()
upgrade_decision.start()
self.assertFalse(upgrade_decision.UpgradeDecision_upgradeInstanceTree())
self.assertEqual('started', upgrade_decision.getSimulationState())
def testUpgradeDecision_upgradeComputeNode_no_software_release(self):
person = self._makePerson()
compute_node, _ = self._makeComputeNode(owner=person)
upgrade_decision = self._makeUpgradeDecision()
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValueList([compute_node])
self.tic()
upgrade_decision.confirm()
upgrade_decision.start()
self.assertFalse(upgrade_decision.UpgradeDecision_upgradeComputeNode())
self.assertEqual('started', upgrade_decision.getSimulationState())
def testUpgradeDecision_upgradeComputeNode_no_hosting_subscripion(self):
software_release = self._makeSoftwareRelease()
upgrade_decision = self._makeUpgradeDecision()
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValueList([software_release])
self.tic()
upgrade_decision.confirm()
upgrade_decision.start()
self.assertFalse(upgrade_decision.UpgradeDecision_upgradeComputeNode())
self.assertEqual('started', upgrade_decision.getSimulationState())
def testUpgradeDecision_upgradeComputeNode(self):
self._makePerson()
compute_node, _ = self._makeComputeNode()
software_release = self._makeSoftwareRelease()
upgrade_decision = self._makeUpgradeDecision()
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValueList([software_release, compute_node])
url = software_release.getUrlString()
self.tic()
self.assertFalse(upgrade_decision.UpgradeDecision_upgradeComputeNode())
upgrade_decision.confirm()
upgrade_decision.start()
self.assertTrue(upgrade_decision.UpgradeDecision_upgradeComputeNode())
self.tic()
software_installation = compute_node.getAggregateRelatedValue(
portal_type='Software Installation')
self.assertEqual('start_requested', software_installation.getSlapState())
self.assertEqual(url, software_installation.getUrlString())
self.assertEqual('validated', software_installation.getValidationState())
self.assertEqual('stopped', upgrade_decision.getSimulationState())
def testUpgradeDecision_processUpgradeComputeNode(self):
self._makePerson()
compute_node, _ = self._makeComputeNode()
software_release = self._makeSoftwareRelease()
upgrade_decision = self._makeUpgradeDecision()
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValueList([software_release, compute_node])
url = software_release.getUrlString()
self.tic()
self.assertFalse(upgrade_decision.UpgradeDecision_processUpgrade())
upgrade_decision.confirm()
upgrade_decision.start()
self.assertTrue(upgrade_decision.UpgradeDecision_processUpgrade())
self.tic()
software_installation = compute_node.getAggregateRelatedValue(
portal_type='Software Installation')
self.assertEqual('start_requested', software_installation.getSlapState())
self.assertEqual(url, software_installation.getUrlString())
self.assertEqual('validated', software_installation.getValidationState())
self.assertEqual('stopped', upgrade_decision.getSimulationState())
def testSoftwareRelease_createUpgradeDecision_compute_node(self):
person = self._makePerson()
compute_node, _ = self._makeComputeNode(owner=person)
......@@ -893,54 +699,6 @@ class TestSlapOSPDMSkins(TestSlapOSPDMMixinSkins):
self.assertEqual(in_progress, None)
def testUpgradeDecision_tryToCancel(self):
compute_node, _ = self._makeComputeNode()
software_release = self._makeSoftwareRelease()
software_release2 = self._makeSoftwareRelease()
upgrade_decision = self._makeUpgradeDecision()
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValueList([software_release, compute_node])
upgrade_decision.confirm()
upgrade_decision2 = self._makeUpgradeDecision()
upgrade_decision_line2 = self._makeUpgradeDecisionLine(upgrade_decision2)
upgrade_decision_line2.setAggregateValueList([software_release, compute_node])
upgrade_decision2.confirm()
upgrade_decision2.start()
url = software_release.getUrlString()
url2 = software_release2.getUrlString()
# Cancel is not possible with the same url_string
self.assertEqual(upgrade_decision.UpgradeDecision_tryToCancel(url), False)
self.assertEqual(upgrade_decision.UpgradeDecision_tryToCancel(url2), True)
self.assertEqual(upgrade_decision.getSimulationState(), 'cancelled')
# Cancel is no longer possible
self.assertEqual(upgrade_decision2.UpgradeDecision_tryToCancel(url), False)
self.assertEqual(upgrade_decision2.UpgradeDecision_tryToCancel(url2), False)
self.assertEqual(upgrade_decision2.getSimulationState(), 'started')
def testUpgradeDecision_tryToCancel_withRejected(self):
compute_node, _ = self._makeComputeNode()
software_release = self._makeSoftwareRelease()
software_release2 = self._makeSoftwareRelease()
upgrade_decision = self._makeUpgradeDecision()
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValueList([software_release, compute_node])
upgrade_decision.confirm()
upgrade_decision.reject()
url = software_release.getUrlString()
url2 = software_release2.getUrlString()
# Try to cancel rejected UD with the same sr will return False
self.assertEqual(upgrade_decision.UpgradeDecision_tryToCancel(url), False)
self.assertEqual(upgrade_decision.getSimulationState(), 'rejected')
# Try to cancel rejected UD will return True with url2
self.assertEqual(upgrade_decision.UpgradeDecision_tryToCancel(url2), True)
self.assertEqual(upgrade_decision.getSimulationState(), 'rejected')
def testComputeNode_checkAndCreateUpgradeDecision_auto(self):
person = self._makePerson()
compute_node, _ = self._makeComputeNode(owner=person,
......@@ -966,10 +724,10 @@ class TestSlapOSPDMSkins(TestSlapOSPDMMixinSkins):
self.assertEqual(len(upgrade_decision), 1)
self.assertEqual(upgrade_decision[0].getSimulationState(), 'started')
compute_node_aggregate = upgrade_decision[0].UpgradeDecision_getComputeNode()
self.assertEqual(compute_node_aggregate.getReference(),
compute_node.getReference())
release = upgrade_decision[0].UpgradeDecision_getSoftwareRelease()
compute_node_aggregate = upgrade_decision[0].UpgradeDecision_getAggregateValue("Compute Node")
self.assertEqual(compute_node_aggregate,
compute_node)
release = upgrade_decision[0].UpgradeDecision_getAggregateValue("Software Release")
self.assertEqual(release.getUrlString(),
software_release2.getUrlString())
self.tic()
......@@ -1001,7 +759,7 @@ class TestSlapOSPDMSkins(TestSlapOSPDMMixinSkins):
self.assertEqual(upgrade_decision.getSimulationState(), 'cancelled')
self.assertEqual(upgrade_decision2.getSimulationState(), 'planned')
release = upgrade_decision2.UpgradeDecision_getSoftwareRelease()
release = upgrade_decision2.UpgradeDecision_getAggregateValue("Software Release")
self.assertEqual(release.getUrlString(),
software_release3.getUrlString())
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_count</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>source/portal_workflow/upgrade_slap_interface_workflow/state_draft</string>
</tuple>
</value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>person_slap_interface_workflow</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>upgrade_slap_interface_workflow</string> </value>
</item>
<item>
<key> <string>language</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>manager_bypass</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow</string> </value>
</item>
<item>
<key> <string>state_variable</string> </key>
<value> <string>slap_state</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Upgrade Slap Interface Workflow</string> </value>
</item>
<item>
<key> <string>workflow_managed_permission</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Length" module="BTrees.Length"/>
</pickle>
<pickle> <int>0</int> </pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
</ZopeData>
upgrade_decision = state_change["object"]
from DateTime import DateTime
portal = upgrade_decision.getPortalObject()
document = upgrade_decision.UpgradeDecision_getAggregateValue("Instance Tree")
if document is None:
document = upgrade_decision.UpgradeDecision_getAggregateValue("Compute Node")
if document is None:
raise ValueError("No Compute Node or Instance Tree associated to upgrade.")
# Get required arguments
kwargs = state_change.kwargs
# Required args
# Raise TypeError if all parameters are not provided
try:
upgrade_scope = kwargs['upgrade_scope']
except KeyError:
raise TypeError("UpgradeDecision_approveRegistration takes exactly 1 arguments")
tag = "%s_requestUpgradeDecisionCreation_inProgress" % document.getUid()
activate_kw = {'tag': tag}
if portal.portal_activities.countMessageWithTag(tag) > 0:
# nothing to do
return
with upgrade_decision.defaultActivateParameterDict(activate_kw):
if upgrade_decision.getSimulationState() == "draft":
upgrade_decision.plan()
upgrade_decision.setStartDate(DateTime())
if upgrade_scope == "auto":
if upgrade_decision.getSimulationState() == "planned":
upgrade_decision.start()
# Prevent concurrent transaction to create 2 upgrade decision for the same instance_tree
document.serialize()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Script" module="erp5.portal_type"/>
</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>state_change</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>script_UpgradeDecision_approveRegistration</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Script</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>UpgradeDecision_approveRegistration</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -50,19 +50,17 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>state_object</string> </value>
<value> <string>state_change</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<key> <string>description</string> </key>
<value>
<tuple>
<string>Assignor</string>
</tuple>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>script_WebMessage_stopAndReopenTicket</string> </value>
<value> <string>script_UpgradeDecision_checkConsistency</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
......
support_request = context
upgrade_decision = state_change["object"]
from DateTime import DateTime
portal = context.getPortalObject()
# Get required arguments
kwargs = state_change.kwargs
# Required args
# Raise TypeError if all parameters are not provided
try:
message_title = kwargs['message_title']
message = kwargs['message']
destination_relative_url = kwargs['destination_relative_url']
except KeyError:
raise TypeError("UpgradeDecision_requestEvent takes exactly 3 arguments")
resource = portal.service_module.slapos_crm_information.getRelativeUrl()
# create Web message if needed for this ticket
last_event = context.portal_catalog.getResultValue(
last_event = portal.portal_catalog.getResultValue(
title=message_title,
follow_up_uid=support_request.getUid(),
follow_up_uid=upgrade_decision.getUid(),
sort_on=[('delivery.start_date', 'DESC')],
)
if last_event:
# User has already been notified for this problem.
return last_event
transactional_event = context.REQUEST.get("support_request_notified_item", None)
transactional_event = context.REQUEST.get("upgrade_decision_notified_item", None)
if transactional_event is not None:
if (transactional_event.getFollowUpUid() == support_request.getUid()) and \
if (transactional_event.getFollowUpUid() == upgrade_decision.getUid()) and \
(transactional_event.getTitle() == message_title):
return transactional_event
......@@ -28,14 +42,12 @@ event.edit(
text_content=message,
start_date = DateTime(),
resource = resource,
source=support_request.getSource(),
source=upgrade_decision.getSource(),
destination=destination_relative_url,
follow_up=support_request.getRelativeUrl(),
follow_up=upgrade_decision.getRelativeUrl(),
)
event.stop()
event.deliver()
support_request.serialize()
context.REQUEST.set("support_request_notified_item", event)
return event
upgrade_decision.serialize()
upgrade_decision.REQUEST.set("upgrade_decision_notified_item", event)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Script" module="erp5.portal_type"/>
</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>state_change</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>script_UpgradeDecision_notify</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Script</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>UpgradeDecision_notify</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
if context.getSimulationState() != 'started':
# Update Decision is not on started state, Upgrade is not possible!
return False
upgrade_decision = state_change["object"]
from DateTime import DateTime
instance_tree = context.UpgradeDecision_getInstanceTree()
software_release = context.UpgradeDecision_getSoftwareRelease()
if upgrade_decision.getSimulationState() != 'started':
# Update Decision is not on started state, Upgrade is not possible!
return
if instance_tree is None:
return False
instance_tree = upgrade_decision.UpgradeDecision_getAggregateValue("Instance Tree")
software_release = upgrade_decision.UpgradeDecision_getAggregateValue("Software Release")
compute_node = upgrade_decision.UpgradeDecision_getAggregateValue("Compute Node")
if software_release is None:
return False
return
if compute_node is None and instance_tree is None:
return
if compute_node is not None and instance_tree is not None:
raise ValueError("Something is wrong, you cannot upgrade Compute Node and Instance Tree on the same decision.")
software_release_url = software_release.getUrlString()
person = instance_tree.getDestinationSectionValue(portal_type="Person")
if compute_node is not None:
compute_node.requestSoftwareRelease(
software_release_url=software_release_url,
state="available")
upgrade_decision.stop(comment="Upgrade Processed for the Compute Node!")
return
# Test if the Software is available at the ComputeNode.
if not instance_tree.InstanceTree_isUpgradePossible(
......@@ -27,6 +41,7 @@ elif status == "stop_requested":
elif status == "destroy_requested":
state = "destroyed"
person = instance_tree.getDestinationSectionValue(portal_type="Person")
person.requestSoftwareInstance(
state=state,
software_release=software_release_url,
......@@ -37,6 +52,5 @@ person.requestSoftwareInstance(
shared=instance_tree.isRootSlave()
)
context.stop()
return True
upgrade_decision.stop(
comment="Upgrade Processed for the Instance Tree!")
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Script" module="erp5.portal_type"/>
</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>state_change</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>script_UpgradeDecision_requestUpgrade</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Script</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>UpgradeDecision_requestUpgrade</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
upgrade_decision = context
upgrade_decision = state_change["object"]
from DateTime import DateTime
cancellable_state_list = ['confirmed', 'planned']
require_state_list = ['rejected', 'confirmed', 'planned']
simulation_state = upgrade_decision.getSimulationState()
# Get required arguments
kwargs = state_change.kwargs
# Required args
# Raise TypeError if all parameters are not provided
try:
software_release_url = kwargs['software_release_url']
except KeyError:
raise TypeError("UpgradeDecision_reviewRegistration takes exactly 1 arguments")
if simulation_state in require_state_list:
current_release = upgrade_decision.UpgradeDecision_getSoftwareRelease()
current_release = upgrade_decision.UpgradeDecision_getAggregateValue("Software Release")
if not current_release:
# This upgrade decision is not valid
return False
instance_tree = upgrade_decision.UpgradeDecision_getInstanceTree()
return
instance_tree = upgrade_decision.UpgradeDecision_getAggregateValue("Instance Tree")
if instance_tree is not None:
current_instance_tree_release = instance_tree.getUrlString()
if current_instance_tree_release == new_url_string:
if current_instance_tree_release == software_release_url:
if simulation_state in cancellable_state_list:
upgrade_decision.cancel()
return True
upgrade_decision.cancel(comment="Instance tree is already upgraded.")
return
if current_release.getUrlString() == new_url_string:
if current_release.getUrlString() == software_release_url:
# Cannot cancel because the software releases are the same
return False
if simulation_state in cancellable_state_list:
upgrade_decision.cancel()
return True
else:
return False
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
<global name="Workflow Script" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......@@ -50,11 +50,33 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
<value> <string>state_change</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>UpgradeDecision_getSoftwareRelease</string> </value>
<value> <string>script_UpgradeDecision_reviewRegistration</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Script</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>UpgradeDecision_reviewRegistration</string> </value>
</item>
</dictionary>
</pickle>
......
upgrade_decision = state_change["object"]
from DateTime import DateTime
portal = upgrade_decision.getPortalObject()
instance_tree = upgrade_decision.UpgradeDecision_getAggregateValue("Instance Tree")
software_release = upgrade_decision.UpgradeDecision_getAggregateValue("Software Release")
if upgrade_decision.getSimulationState() == "cancelled":
return
if software_release.getValidationState() == "archived":
upgrade_decision.cancel(comment="Software Release is archived.")
return
if instance_tree is not None:
if instance_tree.getUpgradeScope() in ['never', 'disabled']:
upgrade_decision.cancel("Upgrade scope was disabled on the related Instance Tree")
elif instance_tree.getSlapState() == "destroy_requested":
upgrade_decision.cancel(comment="Instance Tree is destroyed.")
elif instance_tree.getUrlString() == software_release.getUrlString():
upgrade_decision.cancel(comment="Instance tree is already upgraded.")
return
compute_node = upgrade_decision.UpgradeDecision_getAggregateValue("Compute Node")
if compute_node is not None:
if compute_node.getUpgradeScope() in ['never', 'disabled']:
upgrade_decision.cancel("Upgrade scope was disabled on the related Instance Tree")
return
elif compute_node.getAllocationScope() in ["closed/forever", "closed/termination"]:
upgrade_decision.cancel(comment="Compute Node is closed.")
return
already_deployed = len(portal.portal_catalog(limit=1,
portal_type="Compute Partition",
parent_reference=compute_node.getReference(),
software_release_url=software_release.getUrlString()))
if already_deployed:
upgrade_decision.cancel(comment="Compute Node already has the software release")
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Script" module="erp5.portal_type"/>
</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>state_change</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>script_UpgradeDecision_reviewUpgrade</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Script</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>UpgradeDecision_reviewUpgrade</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow State" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>acquire_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>destination/portal_workflow/upgrade_slap_interface_workflow/transition_approve_registration</string>
<string>destination/portal_workflow/upgrade_slap_interface_workflow/transition_notify</string>
<string>destination/portal_workflow/upgrade_slap_interface_workflow/transition_request_upgrade</string>
<string>destination/portal_workflow/upgrade_slap_interface_workflow/transition_review_registration</string>
<string>destination/portal_workflow/upgrade_slap_interface_workflow/transition_review_upgrade</string>
</tuple>
</value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>state_draft</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow State</string> </value>
</item>
<item>
<key> <string>state_permission_role_list_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>state_type</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Draft</string> </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>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Transition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>action_name</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/workflow</string>
<string>before_script/portal_workflow/upgrade_slap_interface_workflow/script_UpgradeDecision_checkConsistency</string>
<string>after_script/portal_workflow/upgrade_slap_interface_workflow/script_UpgradeDecision_approveRegistration</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>guard_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>transition_approve_registration</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Transition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Approve Registration</string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Transition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>action_name</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/workflow</string>
<string>before_script/portal_workflow/upgrade_slap_interface_workflow/script_UpgradeDecision_checkConsistency</string>
<string>after_script/portal_workflow/upgrade_slap_interface_workflow/script_UpgradeDecision_notify</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Create an event for the Upgrade Decision</string> </value>
</item>
<item>
<key> <string>guard_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>transition_notify</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Transition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Notify</string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Transition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>action_name</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/workflow</string>
<string>before_script/portal_workflow/upgrade_slap_interface_workflow/script_UpgradeDecision_checkConsistency</string>
<string>after_script/portal_workflow/upgrade_slap_interface_workflow/script_UpgradeDecision_requestUpgrade</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Perform the Upgrade</string> </value>
</item>
<item>
<key> <string>guard_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>transition_request_upgrade</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Transition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Request Upgrade</string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Transition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>action_name</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/workflow</string>
<string>before_script/portal_workflow/upgrade_slap_interface_workflow/script_UpgradeDecision_checkConsistency</string>
<string>after_script/portal_workflow/upgrade_slap_interface_workflow/script_UpgradeDecision_reviewRegistration</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Cancel if the current upgrade isn\'t valid anymore. </string> </value>
</item>
<item>
<key> <string>guard_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>transition_review_registration</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Transition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Review Registration</string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Transition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>action_name</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/workflow</string>
<string>before_script/portal_workflow/upgrade_slap_interface_workflow/script_UpgradeDecision_checkConsistency</string>
<string>after_script/portal_workflow/upgrade_slap_interface_workflow/script_UpgradeDecision_reviewUpgrade</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Review if the upgrade still applicable</string> </value>
</item>
<item>
<key> <string>guard_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>transition_review_upgrade</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Transition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Review Upgrade</string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>The last transition</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_action</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</string> </key>
<value> <string>transition/getReference|nothing</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>The name of the user who performed the last transition</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_actor</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</string> </key>
<value> <string>user/getUserName</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Comments about the last transition</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_comment</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</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="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </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>id</string> </key>
<value> <string>variable_error_message</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>0</int> </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>id</string> </key>
<value> <string>variable_history</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</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="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>portal type (use as filter for worklists)</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_portal_type</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Time of the last transition</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_time</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</string> </key>
<value> <string>state_change/getDateTime</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -3,3 +3,4 @@ Software Product | commerce_validation_workflow
Upgrade Decision | edit_workflow
Upgrade Decision | ticket_interaction_workflow
Upgrade Decision | upgrade_decision_workflow
Upgrade Decision | upgrade_slap_interface_workflow
\ No newline at end of file
......@@ -2,3 +2,4 @@ test.erp5.testSlapOSPDMAlarm
test.erp5.testSlapOSPDMSkins
test.erp5.testSlapOSPDMDestroySoftwareInstallationWithArchivedSoftwareReleaseAlarm
test.erp5.testSlapOSPDMCreateUpgradeDecisionSkins
test.erp5.testSlapOSCloudUpgradeSlapInterfaceWorkflow
\ No newline at end of file
upgrade_decision_workflow
upgrade_slap_interface_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