Commit 9cacdec2 authored by Rafael Monnerat's avatar Rafael Monnerat

Propagate activate_kw when edit successor

See merge request nexedi/slapos.core!581
parents 3b27422c c6eee57f
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
# #
############################################################################## ##############################################################################
from Products.ERP5Type.TransactionalVariable import getTransactionalVariable
from AccessControl.SecurityManagement import getSecurityManager, \ from AccessControl.SecurityManagement import getSecurityManager, \
setSecurityManager, newSecurityManager setSecurityManager, newSecurityManager
from Products.ERP5Security import SUPER_USER from Products.ERP5Security import SUPER_USER
...@@ -283,6 +284,13 @@ def Computer_checkComputeNodeMigrationConsistency(self, fixit=False): ...@@ -283,6 +284,13 @@ def Computer_checkComputeNodeMigrationConsistency(self, fixit=False):
return error_list return error_list
def Base_setTransactionalTag(self, tag, REQUEST=None):
getTransactionalVariable()[str(tag)] = str(tag)
def Base_getTransactionalTag(self, tag, REQUEST=None):
if REQUEST is not None:
raise Unauthorized
return getTransactionalVariable().get(tag, None)
def Base_updateRelatedContentWithoutReindextion(self, previous_category_url, new_category_url, REQUEST=None): def Base_updateRelatedContentWithoutReindextion(self, previous_category_url, new_category_url, REQUEST=None):
""" This method indeed reimplements the updateRelatedContent but it uses """ This method indeed reimplements the updateRelatedContent but it uses
......
...@@ -6,12 +6,6 @@ ...@@ -6,12 +6,6 @@
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item> <item>
<key> <string>default_reference</string> </key> <key> <string>default_reference</string> </key>
<value> <string>SlapOSCloud</string> </value> <value> <string>SlapOSCloud</string> </value>
...@@ -55,28 +49,13 @@ ...@@ -55,28 +49,13 @@
<item> <item>
<key> <string>workflow_history</string> </key> <key> <string>workflow_history</string> </key>
<value> <value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent> <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
<record id="2" aka="AAAAAAAAAAI="> <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> <pickle>
<global name="PersistentMapping" module="Persistence.mapping"/> <global name="PersistentMapping" module="Persistence.mapping"/>
</pickle> </pickle>
...@@ -89,7 +68,7 @@ ...@@ -89,7 +68,7 @@
<item> <item>
<key> <string>component_validation_workflow</string> </key> <key> <string>component_validation_workflow</string> </key>
<value> <value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent> <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value> </value>
</item> </item>
</dictionary> </dictionary>
...@@ -98,7 +77,7 @@ ...@@ -98,7 +77,7 @@
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
<record id="4" aka="AAAAAAAAAAQ="> <record id="3" aka="AAAAAAAAAAM=">
<pickle> <pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/> <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle> </pickle>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ExternalMethod" module="Products.ExternalMethod.ExternalMethod"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_function</string> </key>
<value> <string>Base_getTransactionalTag</string> </value>
</item>
<item>
<key> <string>_module</string> </key>
<value> <string>SlapOSCloud</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_getTransactionalTag</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ExternalMethod" module="Products.ExternalMethod.ExternalMethod"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_function</string> </key>
<value> <string>Base_setTransactionalTag</string> </value>
</item>
<item>
<key> <string>_module</string> </key>
<value> <string>SlapOSCloud</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_setTransactionalTag</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
############################################################################## ##############################################################################
from erp5.component.test.SlapOSTestCaseMixin import SlapOSTestCaseMixin from erp5.component.test.SlapOSTestCaseMixin import SlapOSTestCaseMixin
import transaction import transaction
from unittest import expectedFailure
from time import sleep from time import sleep
from zExceptions import Unauthorized from zExceptions import Unauthorized
...@@ -441,7 +440,6 @@ class TestSlapOSCoreInstanceSlapInterfaceWorkflow(SlapOSTestCaseMixin): ...@@ -441,7 +440,6 @@ class TestSlapOSCoreInstanceSlapInterfaceWorkflow(SlapOSTestCaseMixin):
self.assertRaises(NotImplementedError, B_instance.requestInstance, self.assertRaises(NotImplementedError, B_instance.requestInstance,
**request_kw) **request_kw)
@expectedFailure
def test_request_tree_change_same_transaction(self): def test_request_tree_change_same_transaction(self):
"""Checks tree change forced by request """Checks tree change forced by request
...@@ -472,6 +470,66 @@ class TestSlapOSCoreInstanceSlapInterfaceWorkflow(SlapOSTestCaseMixin): ...@@ -472,6 +470,66 @@ class TestSlapOSCoreInstanceSlapInterfaceWorkflow(SlapOSTestCaseMixin):
self.assertRaises(NotImplementedError, B_instance.requestInstance, self.assertRaises(NotImplementedError, B_instance.requestInstance,
**request_kw) **request_kw)
def test_request_tree_edit_parameters_change_not_indexed(self):
"""Checks tree change forced by request
For a tree like:
A
|
A
|\
B C
|
D
When C requests D tree in a while C requests D, but before indexation,
the system shall disallow the operation."""
request_kw = self.request_kw.copy()
request_kw['software_title'] = self.generateNewSoftwareTitle()
self.software_instance.requestInstance(**request_kw)
B_instance = self.software_instance.REQUEST.get('request_instance')
request_kw['software_title'] = self.generateNewSoftwareTitle()
self.software_instance.requestInstance(**request_kw)
C_instance = self.software_instance.REQUEST.get('request_instance')
request_kw['software_title'] = self.generateNewSoftwareTitle()
B_instance.requestInstance(**request_kw)
D_instance = self.software_instance.REQUEST.get('request_instance')
self.assertSameSet(
self.software_instance.getSuccessorList(),
[B_instance.getRelativeUrl(), C_instance.getRelativeUrl()])
self.assertSameSet(
B_instance.getSuccessorList(), [D_instance.getRelativeUrl()])
# Ensure all is indexed first
self.tic()
# B edits twice w/o a problem w/o indexation problems
request_kw['instance_xml'] = self.generateSafeXml()
B_instance.requestInstance(**request_kw)
transaction.commit()
C_instance.requestInstance(**request_kw)
transaction.commit()
self.assertSameSet(
C_instance.getSuccessorList(), [D_instance.getRelativeUrl()])
self.assertSameSet(
B_instance.getSuccessorList(), [])
# B request must fails since indexation didnt finished up properly
# which would lead to dupplicated set on sucessor
self.assertRaises(NotImplementedError, B_instance.requestInstance,
**request_kw)
def test_request_started_stopped_destroyed(self): def test_request_started_stopped_destroyed(self):
request_kw = self.request_kw.copy() request_kw = self.request_kw.copy()
...@@ -706,7 +764,6 @@ class TestSlapOSCoreInstanceSlapInterfaceWorkflow(SlapOSTestCaseMixin): ...@@ -706,7 +764,6 @@ class TestSlapOSCoreInstanceSlapInterfaceWorkflow(SlapOSTestCaseMixin):
self.assertRaises(NotImplementedError, B_instance.requestInstance, self.assertRaises(NotImplementedError, B_instance.requestInstance,
**request_kw) **request_kw)
@expectedFailure
def test_request_tree_change_same_transaction_shared(self): def test_request_tree_change_same_transaction_shared(self):
"""Checks tree change forced by request """Checks tree change forced by request
...@@ -1160,7 +1217,6 @@ class TestSlapOSCoreInstanceSlapInterfaceWorkflowTransfer(SlapOSTestCaseMixin): ...@@ -1160,7 +1217,6 @@ class TestSlapOSCoreInstanceSlapInterfaceWorkflowTransfer(SlapOSTestCaseMixin):
self.assertTrue(serial in self.software_instance.getSslCertificate()) self.assertTrue(serial in self.software_instance.getSslCertificate())
self.assertTrue(certificate_login.getReference() in \ self.assertTrue(certificate_login.getReference() in \
self.software_instance.getSslCertificate().decode('string_escape')) self.software_instance.getSslCertificate().decode('string_escape'))
self.assertRaises(ValueError, self.software_instance.generateCertificate) self.assertRaises(ValueError, self.software_instance.generateCertificate)
def test_revokeCertificate(self): def test_revokeCertificate(self):
......
...@@ -30,7 +30,7 @@ else: ...@@ -30,7 +30,7 @@ else:
# Prevent creating two instances with the same title # Prevent creating two instances with the same title
instance_tree.serialize() instance_tree.serialize()
tag = "%s_%s_inProgress" % (instance_tree.getUid(), software_title) tag = "%s_%s_inProgress" % (instance_tree.getUid(), software_title)
if (portal.portal_activities.countMessageWithTag(tag) > 0): if (portal.portal_activities.countMessageWithTag(tag) > 0) or context.Base_getTransactionalTag(tag):
# The software instance is already under creation but can not be fetched from catalog # 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 # As it is not possible to fetch informations, it is better to raise an error
raise NotImplementedError(tag) raise NotImplementedError(tag)
...@@ -74,6 +74,7 @@ if (request_software_instance is None): ...@@ -74,6 +74,7 @@ if (request_software_instance is None):
else: else:
instance_found = True instance_found = True
# First time that the software instance is requested # First time that the software instance is requested
successor = None
# Create a new one # Create a new one
reference = "SOFTINST-%s" % portal.portal_ids.generateNewId( reference = "SOFTINST-%s" % portal.portal_ids.generateNewId(
...@@ -105,8 +106,8 @@ else: ...@@ -105,8 +106,8 @@ else:
successor = request_software_instance.getSuccessorRelatedValue(portal_type="Software Instance") successor = request_software_instance.getSuccessorRelatedValue(portal_type="Software Instance")
if (successor is None): if (successor is None):
# Check if the precessor is a Instance Tree # Check if the precessor is a Instance Tree
instance_tree_precessesor = request_software_instance.getSuccessorRelatedValue(portal_type="Instance Tree") instance_tree_successor = request_software_instance.getSuccessorRelatedValue(portal_type="Instance Tree")
if (requester_instance.getPortalType() != "Instance Tree" and instance_tree_precessesor is not None): if (requester_instance.getPortalType() != "Instance Tree" and instance_tree_successor is not None):
raise ValueError('It is disallowed to request root software instance %s' % request_software_instance.getRelativeUrl()) raise ValueError('It is disallowed to request root software instance %s' % request_software_instance.getRelativeUrl())
else: else:
successor = requester_instance successor = requester_instance
...@@ -114,10 +115,14 @@ else: ...@@ -114,10 +115,14 @@ else:
if request_software_instance.getUid() not in graph: if request_software_instance.getUid() not in graph:
graph[request_software_instance.getUid()] = request_software_instance.getSuccessorUidList() graph[request_software_instance.getUid()] = request_software_instance.getSuccessorUidList()
successor_uid_list = successor.getSuccessorUidList() successor_uid_list = successor.getSuccessorUidList()
if request_software_instance.getUid() in successor_uid_list: if successor != requester_instance:
successor_uid_list.remove(request_software_instance.getUid()) if request_software_instance.getUid() in successor_uid_list:
successor.edit(successor_uid_list=successor_uid_list) successor_uid_list.remove(request_software_instance.getUid())
successor.edit(
successor_uid_list=successor_uid_list,
activate_kw={'tag': tag}
)
graph[successor.getUid()] = successor_uid_list graph[successor.getUid()] = successor_uid_list
if instance_found: if instance_found:
...@@ -132,6 +137,7 @@ if instance_found: ...@@ -132,6 +137,7 @@ if instance_found:
} }
request_software_instance_url = request_software_instance.getRelativeUrl() request_software_instance_url = request_software_instance.getRelativeUrl()
context.REQUEST.set('request_instance', request_software_instance) context.REQUEST.set('request_instance', request_software_instance)
context.Base_setTransactionalTag(tag)
if (root_state == "started"): if (root_state == "started"):
request_software_instance.requestStart(**promise_kw) request_software_instance.requestStart(**promise_kw)
elif (root_state == "stopped"): elif (root_state == "stopped"):
...@@ -142,7 +148,11 @@ if instance_found: ...@@ -142,7 +148,11 @@ if instance_found:
else: else:
raise ValueError, "state should be started, stopped or destroyed" raise ValueError, "state should be started, stopped or destroyed"
successor_list = requester_instance.getSuccessorList() + [request_software_instance_url] successor_list = requester_instance.getSuccessorList()
successor_uid_list = requester_instance.getSuccessorUidList()
if successor != requester_instance:
successor_list.append(request_software_instance_url)
successor_uid_list.append(request_software_instance.getUid())
uniq_successor_list = list(set(successor_list)) uniq_successor_list = list(set(successor_list))
successor_list.sort() successor_list.sort()
uniq_successor_list.sort() uniq_successor_list.sort()
...@@ -150,13 +160,16 @@ if instance_found: ...@@ -150,13 +160,16 @@ if instance_found:
assert successor_list == uniq_successor_list, "%s != %s" % (successor_list, uniq_successor_list) assert successor_list == uniq_successor_list, "%s != %s" % (successor_list, uniq_successor_list)
# update graph to reflect requested operation # update graph to reflect requested operation
graph[requester_instance.getUid()] = requester_instance.getSuccessorUidList() + [request_software_instance.getUid()] graph[requester_instance.getUid()] = successor_uid_list
# check if all elements are still connected and if there is no cycle # check if all elements are still connected and if there is no cycle
request_software_instance.checkConnected(graph, instance_tree.getUid()) request_software_instance.checkConnected(graph, instance_tree.getUid())
request_software_instance.checkNotCyclic(graph) request_software_instance.checkNotCyclic(graph)
requester_instance.edit(successor_list=successor_list) if successor != requester_instance:
requester_instance.edit(
successor_list=successor_list,
activate_kw={'tag': tag}
)
else: else:
context.REQUEST.set('request_instance', None) context.REQUEST.set('request_instance', None)
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