Commit de9cde62 authored by Rafael Monnerat's avatar Rafael Monnerat

slapos_cloud: Protect supply against multiple calls on the same request

  This prevents +2 supplies on the request creates more them one software installation with same url on a compute  node.
parent e6794060
...@@ -179,6 +179,7 @@ class DefaultScenarioMixin(TestSlapOSSecurityMixin): ...@@ -179,6 +179,7 @@ class DefaultScenarioMixin(TestSlapOSSecurityMixin):
def supplySoftware(self, server, url, state='available'): def supplySoftware(self, server, url, state='available'):
self.portal.portal_slap.supplySupply(url, server.getReference(), state) self.portal.portal_slap.supplySupply(url, server.getReference(), state)
self.tic() self.tic()
self.cleanUpRequest()
software_installation = self.portal.portal_catalog.getResultValue( software_installation = self.portal.portal_catalog.getResultValue(
portal_type='Software Installation', portal_type='Software Installation',
......
...@@ -142,10 +142,9 @@ class SlapOSTestCaseMixin(testSlapOSMixin): ...@@ -142,10 +142,9 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
_custom_additional_bt5_list = [] _custom_additional_bt5_list = []
# Used by testSlapOSERP5GroupRoleSecurity.TestSlapOSGroupRoleSecurityCoverage for # Used by testSlapOSERP5GroupRoleSecurity.TestSlapOSGroupRoleSecurityCoverage for
# searh classes for assert overage # search classes for assert overage
security_group_role_test_id_list = ['test.erp5.testSlapOSERP5GroupRoleSecurity'] security_group_role_test_id_list = ['test.erp5.testSlapOSERP5GroupRoleSecurity']
def afterSetUp(self): def afterSetUp(self):
testSlapOSMixin.afterSetUp(self) testSlapOSMixin.afterSetUp(self)
self.changeSkin('View') self.changeSkin('View')
...@@ -156,6 +155,14 @@ class SlapOSTestCaseMixin(testSlapOSMixin): ...@@ -156,6 +155,14 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
"""Overwrite this function on project context to tweak production focus tests""" """Overwrite this function on project context to tweak production focus tests"""
pass pass
def cleanUpRequest(self):
""" set None some values that can cause problems in tests
"""
for key in self.portal.REQUEST.keys():
if key.endswith("_inProgress"):
# Reset values set on script_ComputeNode_requestSoftwareReleaseChange
self.portal.REQUEST.set(key, None)
def addAccountingManagerAssignment(self, person): def addAccountingManagerAssignment(self, person):
person.newContent( person.newContent(
portal_type='Assignment', portal_type='Assignment',
...@@ -290,7 +297,7 @@ class SlapOSTestCaseMixin(testSlapOSMixin): ...@@ -290,7 +297,7 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
project_reference=project.getReference() project_reference=project.getReference()
) )
# As the software url does not match any service, and any trade condition # As the software url does not match any service, and any trade condition
# no instance is automatically created. # no instance is automatically created.
# except if we fake Item_getSubscriptionStatus # except if we fake Item_getSubscriptionStatus
with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"): with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
...@@ -352,7 +359,6 @@ class SlapOSTestCaseMixin(testSlapOSMixin): ...@@ -352,7 +359,6 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
self.portal.portal_workflow._jumpToStateFor(self.software_instance, 'start_requested') self.portal.portal_workflow._jumpToStateFor(self.software_instance, 'start_requested')
self.software_instance.validate() self.software_instance.validate()
self.requested_software_instance.edit( self.requested_software_instance.edit(
title=self.generateNewSoftwareTitle(), title=self.generateNewSoftwareTitle(),
reference="TESTSI-%s" % self.generateNewId(), reference="TESTSI-%s" % self.generateNewId(),
......
...@@ -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 Products.ERP5Type.Errors import UnsupportedWorkflowMethod from Products.ERP5Type.Errors import UnsupportedWorkflowMethod
...@@ -212,6 +211,7 @@ class TestSlapOSCoreComputeNodeSlapInterfaceWorkflow(SlapOSTestCaseMixin): ...@@ -212,6 +211,7 @@ class TestSlapOSCoreComputeNodeSlapInterfaceWorkflow(SlapOSTestCaseMixin):
self.compute_node.requestSoftwareRelease(software_release_url=url, self.compute_node.requestSoftwareRelease(software_release_url=url,
state='available') state='available')
self.tic() self.tic()
self.cleanUpRequest()
self.login() self.login()
software_installation = self.compute_node.getAggregateRelatedValue( software_installation = self.compute_node.getAggregateRelatedValue(
portal_type='Software Installation') portal_type='Software Installation')
...@@ -245,7 +245,6 @@ class TestSlapOSCoreComputeNodeSlapInterfaceWorkflow(SlapOSTestCaseMixin): ...@@ -245,7 +245,6 @@ class TestSlapOSCoreComputeNodeSlapInterfaceWorkflow(SlapOSTestCaseMixin):
state='available') state='available')
transaction.abort() transaction.abort()
@expectedFailure
def test_requestSoftwareRelease_same_transaction(self): def test_requestSoftwareRelease_same_transaction(self):
self.person_user = self.makePerson(self.project) self.person_user = self.makePerson(self.project)
self.addProjectProductionManagerAssignment(self.person_user, self.project) self.addProjectProductionManagerAssignment(self.person_user, self.project)
...@@ -641,6 +640,7 @@ class TestSlapOSCoreComputeNodeSlapInterfaceWorkflowSupply(SlapOSTestCaseMixin): ...@@ -641,6 +640,7 @@ class TestSlapOSCoreComputeNodeSlapInterfaceWorkflowSupply(SlapOSTestCaseMixin):
software_installation.getReference()) software_installation.getReference())
self.tic() self.tic()
self.cleanUpRequest()
self.compute_node.requestSoftwareRelease(state="available", self.compute_node.requestSoftwareRelease(state="available",
software_release_url=software_release) software_release_url=software_release)
...@@ -673,6 +673,7 @@ class TestSlapOSCoreComputeNodeSlapInterfaceWorkflowSupply(SlapOSTestCaseMixin): ...@@ -673,6 +673,7 @@ class TestSlapOSCoreComputeNodeSlapInterfaceWorkflowSupply(SlapOSTestCaseMixin):
software_installation.getReference()) software_installation.getReference())
self.tic() self.tic()
self.cleanUpRequest()
self.compute_node.requestSoftwareRelease(state="destroyed", self.compute_node.requestSoftwareRelease(state="destroyed",
software_release_url=software_release) software_release_url=software_release)
...@@ -714,6 +715,7 @@ class TestSlapOSCoreComputeNodeSlapInterfaceWorkflowSupply(SlapOSTestCaseMixin): ...@@ -714,6 +715,7 @@ class TestSlapOSCoreComputeNodeSlapInterfaceWorkflowSupply(SlapOSTestCaseMixin):
software_installation.getReference()) software_installation.getReference())
self.tic() self.tic()
self.cleanUpRequest()
self.compute_node.requestSoftwareRelease(state="destroyed", self.compute_node.requestSoftwareRelease(state="destroyed",
software_release_url=software_release) software_release_url=software_release)
...@@ -761,6 +763,7 @@ class TestSlapOSCoreComputeNodeSlapInterfaceWorkflowSupply(SlapOSTestCaseMixin): ...@@ -761,6 +763,7 @@ class TestSlapOSCoreComputeNodeSlapInterfaceWorkflowSupply(SlapOSTestCaseMixin):
software_installation.getReference()) software_installation.getReference())
self.tic() self.tic()
self.cleanUpRequest()
self.compute_node.requestSoftwareRelease(state="destroyed", self.compute_node.requestSoftwareRelease(state="destroyed",
software_release_url=software_release) software_release_url=software_release)
......
...@@ -14,7 +14,7 @@ except KeyError: ...@@ -14,7 +14,7 @@ except KeyError:
tag = "%s_%s_inProgress" % (compute_node.getUid(), tag = "%s_%s_inProgress" % (compute_node.getUid(),
software_release_url) software_release_url)
if (portal.portal_activities.countMessageWithTag(tag) > 0): if (portal.portal_activities.countMessageWithTag(tag) > 0 or compute_node.REQUEST.get(tag) == 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)
...@@ -41,7 +41,7 @@ else: ...@@ -41,7 +41,7 @@ else:
if (state == "destroyed"): if (state == "destroyed"):
# No need to create destroyed subscription. # No need to create destroyed subscription.
return return
software_installation_reference = "SOFTINSTALL-%s" % context.getPortalObject().portal_ids\ software_installation_reference = "SOFTINSTALL-%s" % portal.portal_ids\
.generateNewId(id_group='slap_software_installation_reference', id_generator='uid') .generateNewId(id_group='slap_software_installation_reference', id_generator='uid')
software_installation = portal.getDefaultModule(portal_type=software_installation_portal_type).newContent( software_installation = portal.getDefaultModule(portal_type=software_installation_portal_type).newContent(
portal_type=software_installation_portal_type, portal_type=software_installation_portal_type,
...@@ -51,6 +51,7 @@ else: ...@@ -51,6 +51,7 @@ else:
follow_up_value=compute_node.getFollowUpValue(), follow_up_value=compute_node.getFollowUpValue(),
activate_kw={'tag': tag} activate_kw={'tag': tag}
) )
compute_node.REQUEST.set(tag, tag)
# Change desired state # Change desired state
if (state == "available"): if (state == "available"):
...@@ -67,4 +68,4 @@ if validation_state == 'draft': ...@@ -67,4 +68,4 @@ if validation_state == 'draft':
portal.portal_workflow.doActionFor(software_installation, portal.portal_workflow.doActionFor(software_installation,
'validate_action') 'validate_action')
context.REQUEST.set('software_installation_url', software_installation.getRelativeUrl()) compute_node.REQUEST.set('software_installation_url', software_installation.getRelativeUrl())
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