Commit 315adc1c authored by Cédric Le Ninivin's avatar Cédric Le Ninivin

slapos_jio_api_style: First version of update Compute Node to replace format

parent 3c389f8c
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_slapos_json_put</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_slapos_json_put</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>slapos_jio_api_put_compute_node</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>View</string>
</tuple>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Action Information</string> </value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>1.5</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Update Compute Node</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/ComputeNode_updateFromJSON</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="JSON Form" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>after_method_id</string> </key>
<value> <string>ComputeNode_updateFromAPIDict</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/json</string> </value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>ComputeNode_updateFromJSON</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ComputeNode_updateFromJSON</string> </value>
</item>
<item>
<key> <string>output_schema</string> </key>
<value> <string>{\n
"$schema": "http://json-schema.org/draft-07/schema#",\n
"title": "Software Installation Updated",\n
"description": "Response when the software installation is updated",\n
"type": "object",\n
"properties": {\n
"software_release_uri": {\n
"title": "Software Release URI",\n
"type": "string",\n
"format": "uri-reference"\n
},\n
"compute_node_id": {\n
"title": "Compute Node ID",\n
"type": "string",\n
"description": "The Id of the compute node, example: COMP-1234"\n
},\n
"portal_type": {\n
"title": "Portal Type",\n
"const": "Software Installation",\n
"type": "string"\n
},\n
"date": {\n
"title": "Date",\n
"description": "Date and Time of the operation",\n
"type": "string",\n
"format": "date-time"\n
},\n
"success": {\n
"title": "Success Message",\n
"type": "string",\n
"description": "Success Message"\n
},\n
}\n
}\n
</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>JSON Form</string> </value>
</item>
<item>
<key> <string>text_content</string> </key>
<value> <string>{\n
"$schema": "http://json-schema.org/draft-07/schema#",\n
"title": "Update Compute Node",\n
"description": "Update Compute Node Information. Send the list of partition and their ip addresses.",\n
"type": "object",\n
"properties": {\n
"compute_partition_list": {\n
"title": "Compute Partition List",\n
"type": "array",\n
"descritpion": "List Compute Node Partitions hosted on the computer",\n
"items": {\n
"type": "object",\n
"title": "Compute Node Partition",\n
"description": "Compute Node Partitions host Software Instances",\n
"properties": {\n
"partition_id": {\n
"title": "Partition ID",\n
"descritpion": "Unique ID of the Compute Node Partition",\n
"type": "string"\n
},\n
"ip_list": {\n
"title": "IP List",\n
"type": "array",\n
"descritpion": "List of IPs usable by the Software Instance on the partition. Used to configure firewall when necessary and allow only related instances to access it.",\n
"items": {\n
"type": "object",\n
"title": "Internet Protocol Address",\n
"description": "All element to describe the interface",\n
"properties": {\n
"ip-address": {\n
"title": "IP Address",\n
"type": "string"\n
},\n
"network-interface": {\n
"title": "Network Interface",\n
"type": "string"\n
},\n
"gateway-ip-address": {\n
"title": "Gateway Ip Address",\n
"type": "string"\n
},\n
"netmask": {\n
"title": "Netmask",\n
"type": "string"\n
},\n
"network-address": {\n
"title": "Network Address",\n
"type": "string"\n
}\n
},\n
"required": ["ip-address"]\n
}\n
}\n
},\n
"required": ["partition_id"]\n
}\n
},\n
"compute_node_id": {\n
"title": "Compute Node ID",\n
"type": "string",\n
"description": "Unique Id of the object. It is not editable."\n
},\n
"portal_type": {\n
"title": "Portal Type",\n
"const": "Compute Node",\n
"type": "string"\n
}\n
},\n
"required": ["portal_type", "compute_node_id"]\n
}\n
</string> </value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>01</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
def compareAndUpdateAddressList(partition, partition_ip_list):
to_delete_ip_id_list = []
to_add_ip_dict_list = partition_ip_list[:]
existing_address_list = partition.contentValues(portal_type='Internet Protocol Address')
existing_address_list.sort(key=lambda x: {0: 1, 1: 2}[int(x.id == 'default_network_interface')])
for internet_protocol_address in existing_address_list:
current_dict = {
"ip-address": internet_protocol_address.getIpAddress(),
"network-interface": internet_protocol_address.getNetworkInterface('').decode("UTF-8"),
}
if internet_protocol_address.getGatewayIpAddress(''):
current_dict["gateway-ip-address"] = internet_protocol_address.getGatewayIpAddress('').decode("UTF-8")
if internet_protocol_address.getNetmask(''):
current_dict["netmask"] = internet_protocol_address.getNetmask('').decode("UTF-8")
if internet_protocol_address.getNetworkAddress(''):
current_dict["network-address"] = internet_protocol_address.getNetworkAddress('').decode("UTF-8")
if current_dict in to_add_ip_dict_list:
to_add_ip_dict_list.remove(current_dict)
else:
to_delete_ip_id_list.append(internet_protocol_address.getId())
for address in to_add_ip_dict_list:
if to_delete_ip_id_list:
address_document = partition.restrictedTraverse(
to_delete_ip_id_list.pop()
)
else:
kw = {'portal_type': 'Internet Protocol Address'}
if not len(partition.objectIds(portal_type='Internet Protocol Address')):
kw.update(id='default_network_address')
address_document = partition.newContent(**kw)
edit_kw = {
"ip_address": address['ip-address'],
"network_interface": address.get("network-interface"),
"netmask": address.get('netmask'),
}
if "network-address" in address:
edit_kw["network_address"] = address["network-address"]
if "gateway-ip-address" in address:
edit_kw["gateway_ip_address"] = address["gateway-ip-address"]
address_document.edit(**edit_kw)
if to_delete_ip_id_list:
partition.deleteContent(to_delete_ip_id_list)
# Getting existing partitions
existing_partition_dict = {}
for c in context.contentValues(portal_type="Compute Partition"):
existing_partition_dict[c.getReference()] = c
# update compute_node data
edit_kw = {}
quantity = len(data_dict['compute_partition_list'])
if context.getQuantity() != quantity:
edit_kw['quantity'] = quantity
if edit_kw:
context.edit(**edit_kw)
expected_partition_dict = {}
for send_partition in data_dict['compute_partition_list']:
partition = existing_partition_dict.get(send_partition['partition_id'], None)
expected_partition_dict[send_partition['partition_id']] = True
if partition is None:
partition = context.newContent(portal_type='Compute Partition')
partition.validate()
partition.markFree()
elif partition.getSlapState() == 'inactive':
# Reactivate partition
partition.markFree(comment="Reactivated by slapformat")
if partition.getValidationState() == "invalidated":
partition.validate(comment="Reactivated by slapformat")
if partition.getReference() != send_partition['partition_id']:
partition.edit(reference=send_partition['partition_id'])
compareAndUpdateAddressList(partition, send_partition.get("ip_list", []))
# Desactivate all other partitions
for key, value in existing_partition_dict.items():
if key not in expected_partition_dict:
if value.getSlapState() == "free":
value.markInactive(comment="Desactivated by slapformat")
if value.getValidationState() == "validated":
value.invalidate(comment="Desactivated by slapformat")
import json
return json.dumps({
"$schema": json_form.absolute_url().strip() + "/getOutputJSONSchema",
"compute_node_id": context.getReference(),
"date": str(DateTime()),
"portal_type": "Compute Node",
"success": "Done"
}, indent=2)
<?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>data_dict, json_form</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ComputeNode_updateFromAPIDict</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
Compute Node | slapos_jio_api_get_compute_node Compute Node | slapos_jio_api_get_compute_node
Compute Node | slapos_jio_api_put_compute_node
Slave Instance | slapos_jio_api_get_software_instance Slave Instance | slapos_jio_api_get_software_instance
Software Installation | slapos_jio_api_get_software_installation Software Installation | slapos_jio_api_get_software_installation
Software Installation | slapos_jio_api_put_software_installation Software Installation | slapos_jio_api_put_software_installation
......
portal_callables/ComputeNode_getFromJSON portal_callables/ComputeNode_getFromJSON
portal_callables/ComputeNode_updateFromJSON
portal_callables/SoftwareInstallation_getFromJSON portal_callables/SoftwareInstallation_getFromJSON
portal_callables/SoftwareInstallation_updateFromJSON portal_callables/SoftwareInstallation_updateFromJSON
portal_callables/SoftwareInstance_getFromJSON portal_callables/SoftwareInstance_getFromJSON
......
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