Commit e1f74ff5 authored by Romain Courteaud's avatar Romain Courteaud

slapos_slap_tool: support for the virtual master logic

A project reference is required to create a compute node.

Add compatibility with the user request
Console client does not send a project reference.
Try to guess it for simple cases
parent e5f82c58
......@@ -16,7 +16,9 @@ def getComputeNodeReferenceAndUserId(item):
if partition is not None:
compute_node = partition.getParentValue()
if compute_node is not None and compute_node.getValidationState() == 'validated':
if (compute_node is not None) and \
(compute_node.getPortalType() == 'Compute Node') and \
(compute_node.getValidationState() == 'validated'):
return compute_node, compute_node.getReference(), compute_node.getUserId()
return None, None, None
......
......@@ -6,12 +6,6 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SlapOSSlapTool</string> </value>
......@@ -55,28 +49,13 @@
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
......@@ -89,7 +68,7 @@
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
......@@ -98,7 +77,7 @@
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
......
......@@ -5,8 +5,8 @@ class TestSlapOSCoreComputeNodeUpdateFromDict(SlapOSTestCaseMixinWithAbort):
def afterSetUp(self):
SlapOSTestCaseMixinWithAbort.afterSetUp(self)
self.compute_node = self.portal.compute_node_module.template_compute_node\
.Base_createCloneDocument(batch_mode=1)
self.compute_node = self.portal.compute_node_module\
.newContent(portal_type="Compute Node")
self.compute_node.edit(
reference='TESTC-%s' % self.generateNewId(),
)
......
......@@ -373,7 +373,7 @@ class SlapTool(BaseTool):
security.declareProtected(Permissions.AccessContentsInformation,
'getSoftwareReleaseListFromSoftwareProduct')
def getSoftwareReleaseListFromSoftwareProduct(self,
def getSoftwareReleaseListFromSoftwareProduct(self, project_reference,
software_product_reference=None, software_release_url=None):
"""
Get the list of all published Software Releases related to one of either:
......@@ -384,12 +384,23 @@ class SlapTool(BaseTool):
If referenced Software Product does not exist, return empty list.
If referenced Software Release does not exist, raise.
"""
project_list = self.getPortalObject().portal_catalog.portal_catalog(
portal_type='Project',
reference=project_reference,
validation_state='validated',
limit=2
)
if len(project_list) != 1:
raise NotImplementedError("%i projects '%s'" % (len(project_list), project_reference))
project = project_list[0]
if software_product_reference is None:
assert(software_release_url is not None)
software_product_reference = self.getPortalObject().portal_catalog.unrestrictedSearchResults(
portal_type='Software Release',
portal_type='Software Product Release Variation',
parent__follow_up__uid=project.getUid(),
url_string=software_release_url
)[0].getObject().getAggregateValue().getReference()
)[0].getObject().getParentValue().getReference()
else:
# Don't accept both parameters
assert(software_release_url is None)
......@@ -397,13 +408,14 @@ class SlapTool(BaseTool):
software_product_list = self.getPortalObject().portal_catalog.unrestrictedSearchResults(
portal_type='Software Product',
reference=software_product_reference,
follow_up__uid=project.getUid(),
validation_state='published')
if len(software_product_list) is 0:
return dumps([])
if len(software_product_list) > 1:
raise NotImplementedError('Several Software Product with the same title.')
software_release_list = \
software_product_list[0].getObject().getAggregateRelatedValueList()
software_product_list[0].getObject().contentValues(portal_type='Software Product Release Variation')
def sortkey(software_release):
publication_date = software_release.getEffectiveDate()
......@@ -420,9 +432,7 @@ class SlapTool(BaseTool):
)
return dumps(
[software_release.getUrlString()
for software_release in software_release_list
if software_release.getValidationState() in \
['published', 'published_alive']])
for software_release in software_release_list])
security.declareProtected(Permissions.AccessContentsInformation,
'getHateoasUrl')
......@@ -508,20 +518,20 @@ class SlapTool(BaseTool):
return self._supplySupply(url, computer_id, state)
@convertToREST
def _requestComputeNode(self, compute_node_title):
def _requestComputeNode(self, compute_node_title, project_reference):
portal = self.getPortalObject()
person = portal.portal_membership.getAuthenticatedMember().getUserValue()
person.requestComputeNode(compute_node_title=compute_node_title)
person.requestComputeNode(compute_node_title=compute_node_title, project_reference=project_reference)
compute_node = ComputeNode(self.REQUEST.get('compute_node_reference').decode("UTF-8"))
return dumps(compute_node)
security.declareProtected(Permissions.AccessContentsInformation,
'requestComputer')
def requestComputer(self, computer_title):
def requestComputer(self, computer_title, project_reference):
"""
Request Compute Node
"""
return self._requestComputeNode(computer_title)
return self._requestComputeNode(computer_title, project_reference)
security.declareProtected(Permissions.AccessContentsInformation,
'buildingSoftwareRelease')
......@@ -615,7 +625,7 @@ class SlapTool(BaseTool):
def requestComputerPartition(self, computer_id=None,
computer_partition_id=None, software_release=None, software_type=None,
partition_reference=None, partition_parameter_xml=None,
filter_xml=None, state=None, shared_xml=_MARKER):
filter_xml=None, state=None, shared_xml=_MARKER, project_reference=None):
"""
Asynchronously requests creation of compute partition for assigned
parameters
......@@ -629,7 +639,8 @@ class SlapTool(BaseTool):
"""
return self._requestComputePartition(computer_id, computer_partition_id,
software_release, software_type, partition_reference,
shared_xml, partition_parameter_xml, filter_xml, state)
shared_xml, partition_parameter_xml, filter_xml, state,
project_reference)
security.declareProtected(Permissions.AccessContentsInformation,
'useComputer')
......@@ -926,7 +937,8 @@ class SlapTool(BaseTool):
@convertToREST
def _requestComputePartition(self, compute_node_id, compute_partition_id,
software_release, software_type, partition_reference,
shared_xml, partition_parameter_xml, filter_xml, state):
shared_xml, partition_parameter_xml, filter_xml, state,
project_reference):
"""
Asynchronously requests creation of compute partition for assigned
parameters
......@@ -964,7 +976,8 @@ class SlapTool(BaseTool):
instance_xml=castToStr(partition_parameter_kw),
shared=shared,
sla_xml=castToStr(filter_kw),
state=state)
state=state,
project_reference=project_reference)
portal = self.getPortalObject()
if compute_node_id and compute_partition_id:
......@@ -978,8 +991,48 @@ class SlapTool(BaseTool):
else:
# requested as root, so done by human
requester = portal.portal_membership.getAuthenticatedMember().getUserValue()
if project_reference is None:
# Compatibility with the slapos console client
# which does not send any project_reference parameter
# and always connect to a uniq url
# Try to guess the project reference automatically
project_list = portal.portal_catalog(portal_type='Project', limit=2)
if len(project_list) == 1:
# If the user only has access to one project
# we can easily suppose the request must be allocated here
kw['project_reference'] = project_list[0].getReference()
else:
release_variation_list = portal.portal_catalog(
portal_type='Software Product Release Variation',
url_string=software_release,
limit=2
)
if len(release_variation_list) == 1:
# If the user only has access to matching release variation
# we can easily suppose the request must be allocated on the same project
kw['project_reference'] = release_variation_list[0].getParentValue().getFollowUpReference()
# Finally, try to use the SLA parameter to guess where it could be
elif 'project_guid' in filter_kw:
kw['project_reference'] = filter_kw['project_guid']
elif 'computer_guid' in filter_kw:
computer_list = portal.portal_catalog(
portal_type=['Compute Node', 'Remote Node', 'Instance Node'],
limit=2
)
if len(computer_list == 1):
kw['project_reference'] = computer_list[0].getFollowUpReference()
elif 'network_guid' in filter_kw:
network_list = portal.portal_catalog(
portal_type='Computer Network',
limit=2
)
if len(network_list == 1):
kw['project_reference'] = network_list[0].getFollowUpReference()
key = '_'.join([requester.getRelativeUrl(), partition_reference])
last_data = requester.getLastData(key)
requested_software_instance = None
value = dict(
......@@ -989,7 +1042,7 @@ class SlapTool(BaseTool):
if last_data is not None and isinstance(last_data, type(value)):
requested_software_instance = self.restrictedTraverse(
last_data.get('request_instance'), None)
if last_data is None or not isinstance(last_data, type(value)) or \
last_data.get('hash') != value['hash'] or \
requested_software_instance is None:
......
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