Commit bdd29231 authored by Romain Courteaud's avatar Romain Courteaud

slapos_pdm: wip upgrade decision redesign with allocation supply

parent d01bc043
......@@ -2,64 +2,77 @@ from DateTime import DateTime
portal = context.getPortalObject()
instance_tree = context
upgrade_scope = context.getUpgradeScope("ask_confirmation")
if upgrade_scope in ["never", "disabled"]:
return
root_instance_list = [
q for q in instance_tree.getSuccessorValueList(portal_type=["Software Instance", "Slave Instance"])
if q.getSlapState() != 'destroy_requested']
if len(root_instance_list) == 0:
return
root_instance = root_instance_list[0]
slave_upgrade = False
if root_instance.getPortalType() == 'Slave Instance':
slave_upgrade = True
upgrade_scope = "auto"
if instance_tree.getSlapState() == "destroy_requested":
return
# Check if UpgradeDecision_approveRegistration is running
# XXX we should instead look at the current upgrade decision state
tag = "%s_requestUpgradeDecisionCreation_inProgress" % instance_tree.getUid()
if portal.portal_activities.countMessageWithTag(tag) > 0:
# nothing to do
# previous run not finished, skip
return
partition = root_instance.getAggregateValue(portal_type="Compute Partition")
if partition is None:
upgrade_scope = context.getUpgradeScope("ask_confirmation")
if upgrade_scope in ["never", "disabled"]:
return
decision_title = 'A new upgrade is available for %s' % instance_tree.getTitle()
newer_release = None
software_product, software_release, software_type = instance_tree.InstanceTree_getSoftwareProduct()
if slave_upgrade:
software_instance = partition.getAggregateRelatedValue(portal_type='Software Instance')
if software_instance:
url_string = software_instance.getUrlString()
if url_string != instance_tree.getUrlString():
newer_release = context.portal_catalog.getResultValue(portal_type='Software Release', url_string=url_string)
else:
newer_release = instance_tree.\
InstanceTree_getUpgradableSoftwareRelease()
if newer_release is None:
if software_product is None:
# No way to upgrade, if we can find which Software Product to upgrade
return
decision_in_progress = newer_release.\
SoftwareRelease_getUpgradeDecisionInProgress(instance_tree.getUid())
if decision_in_progress:
decision_in_progress.reviewRegistration(
software_release_url=newer_release.getUrlString())
if decision_in_progress.getSimulationState() != "cancelled":
return
node = None
root_instance_list = [
q for q in instance_tree.getSuccessorValueList(portal_type=["Software Instance", "Slave Instance"])
if q.getSlapState() != 'destroy_requested']
if len(root_instance_list) != 0:
root_instance = root_instance_list[0]
upgrade_decision = newer_release.SoftwareRelease_createUpgradeDecision(
source_url=instance_tree.getRelativeUrl(),
title=decision_title
person = context.getDestinationSectionValue()
# Search if the product with the same type
# XXX search only for the main node
allocation_cell_list = software_product.getFollowUpValue().Project_getSoftwareProductPredicateList(
software_product=software_product,
software_product_type=software_type,
#software_product_release=software_release,
destination_value=person,
predicate_portal_type='Allocation Supply Cell'
)
upgrade_decision.approveRegistration(
upgrade_scope=upgrade_scope)
# Only upgrade if there is no doubt (ie, only 1 url is allowed)
if len(allocation_cell_list) == 1:
if (allocation_cell_list[0].getSoftwareType() != instance_tree.getUrlString()):
# XXX Upgrade
decision_title = 'A new upgrade is available for %s' % instance_tree.getTitle()
decision_in_progress = portal.portal_catalog.getResultValue(
portal_type='Upgrade Decision',
aggregate__uid=instance_tree.getUid()
)
if decision_in_progress:
if 1:
raise NotImplementedError('reviewRegistration')
decision_in_progress.reviewRegistration(
software_release_url=newer_release.getUrlString())
if decision_in_progress.getSimulationState() != "cancelled":
return
upgrade_decision = portal.upgrade_decision_module.newContent(
portal_type='Upgrade Decision',
title=decision_title,
destination_section_value=person,
destination_decision_value=person,
destination_project_value=instance_tree.getFollowUpValue(),
resource_value=software_product,
variation_category_list=allocation_cell_list[0].getVariationCategoryList(),
aggregate_value=instance_tree,
)
upgrade_decision.approveRegistration(
upgrade_scope=upgrade_scope)
return upgrade_decision
return upgrade_decision
from DateTime import DateTime
portal = context.getPortalObject()
software_release = context
source_product = portal.restrictedTraverse(source_url, None)
if not source_product:
return
portal_type = source_product.getPortalType()
if portal_type == 'Instance Tree':
person_url = source_product.getDestinationSection()
else:
return
if not person_url:
return
upgrade_decision = portal.upgrade_decision_module.\
template_upgrade_decision.Base_createCloneDocument(batch_mode=1)
upgrade_decision.edit(title=title)
upgrade_decision.setDestinationSection(person_url)
upgrade_decision.setDestinationDecision(person_url)
decision_line_list = upgrade_decision.contentValues(
portal_type='Upgrade Decision Line')
if len(decision_line_list) > 0:
decision_line = decision_line_list[0]
else:
decision_line = upgrade_decision.newContent(
portal_type='Upgrade Decision Line')
decision_line.edit(
title='Request decision upgrade for %s on %s %s' % (
software_release.getTitle(), portal_type, source_product.getReference()),
aggregate=[source_url, software_release.getRelativeUrl()])
return upgrade_decision
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>source_url, title</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SoftwareRelease_createUpgradeDecision</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
portal = context.getPortalObject()
product_reference = context.getAggregateReference()
decision_line_in_progress_list = portal.portal_catalog(
portal_type='Upgrade Decision Line',
default_aggregate_uid=aggregate_uid)
for decision_line in decision_line_in_progress_list:
upgrade_decision = decision_line.getParentValue()
simulation_state = upgrade_decision.getSimulationState()
if simulation_state not in ['planned', 'confirmed',
'started', 'stopped', 'rejected']:
continue
release_list = decision_line.getAggregateValueList(portal_type="Software Release")
if len(release_list) > 1:
continue
if not release_list:
continue
# If the current sr in rejected we must prevent creation of new upgrade decision for this sr
if simulation_state == 'rejected' and \
release_list[0].getUrlString() != context.getUrlString():
continue
# If both software release belong to the same software product, there is an upgrade decision in progress
if product_reference == release_list[0].getAggregateReference():
return upgrade_decision
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>aggregate_uid</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SoftwareRelease_getUpgradeDecisionInProgress</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -20,31 +20,50 @@
##############################################################################
from erp5.component.test.testSlapOSPDMSkins import TestSlapOSPDMMixinSkins
from DateTime import DateTime
import transaction
class TestSlapOSPDMCreateUpgradeDecisionSkins(TestSlapOSPDMMixinSkins):
def _makeSoftwareProductCatalog(self):
self.software_product = self._makeSoftwareProduct(self.generateNewId())
self.previous_software_release = self._makeSoftwareRelease(self.generateNewId())
self.new_software_release = self._makeSoftwareRelease(self.generateNewId())
self.previous_software_release.publish()
self.new_software_release.publish()
def afterSetUp(self):
self.portal.testromain()
TestSlapOSPDMMixinSkins.afterSetUp(self)
preference = self.portal.portal_preferences.getActiveSystemPreference()
preference.setPreferredCloudContractEnabled(True)
self.tic()
self.project = self.addProject()
self._makeComputeNode()
self._makeSoftwareProductCatalog(self.project)
self._installSoftwareOnTheComputeNode([
self.previous_software_release.getUrlString(),
self.new_software_release.getUrlString()
])
self.person = self.makePerson(self.project)
self.tic()
self._makeTreeForTestSlapOSPDMCreateUpgradeDecisionSkins(
self.previous_software_release.getUrlString(),
self.software_product.contentValues(portal_type='Software Product Type Variation')[0].getTitle(),
self.project
)
self.previous_software_release.edit(
aggregate=self.software_product.getRelativeUrl(),
url_string=self.generateNewSoftwareReleaseUrl(),
version='1',
effective_date=DateTime()-1,
def _makeSoftwareProductCatalog(self, project):
self.software_product = self._makeSoftwareProduct(
project,
new_id=self.generateNewId(),
url=self.generateNewSoftwareReleaseUrl(),
software_type='foobartype'
)
self.previous_software_release = self._makeSoftwareRelease(self.software_product)
self.new_software_release = self._makeSoftwareRelease(self.software_product)
self.new_software_release.edit(
aggregate=self.software_product.getRelativeUrl(),
url_string=self.generateNewSoftwareReleaseUrl(),
version='2',
effective_date=DateTime(),
self.addAllocationSupply(
"for compute node",
# XXX node node
None,
self.software_product,
self.new_software_release,
self.software_product.contentValues(portal_type='Software Product Type Variation')[0],
)
self.tic()
def _installSoftwareOnTheComputeNode(self, software_release_url_list):
......@@ -57,7 +76,7 @@ class TestSlapOSPDMCreateUpgradeDecisionSkins(TestSlapOSPDMMixinSkins):
software_installation.requestStart()
self.tic()
def _createInstance(self, url_string, shared=False):
def _createInstance(self, url_string, software_type, project, shared=False):
instance_tree = self.portal.instance_tree_module\
.template_instance_tree.Base_createCloneDocument(batch_mode=1)
instance_tree.edit(
......@@ -66,16 +85,18 @@ class TestSlapOSPDMCreateUpgradeDecisionSkins(TestSlapOSPDMMixinSkins):
instance_tree.edit(
title=self.generateNewSoftwareTitle(),
reference="TESTHS-%s" % self.generateNewId(),
destination_section_value=self.person
destination_section_value=self.person,
follow_up_value=project
)
request_kw = dict(
software_release=url_string,
software_type=self.generateNewSoftwareType(),
software_type=software_type,
instance_xml=self.generateSafeXml(),
sla_xml=self.generateSafeXml(),
shared=shared,
software_title=instance_tree.getTitle(),
state='started'
state='started',
project_reference=project.getReference()
)
instance_tree.requestStart(**request_kw)
instance_tree.requestInstance(**request_kw)
......@@ -84,30 +105,14 @@ class TestSlapOSPDMCreateUpgradeDecisionSkins(TestSlapOSPDMMixinSkins):
self.tic()
return instance_tree, instance
def _makeTreeForTestSlapOSPDMCreateUpgradeDecisionSkins(self, software_release_url):
self.instance_tree, self.instance = self._createInstance(software_release_url)
self.shared_instance_tree, self.shared_instance = self._createInstance(software_release_url, True)
def _makeTreeForTestSlapOSPDMCreateUpgradeDecisionSkins(self, software_release_url, software_type, project):
self.instance_tree, self.instance = self._createInstance(software_release_url, software_type, project)
self.shared_instance_tree, self.shared_instance = self._createInstance(software_release_url, software_type, project, True)
self.instance.setAggregate(self.partition.getRelativeUrl())
self.shared_instance.setAggregate(self.partition.getRelativeUrl())
self.partition.markBusy()
self.tic()
def afterSetUp(self):
TestSlapOSPDMMixinSkins.afterSetUp(self)
preference = self.portal.portal_preferences.getActiveSystemPreference()
preference.setPreferredCloudContractEnabled(True)
self.tic()
self._makeComputeNode()
self._makeSoftwareProductCatalog()
self._installSoftwareOnTheComputeNode([
self.previous_software_release.getUrlString(),
self.new_software_release.getUrlString()
])
self.person = self.makePerson()
self.tic()
self._makeTreeForTestSlapOSPDMCreateUpgradeDecisionSkins(
self.previous_software_release.getUrlString())
def test_InstanceTree_createUpgradeDecision_upgradeScopeConfirmation(self):
# check upgrade decision on HS
self.instance_tree.setUpgradeScope('manual')
......@@ -168,7 +173,7 @@ class TestSlapOSPDMCreateUpgradeDecisionSkins(TestSlapOSPDMMixinSkins):
person = self._makePerson()
compute_node, _ = self._makeComputeNode(owner=person)
self._makeComputePartitions(compute_node)
software_product = self._makeSoftwareProduct()
software_product = self._makeSoftwareProduct(self.project)
software_release = self._requestSoftwareRelease(
software_product.getRelativeUrl())
url_string = software_release.getUrlString()
......@@ -197,7 +202,7 @@ class TestSlapOSPDMCreateUpgradeDecisionSkins(TestSlapOSPDMMixinSkins):
person = self._makePerson()
compute_node, _ = self._makeComputeNode(owner=person, allocation_scope="close/outdated")
self._makeComputePartitions(compute_node)
software_product = self._makeSoftwareProduct()
software_product = self._makeSoftwareProduct(self.project)
software_release = self._requestSoftwareRelease(
software_product.getRelativeUrl())
url_string = software_release.getUrlString()
......@@ -233,7 +238,7 @@ class TestSlapOSPDMCreateUpgradeDecisionSkins(TestSlapOSPDMMixinSkins):
person = self._makePerson()
compute_node, _ = self._makeComputeNode(owner=person, allocation_scope="open/personal")
self._makeComputePartitions(compute_node)
software_product = self._makeSoftwareProduct()
software_product = self._makeSoftwareProduct(self.project)
software_release = self._requestSoftwareRelease(
software_product.getRelativeUrl())
url_string = software_release.getUrlString()
......@@ -267,7 +272,7 @@ class TestSlapOSPDMCreateUpgradeDecisionSkins(TestSlapOSPDMMixinSkins):
person = self._makePerson()
compute_node, _ = self._makeComputeNode(owner=person)
self._makeComputePartitions(compute_node)
software_product = self._makeSoftwareProduct()
software_product = self._makeSoftwareProduct(self.project)
software_release = self._requestSoftwareRelease(
software_product.getRelativeUrl())
url_string = software_release.getUrlString()
......@@ -308,7 +313,7 @@ class TestSlapOSPDMCreateUpgradeDecisionSkins(TestSlapOSPDMMixinSkins):
person = self._makePerson()
compute_node, _ = self._makeComputeNode(owner=person)
self._makeComputePartitions(compute_node)
software_product = self._makeSoftwareProduct()
software_product = self._makeSoftwareProduct(self.project)
software_release = self._requestSoftwareRelease(
software_product.getRelativeUrl())
url_string = software_release.getUrlString()
......@@ -348,7 +353,7 @@ class TestSlapOSPDMCreateUpgradeDecisionSkins(TestSlapOSPDMMixinSkins):
person = self._makePerson()
compute_node, _ = self._makeComputeNode(owner=person)
self._makeComputePartitions(compute_node)
software_product = self._makeSoftwareProduct()
software_product = self._makeSoftwareProduct(self.project)
software_release = self._requestSoftwareRelease(
software_product.getRelativeUrl())
url_string = software_release.getUrlString()
......@@ -387,7 +392,7 @@ class TestSlapOSPDMCreateUpgradeDecisionSkins(TestSlapOSPDMMixinSkins):
person = self._makePerson()
compute_node, _ = self._makeComputeNode(owner=person)
self._makeComputePartitions(compute_node)
software_product = self._makeSoftwareProduct()
software_product = self._makeSoftwareProduct(self.project)
software_release = self._requestSoftwareRelease(
software_product.getRelativeUrl())
url_string = software_release.getUrlString()
......
......@@ -713,7 +713,7 @@ class TestSlapOSPDMSkins(TestSlapOSPDMMixinSkins):
def testComputeNode_checkAndCreateUpgradeDecision_auto(self):
person = self._makePerson()
compute_node, _ = self._makeComputeNode(owner=person,
allocation_scope="open/public")
allocation_scope="open")
compute_node.edit(upgrade_scope="auto")
software_product = self._makeSoftwareProduct()
software_release = self._requestSoftwareRelease(
......@@ -777,7 +777,7 @@ class TestSlapOSPDMSkins(TestSlapOSPDMMixinSkins):
def testComputeNode_checkAndCreateUpgradeDecision_auto_with_exist(self):
person = self._makePerson()
compute_node, _ = self._makeComputeNode(owner=person,
allocation_scope="open/public")
allocation_scope="open")
compute_node.edit(upgrade_scope="auto")
software_product = self._makeSoftwareProduct()
software_release = self._requestSoftwareRelease(
......
......@@ -2,12 +2,7 @@ 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.")
instance_tree = upgrade_decision.getAggregateValue()
# Get required arguments
kwargs = state_change.kwargs
......@@ -19,7 +14,7 @@ try:
except KeyError:
raise TypeError("UpgradeDecision_approveRegistration takes exactly 1 arguments")
tag = "%s_requestUpgradeDecisionCreation_inProgress" % document.getUid()
tag = "%s_requestUpgradeDecisionCreation_inProgress" % instance_tree.getUid()
activate_kw = {'tag': tag}
if portal.portal_activities.countMessageWithTag(tag) > 0:
# nothing to do
......@@ -35,4 +30,4 @@ with upgrade_decision.defaultActivateParameterDict(activate_kw):
upgrade_decision.start()
# Prevent concurrent transaction to create 2 upgrade decision for the same instance_tree
document.serialize()
instance_tree.serialize()
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