Commit abebfca0 authored by Romain Courteaud's avatar Romain Courteaud

slapos_json_rpc_api: request

parent 2a8c31c4
......@@ -28,6 +28,36 @@
<key> <string>id</string> </key>
<value> <string>jIOWebSection_requestSoftwareInstanceFromJSON</string> </value>
</item>
<item>
<key> <string>output_schema</string> </key>
<value> <string>{\n
"$schema": "http://json-schema.org/draft-07/schema#",\n
"title": "Software Instance Requested",\n
"description": "Response when the software instance is requested",\n
"type": "object",\n
"additionalProperties": false,\n
"properties": {\n
"message": {\n
"title": "Message",\n
"type": "string"\n
},\n
"name": {\n
"title": "Name",\n
"type": "string"\n
},\n
"status": {\n
"title": "Status",\n
"type": "integer"\n
}\n
},\n
"required": [\n
"message",\n
"name",\n
"status"\n
]\n
}\n
</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>JSON Form</string> </value>
......@@ -42,6 +72,10 @@
"type": "object",\n
"additionalProperties": false,\n
"properties": {\n
"project_reference": {\n
"title": "Project Reference",\n
"type": "string"\n
},\n
"title": {\n
"title": "Title",\n
"type": "string",\n
......@@ -124,7 +158,7 @@
"description": "Id Of the Requesting Compute Partition, used by Slap Client when an instance is requesting an instance"\n
}\n
},\n
"required": ["title", "software_release_uri", "portal_type"]\n
"required": ["title", "software_release_uri", "software_type", "portal_type"]\n
}\n
</string> </value>
</item>
......
import json
import urllib
compute_node_id = data_dict.get("compute_node_id", None)
compute_partition_id = data_dict.get("compute_partition_id", None)
class SoftwareInstanceNotReady(Exception):
pass
castToStr = context.Base_castDictToXMLString
def logError(e, error_name="", error_code=400, detail_list=None):
return portal.ERP5Site_logApiErrorAndReturn(
error_code=error_code,
error_message=e,
error_name=error_name,
detail_list=detail_list,
)
portal = context.getPortalObject()
# Loads partition parameter
partition_parameter = data_dict.get("parameters", None)
if partition_parameter:
try:
partition_parameter = json.loads(partition_parameter)
except ValueError, e:
return logError(
"Cannot Decode JSON Parameter. Error: %s" % e,
error_name="CANNOT-DECODE-COMPUTER-PARTITION-JSON-PARAMETER",
)
if not isinstance(partition_parameter, dict):
return logError(
"Parameters should be a key value object.",
error_name="INCORRECT-COMPUTER-PARTITION-JSON-PARAMETER",
)
else:
partition_parameter = {}
try:
# filter dict
filter_kw = data_dict.get("sla_parameters", {})
partition_parameter = data_dict.get("parameters", {})
# filter dict
filter_kw = data_dict.get("sla_parameters", {})
partition_reference = data_dict.get("title")
kw = dict(software_release=data_dict.get("software_release_uri"),
software_type=data_dict.get("software_type"),
software_title=partition_reference,
instance_xml=castToStr(partition_parameter),
shared=data_dict.get("shared", False),
sla_xml=castToStr(filter_kw),
state=data_dict.get("state", "started"),
project_reference=data_dict.get("project_reference", None))
if compute_node_id and compute_partition_id:
compute_partition = portal.portal_catalog.getComputePartitionObject(
compute_node_id,
compute_partition_id,
)
requester = compute_partition.getSoftwareInstance()
instance_tree = requester.getSpecialiseValue()
partition_reference = data_dict.get("title")
kw = dict(software_release=urllib.unquote(data_dict.get("software_release_uri")),
software_type=data_dict.get("software_type", "RootSoftwareInstance"),
software_title=partition_reference,
instance_xml=castToStr(partition_parameter),
shared=data_dict.get("shared", False),
sla_xml=castToStr(filter_kw),
state=data_dict.get("state", "started"),
project_reference=data_dict.get("project_reference", None))
if instance_tree is not None:
kw["project_reference"] = instance_tree.getFollowUpReference()
if compute_node_id and compute_partition_id:
compute_partition = portal.portal_catalog.getComputePartitionObject(
compute_node_id,
compute_partition_id,
)
requester = compute_partition.getSoftwareInstance()
instance_tree = requester.getSpecialiseValue()
if instance_tree.getSlapState() == "stop_requested":
kw['state'] = 'stopped'
if instance_tree is not None:
kw["project_reference"] = instance_tree.getFollowUpReference()
key = '_'.join([instance_tree.getRelativeUrl(), partition_reference])
else:
# requested as root, so done by human
requester = portal.portal_membership.getAuthenticatedMember().getUserValue()
key = '_'.join([requester.getRelativeUrl(), partition_reference])
last_data = requester.getLastData(key)
requested_software_instance = None
value = dict(
hash='_'.join([requester.getRelativeUrl(), str(kw)]),
)
if instance_tree.getSlapState() == "stop_requested":
kw['state'] = 'stopped'
if last_data is not None and isinstance(last_data, type(value)):
requested_software_instance = portal.restrictedTraverse(
last_data.get('request_instance'), None)
key = '_'.join([instance_tree.getRelativeUrl(), partition_reference])
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:
if compute_node_id and compute_partition_id:
requester.requestInstance(**kw)
else:
# requested as root, so done by human
requester = portal.portal_membership.getAuthenticatedMember().getUserValue()
key = '_'.join([requester.getRelativeUrl(), partition_reference])
last_data = requester.getLastData(key)
requested_software_instance = None
value = dict(
hash='_'.join([requester.getRelativeUrl(), str(kw)]),
)
if last_data is not None and isinstance(last_data, type(value)):
requested_software_instance = portal.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:
if compute_node_id and compute_partition_id:
requester.requestInstance(**kw)
else:
# requester is a person so we use another method
requester.requestSoftwareInstance(**kw)
requested_software_instance = context.REQUEST.get('request_instance')
if requested_software_instance is not None:
value['request_instance'] = requested_software_instance\
.getRelativeUrl()
requester.setLastData(value, key=key)
# requester is a person so we use another method
requester.requestSoftwareInstance(**kw)
requested_software_instance = context.REQUEST.get('request_instance')
if requested_software_instance is not None:
return requested_software_instance.asJSONText()
raise SoftwareInstanceNotReady
except SoftwareInstanceNotReady:
return logError(
"Software Instance Not Ready",
error_name="SoftwareInstanceNotReady",
error_code=102
)
value['request_instance'] = requested_software_instance\
.getRelativeUrl()
requester.setLastData(value, key=key)
if requested_software_instance is not None:
return requested_software_instance.asJSONText()
return {
'message': 'Software Instance Not Ready',
'status': 102,
'name': 'SoftwareInstanceNotReady'
}
......@@ -1437,89 +1437,73 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSJsonRpcMixin):
self.assertEqual(instance.getTitle(), new_name)
def test_PersonAccess_34_request_withSlave(self):
self.called_instance_request = ""
def calledRequestInstance(*args, **kw):
self.called_instance_request = kw
project_reference = self.project.getReference()
try:
requestSoftwareInstance = self.person.__class__.requestSoftwareInstance
project_reference = self.project.getReference()
self.person.__class__.requestSoftwareInstance = calledRequestInstance
self.login(self.person_user_id)
response = self.callJsonRpcWebService("slapos.post.slapos_jio_api_request_software_instance", {
response = self.callJsonRpcWebService(
"slapos.post.slapos_jio_api_request_software_instance",
{
"portal_type": "Software Instance",
"project_reference": project_reference,
"software_release_uri": "req_release",
"software_type": "req_type",
"title": "req_reference",
"shared": True,
})
response_dict = json.loads(response.getBody())
if 400 != response.getStatus():
raise ValueError("Unexpected Result %s" % response_dict)
self.assertEqual('application/json',
response.headers.get('content-type'))
self.assertEqual(self.called_instance_request, {
'instance_xml': "<?xml version='1.0' encoding='utf-8'?>\n<instance/>\n",
'project_reference': project_reference,
'software_title': 'req_reference',
'software_release': 'req_release',
'state': 'started',
'sla_xml': "<?xml version='1.0' encoding='utf-8'?>\n<instance/>\n",
'software_type': 'req_type',
'shared': True
})
self.assertTrue(response_dict.pop("$schema").endswith("error-response-schema.json"))
response_dict.pop("debug_id")
self.assertEqual(response_dict, {
'message': 'Software Instance Not Ready',
'name': 'SoftwareInstanceNotReady',
'status': 102
})
finally:
self.person.__class__.requestSoftwareInstance = requestSoftwareInstance
},
self.person_user_id
)
self.assertEqual('application/json', response.headers.get('content-type'))
self.assertEqual({
'message': 'Software Instance Not Ready',
'name': 'SoftwareInstanceNotReady',
'status': 102
}, byteify(json.loads(response.getBody())))
self.assertEqual(response.getStatus(), 200)
self.tic()
requested_instance_tree = self.portal.portal_catalog.getResultValue(
portal_type='Instance Tree',
title="req_reference"
)
self.assertEqual(requested_instance_tree.getDestinationSectionValue().getUserId(), self.person_user_id)
self.assertEqual(requested_instance_tree.getFollowUpReference(), project_reference)
self.assertEqual(requested_instance_tree.getTitle(), "req_reference")
self.assertEqual(requested_instance_tree.getUrlString(), "req_release")
self.assertEqual(requested_instance_tree.getSourceReference(), "req_type")
self.assertTrue(requested_instance_tree.isRootSlave())
def test_PersonAccess_35_request(self):
self.called_instance_request = ""
def calledRequestInstance(*args, **kw):
self.called_instance_request = kw
project_reference = self.project.getReference()
try:
requestSoftwareInstance = self.person.__class__.requestSoftwareInstance
project_reference = self.project.getReference()
self.person.__class__.requestSoftwareInstance = calledRequestInstance
self.login(self.person_user_id)
response = self.callJsonRpcWebService("slapos.post.slapos_jio_api_request_software_instance", {
response = self.callJsonRpcWebService(
"slapos.post.slapos_jio_api_request_software_instance",
{
"portal_type": "Software Instance",
"project_reference": project_reference,
"software_release_uri": "req_release",
"software_type": "req_type",
"title": "req_reference",
"project_reference": project_reference
})
response_dict = json.loads(response.getBody())
if 400 != response.getStatus():
raise ValueError("Unexpected Result %s" % response_dict)
self.assertEqual('application/json',
response.headers.get('content-type'))
self.assertEqual(self.called_instance_request, {
'instance_xml': "<?xml version='1.0' encoding='utf-8'?>\n<instance/>\n",
'project_reference': project_reference,
'software_title': 'req_reference',
'software_release': 'req_release',
'state': 'started',
'sla_xml': "<?xml version='1.0' encoding='utf-8'?>\n<instance/>\n",
'software_type': 'req_type',
'shared': False
})
self.assertTrue(response_dict.pop("$schema").endswith("error-response-schema.json"))
response_dict.pop("debug_id")
self.assertEqual(response_dict, {
'message': 'Software Instance Not Ready',
'name': 'SoftwareInstanceNotReady',
'status': 102
})
finally:
self.person.__class__.requestSoftwareInstance = requestSoftwareInstance
"title": "req_reference"
},
self.person_user_id
)
self.assertEqual('application/json', response.headers.get('content-type'))
self.assertEqual({
'message': 'Software Instance Not Ready',
'name': 'SoftwareInstanceNotReady',
'status': 102
}, byteify(json.loads(response.getBody())))
self.assertEqual(response.getStatus(), 200)
self.tic()
requested_instance_tree = self.portal.portal_catalog.getResultValue(
portal_type='Instance Tree',
title="req_reference"
)
self.assertEqual(requested_instance_tree.getDestinationSectionValue().getUserId(), self.person_user_id)
self.assertEqual(requested_instance_tree.getFollowUpReference(), project_reference)
self.assertEqual(requested_instance_tree.getTitle(), "req_reference")
self.assertEqual(requested_instance_tree.getUrlString(), "req_release")
self.assertEqual(requested_instance_tree.getSourceReference(), "req_type")
self.assertFalse(requested_instance_tree.isRootSlave())
def test_PersonAccess_36_request_allocated_instance(self):
self.tic()
......
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