Commit b1a3af0b authored by Alain Takoudjou's avatar Alain Takoudjou

Fix Upgrade decision generation

- fix upgrade decision duplicated when an hosting subscription is deployed in many partitions
- Prevent concurrent transaction to create 2 upgrade decision for the same Hosting Subscription

/reviewed-on nexedi/slapos.core!79
parents f324043a 9a8e2947
...@@ -8,7 +8,11 @@ ...@@ -8,7 +8,11 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>active_sense_method_id</string> </key> <key> <string>active_sense_method_id</string> </key>
<value> <string>Alarm_computerCheckUpgradeHostingSubscription</string> </value> <value> <string>Alarm_checkAndUpgradeHostingSubscription</string> </value>
</item>
<item>
<key> <string>automatic_solve</string> </key>
<value> <int>0</int> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
portal = context.getPortalObject()
portal.portal_catalog.searchAndActivate(
portal_type='Hosting Subscription',
validation_state = 'validated',
slap_state=['start_requested', 'stop_requested'],
method_id = 'HostingSubscription_createUpgradeDecision',
packet_size=1,
activate_kw = {'tag':tag}
)
context.activate(after_tag=tag).getId()
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>Alarm_computerCheckUpgradeHostingSubscription</string> </value> <value> <string>Alarm_checkAndUpgradeHostingSubscription</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
portal = context.getPortalObject()
default_allocation_scope_uid = [category.getUid() \
for category in portal.portal_categories.allocation_scope.open.objectValues()]
if default_allocation_scope_uid:
portal.portal_catalog.searchAndActivate(
portal_type='Computer',
validation_state = 'validated',
default_allocation_scope_uid=default_allocation_scope_uid,
method_id = 'Computer_createHostingSubscriptionUpgradeDecision',
packet_size=1,
activate_kw = {'tag':tag}
)
context.activate(after_tag=tag).getId()
from DateTime import DateTime
portal = context.getPortalObject()
partition_list = portal.portal_catalog(portal_type='Computer Partition',
free_for_request=0,
parent_uid=context.getUid())
valid_slap_state = ['start_requested', 'stop_requested']
hosting_subscription_list = []
upgrade_decision_list = []
for partition in partition_list:
software_instance = partition.getAggregateRelatedValue(
portal_type='Software Instance')
if not software_instance:
continue
hosting_subscription = software_instance.getSpecialiseValue(
portal_type='Hosting Subscription')
if hosting_subscription and hosting_subscription.getSlapState() \
in valid_slap_state and not \
hosting_subscription in hosting_subscription_list:
hosting_subscription_list.append(hosting_subscription)
else:
continue
newer_release = hosting_subscription.\
HostingSubscription_getUpgradableSoftwareRelease()
if newer_release is None:
continue
decision_in_progress = newer_release.\
SoftwareRelease_getUpgradeDecisionInProgress(hosting_subscription.getUid())
if decision_in_progress and \
not decision_in_progress.UpgradeDecision_tryToCancel(
newer_release.getUrlString()):
continue
upgrade_decision = newer_release.SoftwareRelease_createUpgradeDecision(
source_url=hosting_subscription.getRelativeUrl(),
title='A new upgrade is available for %s' % hosting_subscription.getTitle()
)
upgrade_decision.plan()
upgrade_decision.setStartDate(DateTime())
upgrade_decision_list.append(upgrade_decision)
return upgrade_decision_list
from DateTime import DateTime
portal = context.getPortalObject()
hosting_subscription = context
tag = "%s_requestUpgradeDecisionCreation_inProgress" % hosting_subscription.getUid()
activate_kw = {'tag': tag}
if portal.portal_activities.countMessageWithTag(tag) > 0:
# nothing to do
return
root_instance = hosting_subscription.getPredecessorValue()
if root_instance is None or root_instance.getPortalType() == "Slave Instance":
return
if hosting_subscription.getSlapState() == "destroy_requested":
return
partition = root_instance.getAggregateValue(portal_type="Computer Partition")
if partition is None:
return
if not partition.getParent().getAllocationScopeUid() in [category.getUid() \
for category in portal.portal_categories.allocation_scope.open.objectValues()]:
return
decision_title = 'A new upgrade is available for %s' % hosting_subscription.getTitle()
newer_release = hosting_subscription.\
HostingSubscription_getUpgradableSoftwareRelease()
if newer_release is None:
return
decision_in_progress = newer_release.\
SoftwareRelease_getUpgradeDecisionInProgress(hosting_subscription.getUid())
if decision_in_progress and \
not decision_in_progress.UpgradeDecision_tryToCancel(
newer_release.getUrlString()):
return
upgrade_decision = newer_release.SoftwareRelease_createUpgradeDecision(
source_url=hosting_subscription.getRelativeUrl(),
title=decision_title
)
with upgrade_decision.defaultActivateParameterDict(activate_kw):
upgrade_decision.plan()
upgrade_decision.setStartDate(DateTime())
# Prevent concurrent transaction to create 2 upgrade decision for the same hosting_subscription
hosting_subscription.serialize()
return upgrade_decision
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>Computer_createHostingSubscriptionUpgradeDecision</string> </value> <value> <string>HostingSubscription_createUpgradeDecision</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -33,6 +33,19 @@ class TestSlapOSUpgradeDecisionProcess(SlapOSTestCaseMixin): ...@@ -33,6 +33,19 @@ class TestSlapOSUpgradeDecisionProcess(SlapOSTestCaseMixin):
return computer return computer
def _makeHostingSubscription(self, slap_state="start_requested"):
hosting_subscription = self.portal\
.hosting_subscription_module.template_hosting_subscription\
.Base_createCloneDocument(batch_mode=1)
hosting_subscription.validate()
hosting_subscription.edit(
title= "Test hosting sub start %s" % self.new_id,
reference="TESTHSS-%s" % self.new_id,
)
self.portal.portal_workflow._jumpToStateFor(hosting_subscription, slap_state)
return hosting_subscription
def _simulateScript(self, script_name, fake_return='True'): def _simulateScript(self, script_name, fake_return='True'):
if script_name in self.portal.portal_skins.custom.objectIds(): if script_name in self.portal.portal_skins.custom.objectIds():
raise ValueError('Precondition failed: %s exists in custom' % script_name) raise ValueError('Precondition failed: %s exists in custom' % script_name)
...@@ -126,30 +139,44 @@ return %s ...@@ -126,30 +139,44 @@ return %s
computer3.workflow_history['edit_workflow'][-1]['comment']) computer3.workflow_history['edit_workflow'][-1]['comment'])
def test_alarm_hosting_subscription_create_upgrade_decision(self): def test_alarm_hosting_subscription_create_upgrade_decision(self):
computer = self._makeComputer(self.new_id) hosting_subscription = self._makeHostingSubscription()
computer.edit(allocation_scope = 'open/public') hosting_subscription2 = self._makeHostingSubscription()
computer2 = self._makeComputer(self.generateNewId()) hosting_subscription3 = self._makeHostingSubscription()
computer2.edit(allocation_scope = 'open/personal')
computer3 = self._makeComputer(self.generateNewId())
computer3.edit(allocation_scope = 'open/friend')
self._simulateScript('Computer_createHostingSubscriptionUpgradeDecision') self._simulateScript('HostingSubscription_createUpgradeDecision')
try: try:
self.portal.portal_alarms.slapos_pdm_hosting_subscription_create_upgrade_decision.\ self.portal.portal_alarms.slapos_pdm_hosting_subscription_create_upgrade_decision.\
activeSense() activeSense()
self.tic() self.tic()
finally: finally:
self._dropScript('Computer_createHostingSubscriptionUpgradeDecision') self._dropScript('HostingSubscription_createUpgradeDecision')
self.assertEqual('Visited by Computer_createHostingSubscriptionUpgradeDecision', self.assertEqual('Visited by HostingSubscription_createUpgradeDecision',
computer.workflow_history['edit_workflow'][-1]['comment']) hosting_subscription.workflow_history['edit_workflow'][-1]['comment'])
self.assertEqual('Visited by Computer_createHostingSubscriptionUpgradeDecision', self.assertEqual('Visited by HostingSubscription_createUpgradeDecision',
computer2.workflow_history['edit_workflow'][-1]['comment']) hosting_subscription2.workflow_history['edit_workflow'][-1]['comment'])
self.assertEqual('Visited by Computer_createHostingSubscriptionUpgradeDecision', self.assertEqual('Visited by HostingSubscription_createUpgradeDecision',
computer3.workflow_history['edit_workflow'][-1]['comment']) hosting_subscription3.workflow_history['edit_workflow'][-1]['comment'])
def test_alarm_create_upgrade_decision_destroyed_hosting_subscription(self):
hosting_subscription = self._makeHostingSubscription(slap_state="destroy_requested")
hosting_subscription2 = self._makeHostingSubscription(slap_state="destroy_requested")
self._simulateScript('HostingSubscription_createUpgradeDecision')
try:
self.portal.portal_alarms.slapos_pdm_hosting_subscription_create_upgrade_decision.\
activeSense()
self.tic()
finally:
self._dropScript('HostingSubscription_createUpgradeDecision')
self.assertNotEqual('Visited by HostingSubscription_createUpgradeDecision',
hosting_subscription.workflow_history['edit_workflow'][-1]['comment'])
self.assertNotEqual('Visited by HostingSubscription_createUpgradeDecision',
hosting_subscription2.workflow_history['edit_workflow'][-1]['comment'])
def test_alarm_create_upgrade_decision_closed_computer(self): def test_alarm_create_upgrade_decision_closed_computer(self):
computer = self._makeComputer(self.new_id) computer = self._makeComputer(self.new_id)
......
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