Commit 736be971 authored by Romain Courteaud's avatar Romain Courteaud

slapos_cloud:

* propagate Remote Node requests
* define destination_project/section on Remote Node
* Remote Node can also be defined on Allocation Supply
* test requesting Remote Slave
* allow remote allocation on an uniq hardcoded partition
parent 974cce84
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Alarm" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>active_sense_method_id</string> </key>
<value> <string>Alarm_propagateRemoteNodeInstance</string> </value>
</item>
<item>
<key> <string>automatic_solve</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>slapos_cloud_propagate_remote_node_instance</string> </value>
</item>
<item>
<key> <string>periodicity_day_frequency</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>periodicity_hour</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_hour_frequency</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>periodicity_minute</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_minute_frequency</string> </key>
<value> <int>5</int> </value>
</item>
<item>
<key> <string>periodicity_month</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_month_day</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_start_date</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>3660.0</float>
<string>GMT</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>periodicity_week</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Alarm</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Propagate Remote Node Instance</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -27,6 +27,8 @@
<item>business_application</item>
</portal_type>
<portal_type id="Remote Node">
<item>destination_project</item>
<item>destination_section</item>
<item>specialise</item>
</portal_type>
<portal_type id="Slave Instance">
......
portal = context.getPortalObject()
portal.portal_catalog.searchAndActivate(
portal_type='Compute Partition',
free_for_request=0,
parent_portal_type='Remote Node',
method_id='ComputePartition_propagateRemoteNode',
activate_kw={'tag': tag}
)
context.activate(after_tag=tag).getId()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<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>tag, fixit, params</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Alarm_propagateRemoteNodeInstance</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -84,6 +84,10 @@
<string>Instance Node</string>
<string>Instance Node</string>
</tuple>
<tuple>
<string>Remote Node</string>
<string>Remote Node</string>
</tuple>
</list>
</value>
</item>
......
slap_state = context.getSlapState()
portal = context.getPortalObject()
compute_node = context.getParentValue()
if slap_state == 'free':
compute_node = context.getParentValue()
return compute_node.ComputeNode_getSoftwareReleaseUrlStringList()
elif slap_state == 'busy':
......@@ -10,9 +11,12 @@ elif slap_state == 'busy':
instance = portal.portal_catalog.getResultValue(
portal_type="Software Instance",
validation_state="validated",
default_aggregate_uid=context.getUid(),
aggregate__uid=context.getUid(),
)
if (instance is None) or (instance.getSlapState() not in ["start_requested", "stop_requested"]):
# XXX Not very elegant
if (compute_node.getPortalType() == 'Remote Node') and (context.getId() == 'SHARED_REMOTE'):
return ['ANY_URL']
return []
else:
return [instance.getUrlString()]
......
portal = context.getPortalObject()
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 compute_partition.getId() == 'SHARED_REMOTE':
# Hardcoded ID behaviour
local_instance_list = portal.portal_catalog(
portal_type='Slave Instance',
aggregate__uid=compute_partition.getUid()
)
else:
local_instance_list = [portal.portal_catalog.getResultValue(
portal_type='Software Instance',
aggregate__uid=compute_partition.getUid()
)]
for local_instance in local_instance_list:
# XXX TODO this will increase the workflow history
# Use the 'cached' API instead
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')
if requested_software_instance is not None:
local_instance.setConnectionXml(requested_software_instance.getConnectionXml())
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<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></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ComputePartition_propagateRemoteNode</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -36,6 +36,8 @@ software_product, release_variation, type_variation = tmp_instance.InstanceTree_
if software_product is None:
raise ValueError('No Software Product matching')
assert software_product.getFollowUpUid() == project_uid
allocation_cell_list = software_product.getFollowUpValue().Project_getSoftwareProductPredicateList(
software_product=software_product,
software_product_type=type_variation,
......@@ -44,7 +46,6 @@ allocation_cell_list = software_product.getFollowUpValue().Project_getSoftwarePr
predicate_portal_type='Allocation Supply Cell'
)
#context.log('allocation_cell_list %s' % str(allocation_cell_list))
if not allocation_cell_list:
raise ValueError('No Allocation Supply allowing this operation')
......@@ -79,6 +80,10 @@ for compute_node_list, is_slave_on_same_instance_tree_allocable in compute_node_
elif compute_node.getPortalType() == 'Remote Node':
parent_uid_list.append(compute_node.getUid())
# This is the only hardcoded partition accepting any slave instance allocation
shared_partition = compute_node.restrictedTraverse('SHARED_REMOTE', None)
if shared_partition is not None:
partition_uid_list.append(shared_partition.getUid())
else:
raise NotImplementedError('Unsupported Node type: %s' % compute_node.getPortalType())
......
......@@ -4,4 +4,14 @@ reference = "REMOTE-%s" % portal.portal_ids.generateNewId(
id_group='slap_instance_node_reference',
id_generator='uid', default=1)
# XXX format
partition = context.newContent(
portal_type='Compute Partition',
reference='shared_partition',
id='SHARED_REMOTE'
)
partition.markFree()
partition.markBusy()
partition.validate()
context.edit(reference=reference)
......@@ -479,7 +479,10 @@ class DefaultScenarioMixin(TestSlapOSSecurityMixin):
def checkRemoteInstanceAllocation(self, person_user_id, person_reference,
instance_title, software_release, software_type, server,
project_reference, connection_dict_to_check=None):
project_reference, connection_dict_to_check=None,
slave=False):
shared_xml = '<marshal><bool>%i</bool></marshal>' % int(slave)
self.login(person_user_id)
......@@ -488,7 +491,8 @@ class DefaultScenarioMixin(TestSlapOSSecurityMixin):
software_release=software_release,
software_type=software_type,
partition_reference=instance_title,
project_reference=project_reference
project_reference=project_reference,
shared_xml=shared_xml,
)
self.checkCloudContract(person_user_id, person_reference,
......@@ -501,7 +505,8 @@ class DefaultScenarioMixin(TestSlapOSSecurityMixin):
software_release=software_release,
software_type=software_type,
partition_reference=instance_title,
project_reference=project_reference
project_reference=project_reference,
shared_xml=shared_xml,
)
# now instantiate it on compute_node and set some nice connection dict
......
......@@ -12,6 +12,7 @@ person_module/template_member/**
portal_alarms/slapos_allocate_instance
portal_alarms/slapos_assert_instance_tree_successor
portal_alarms/slapos_cloud_invalidate_destroyed_instance
portal_alarms/slapos_cloud_propagate_remote_node_instance
portal_alarms/slapos_free_compute_partition
portal_alarms/slapos_garbage_collect_destroyed_root_tree
portal_alarms/slapos_garbage_collect_non_allocated_root_tree
......@@ -26,4 +27,4 @@ portal_caches/last_stored_data_cache_factory/volatile_cache_plugin
product_module/compute_node
software_installation_module/template_software_installation
software_instance_module/template_slave_instance
software_instance_module/template_software_instance
software_instance_module/template_software_instance
\ No newline at end of file
......@@ -7,6 +7,8 @@ Hosting Subscription Module | business_application
Instance Node | specialise
Instance Tree Module | business_application
Instance Tree | destination_section
Remote Node | destination_project
Remote Node | destination_section
Remote Node | specialise
Slave Instance | aggregate
Slave Instance | specialise
......
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