Commit 2ce4c73d authored by Romain Courteaud's avatar Romain Courteaud

slapos_cloud: create many activites to propagate the remote node informations

It will reduce the transaction time, and so, reduce conflict cost

Ensure instance is indexed before propagating to the remote node
parent a90c5a4d
......@@ -8,114 +8,32 @@ compute_partition = context
remote_node = compute_partition.getParentValue()
assert remote_node.getPortalType() == 'Remote Node'
remote_project = remote_node.getDestinationProjectValue(portal_type='Project')
remote_person = remote_node.getDestinationSectionValue(portal_type='Person')
if local_instance_list is None:
if compute_partition.getId() == 'SHARED_REMOTE':
# Hardcoded ID behaviour
local_instance_list = portal.portal_catalog(
search_kw = dict(
portal_type='Slave Instance',
aggregate__uid=compute_partition.getUid(),
validation_state='validated'
)
else:
local_instance_list = portal.portal_catalog(
search_kw = dict(
portal_type='Software Instance',
aggregate__uid=compute_partition.getUid(),
validation_state='validated'
)
else:
local_instance_list = [portal.restrictedTraverse(x) for x in local_instance_list]
for local_instance in local_instance_list:
assert local_instance.getAggregate() == compute_partition.getRelativeUrl()
# If local instance destruction has been propagated, do nothing
if local_instance.getValidationState() != 'validated':
continue
# do not increase the workflow history
# Use the 'cached' API instead
# manually search the instance and compare all parameters
remote_instance_tree = portal.portal_catalog.getResultValue(
portal_type='Instance Tree',
validation_state='validated',
destination_section__uid=remote_person.getUid(),
follow_up__uid=remote_project.getUid(),
title={'query': '_remote_%s_%s' % (local_instance.getFollowUpReference(),
local_instance.getReference()),
'key': 'ExactMatch'}
)
if remote_instance_tree is not None:
requested_software_instance = remote_instance_tree.getSuccessorValue(title=remote_instance_tree.getTitle())
if (local_instance.getSlapState() == 'destroy_requested'):
if (remote_instance_tree is not None) and \
(remote_instance_tree.getSlapState() != 'destroy_requested'):
# if local instance is destroyed, propagate blindly (do not check url, text content, ...)
remote_person.requestSoftwareInstance(
project_reference=remote_project.getReference(),
software_release=remote_instance_tree.getUrlString(),
software_title='_remote_%s_%s' % (remote_node.getFollowUpReference(), local_instance.getReference()),
software_type=remote_instance_tree.getSourceReference(),
instance_xml=remote_instance_tree.getTextContent(),
sla_xml=None,
shared=(local_instance.getPortalType() == 'Slave Instance'),
state='destroyed'
)
remote_instance_tree.reindexObject(activate_kw=activate_kw)
local_instance.invalidate(comment='Remote destruction has been propagated')
# Try to no trigger the script again on this object
local_instance.reindexObject(activate_kw=activate_kw)
continue
if (remote_instance_tree is not None) and \
((local_instance.getUrlString() != remote_instance_tree.getUrlString()) or \
(local_instance.getSourceReference() != remote_instance_tree.getSourceReference())):
# Try to create an Upgrade Decision for the new release
# XXX Move this code to InstanceTree_createUpgradeDecision, and pass only string arguments to it
_, new_release_variation, new_type_variation = remote_instance_tree.asContext(
url_string=local_instance.getUrlString(),
source_reference=local_instance.getSourceReference()
).InstanceTree_getSoftwareProduct()
if new_release_variation is None:
# Nothing can be done. Sadly, leave it as is for now.
continue
else:
return remote_instance_tree.InstanceTree_createUpgradeDecision(
target_software_release=new_release_variation,
target_software_type=new_type_variation
)
if (remote_instance_tree is None) or \
(local_instance.getTextContent() != remote_instance_tree.getTextContent()) or \
(local_instance.getSlapState() != remote_instance_tree.getSlapState()):
remote_person.requestSoftwareInstance(
project_reference=remote_project.getReference(),
software_release=local_instance.getUrlString(),
software_title='_remote_%s_%s' % (remote_node.getFollowUpReference(), local_instance.getReference()),
software_type=local_instance.getSourceReference(),
instance_xml=local_instance.getTextContent(),
sla_xml=None,
shared=(local_instance.getPortalType() == 'Slave Instance'),
state={'start_requested': 'started', 'stop_requested': 'stopped'}[local_instance.getSlapState()]
)
requested_software_instance = context.REQUEST.get('request_instance')
requested_instance_tree = context.REQUEST.get('request_instance_tree')
# Try to no trigger the script again on this object
requested_instance_tree.reindexObject(activate_kw=activate_kw)
if requested_software_instance is not None:
requested_software_instance.reindexObject(activate_kw=activate_kw)
if (requested_software_instance is not None) and \
(requested_software_instance.getConnectionXml() != local_instance.getConnectionXml()):
# Try to no trigger the script again on this object
local_instance.edit(
connection_xml=requested_software_instance.getConnectionXml(),
activate_kw=activate_kw
)
search_kw = dict(uid=[portal.restrictedTraverse(x).getUid() for x in local_instance_list])
# Partition may have a lot of Slave Instance in case of CDN.
# Create many activities, to use all activity nodes, reduce transaction time,
# and reduce conflict cost
if activate_kw is None:
activate_kw = {}
portal.portal_catalog.searchAndActivate(
method_id='SoftwareInstance_propagateRemoteNode',
method_kw={"activate_kw": activate_kw},
activate_kw=activate_kw,
**search_kw
)
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
local_instance = context
compute_partition = local_instance.getAggregateValue()
if compute_partition is None:
return
remote_node = compute_partition.getParentValue()
assert remote_node.getPortalType() == 'Remote Node'
remote_project = remote_node.getDestinationProjectValue(portal_type='Project')
remote_person = remote_node.getDestinationSectionValue(portal_type='Person')
# If local instance destruction has been propagated, do nothing
if local_instance.getValidationState() != 'validated':
return
# do not increase the workflow history
# Use the 'cached' API instead
# manually search the instance and compare all parameters
remote_instance_tree = portal.portal_catalog.getResultValue(
portal_type='Instance Tree',
validation_state='validated',
destination_section__uid=remote_person.getUid(),
follow_up__uid=remote_project.getUid(),
title={'query': '_remote_%s_%s' % (local_instance.getFollowUpReference(),
local_instance.getReference()),
'key': 'ExactMatch'}
)
if remote_instance_tree is not None:
requested_software_instance = remote_instance_tree.getSuccessorValue(title=remote_instance_tree.getTitle())
if (local_instance.getSlapState() == 'destroy_requested'):
if (remote_instance_tree is not None) and \
(remote_instance_tree.getSlapState() != 'destroy_requested'):
# if local instance is destroyed, propagate blindly (do not check url, text content, ...)
remote_person.requestSoftwareInstance(
project_reference=remote_project.getReference(),
software_release=remote_instance_tree.getUrlString(),
software_title='_remote_%s_%s' % (remote_node.getFollowUpReference(), local_instance.getReference()),
software_type=remote_instance_tree.getSourceReference(),
instance_xml=remote_instance_tree.getTextContent(),
sla_xml=None,
shared=(local_instance.getPortalType() == 'Slave Instance'),
state='destroyed'
)
remote_instance_tree.reindexObject(activate_kw=activate_kw)
local_instance.invalidate(comment='Remote destruction has been propagated')
# Try to no trigger the script again on this object
local_instance.reindexObject(activate_kw=activate_kw)
return
if (remote_instance_tree is not None) and \
((local_instance.getUrlString() != remote_instance_tree.getUrlString()) or \
(local_instance.getSourceReference() != remote_instance_tree.getSourceReference())):
# Try to create an Upgrade Decision for the new release
# XXX Move this code to InstanceTree_createUpgradeDecision, and pass only string arguments to it
_, new_release_variation, new_type_variation = remote_instance_tree.asContext(
url_string=local_instance.getUrlString(),
source_reference=local_instance.getSourceReference()
).InstanceTree_getSoftwareProduct()
if new_release_variation is None:
# Nothing can be done. Sadly, leave it as is for now.
return
else:
return remote_instance_tree.InstanceTree_createUpgradeDecision(
target_software_release=new_release_variation,
target_software_type=new_type_variation
)
if (remote_instance_tree is None) or \
(local_instance.getTextContent() != remote_instance_tree.getTextContent()) or \
(local_instance.getSlapState() != remote_instance_tree.getSlapState()):
remote_person.requestSoftwareInstance(
project_reference=remote_project.getReference(),
software_release=local_instance.getUrlString(),
software_title='_remote_%s_%s' % (remote_node.getFollowUpReference(), local_instance.getReference()),
software_type=local_instance.getSourceReference(),
instance_xml=local_instance.getTextContent(),
sla_xml=None,
shared=(local_instance.getPortalType() == 'Slave Instance'),
state={'start_requested': 'started', 'stop_requested': 'stopped'}[local_instance.getSlapState()]
)
requested_software_instance = context.REQUEST.get('request_instance')
requested_instance_tree = context.REQUEST.get('request_instance_tree')
# Try to no trigger the script again on this object
requested_instance_tree.reindexObject(activate_kw=activate_kw)
if requested_software_instance is not None:
requested_software_instance.reindexObject(activate_kw=activate_kw)
if (requested_software_instance is not None) and \
(requested_software_instance.getConnectionXml() != local_instance.getConnectionXml()):
# Try to no trigger the script again on this object
local_instance.edit(
connection_xml=requested_software_instance.getConnectionXml(),
activate_kw=activate_kw
)
<?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>activate_kw=None, REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SoftwareInstance_propagateRemoteNode</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -1277,6 +1277,7 @@ class TestSlapOSPropagateRemoteNodeInstance(SlapOSTestCaseMixin):
sla_xml=self.generateSafeXml()
)
partition.ComputePartition_propagateRemoteNode()
self.tic()
self.assertNotEqual(remote_instance_tree.getModificationDate(),
remote_modification_date)
......@@ -1310,7 +1311,7 @@ class TestSlapOSPropagateRemoteNodeInstance(SlapOSTestCaseMixin):
with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
partition.ComputePartition_propagateRemoteNode()
self.tic()
self.tic()
remote_user = remote_node.getDestinationSectionValue()
remote_project = remote_node.getDestinationProjectValue()
......@@ -1433,7 +1434,7 @@ class TestSlapOSPropagateRemoteNodeInstance(SlapOSTestCaseMixin):
with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
partition.ComputePartition_propagateRemoteNode()
self.tic()
self.tic()
remote_user = remote_node.getDestinationSectionValue()
remote_project = remote_node.getDestinationProjectValue()
......@@ -1452,6 +1453,7 @@ class TestSlapOSPropagateRemoteNodeInstance(SlapOSTestCaseMixin):
)
with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
partition.ComputePartition_propagateRemoteNode()
self.tic()
self.assertNotEqual(software_instance.getModificationDate(), modification_date)
self.assertEqual(remote_instance_tree.getValidationState(), "validated")
......@@ -1501,6 +1503,7 @@ class TestSlapOSPropagateRemoteNodeInstance(SlapOSTestCaseMixin):
self.tic()
self.assertEqual(software_instance.getValidationState(), 'validated')
partition.ComputePartition_propagateRemoteNode()
self.tic()
self.assertNotEqual(remote_instance_tree.getModificationDate(),
remote_modification_date)
......
instance = state_change['object']
partition = instance.getAggregateValue()
if (partition is not None) and (partition.getParentValue().getPortalType() == 'Remote Node'):
instance.Base_reindexAndSenseAlarm(['slapos_cloud_propagate_remote_node_instance'])
partition.Base_reindexAndSenseAlarm(['slapos_cloud_propagate_remote_node_instance'])
......@@ -105,6 +105,7 @@ def makeTestSlapOSCodingStyleTestCase(tested_business_template):
'slapos_cloud/SoftwareInstance_getComputePartitionIPv6',
'slapos_cloud/SoftwareInstance_getDefaultImageAbsoluteUrl',
'slapos_cloud/SoftwareInstance_init',
'slapos_cloud/SoftwareInstance_propagateRemoteNode',
'slapos_cloud/SoftwareInstance_renameAndRequestStopAction',
'slapos_cloud/SoftwareRelease_getRelatedNetworkList',
'slapos_cloud/SoftwareRelease_getUsableComputeNodeList',
......
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