Commit 43bc72f5 authored by Cédric Le Ninivin's avatar Cédric Le Ninivin Committed by Romain Courteaud

slapos_cloud: BIG squash

slapos_cloud: Move Software instance from Base Type to JSON Type

slapos_cloud: Move Software Installation from Base Type to JSON Type

slapos_cloud: Add full_text test dependency

slapos_cloud: Add test dependency to slapos_configurator

slapos_cloud: use getObject to unwrap compute node

slapos_cloud: Do not automatically approve computer registration

slapos_cloud: implement asJSONText for software instance

slapos_cloud: Add JSON Schema to Software Installation

slapos_cloud: add preferred_jio_api_url to SlapOS Preferences

slapos_cloud: make a version of _getSoftwareInstallationFromUrl public that doesn't raise NOTFound

slapos_cloud: make getSoftwareInstallationFromUrl public and remove except NotFound

* NotFound Errors are now handled by API

slapos_cloud: Compute Partition Mixin getSoftwareInstance is public

slapos_cloud: Add asJSONText on Software Installation

slapos_cloud: Improve Software Instance as JSON Text

slapos_cloud: Add getSoftwareInstanceObject to Slapos Catalog Tool Mixin

slapos_cloud: Add retention delay in sla in instance structure

slapos_cloud: Software Instance data schema include retention delay

slapos_cloud: wip Software Instance add access status and processing timestamp

slapos_cloud: Software instance dedicated update sucessor list uses list and is accessible

slapos_cloud: Software Instance asJSON include SSL key and certificate

slapos_cloud: Software Instance Schema put X509 in a sub-object

slapos_cloud: Software Instance Schema fix typo on root_instance_title

slapos_cloud: Software Instance clean asJSON Text add full_ip_list and remove relative_url

slapos_cloud: SoftwareInstance As JSON Text always use Software Instance Schema

slapos_cloud: Remove certificates from Software Instance JSON Object

slapos_cloud: Catch not found computer when getting compute partition

slapos_cloud: Software Instance schema, give more information in connection parameters

slapos_cloud: Add getSlapTimestamp method

The Slap Timestamp represent the last date a relevant modification has
been done to the object.

slapos_cloud: Software Instance add handle for slap_state draft

slapos_cloud: Add getJSONSchemaUrl method

This is an attempt to provide stability to the Schema URL and by extension to asJSONText
With absolute url usage used to calculate the Schema URL the url change according to the url being used

slapos_cloud: SlapTimestamp for Software Instance takes into account hosted shared instance

slapos_cloud: Add jIO API Revision to Shared and Software Instance

slapos_cloud: Fix add missing JIOAPIRevisionMixin on Instances portal type

slapos_cloud: add jio api revision on Software Installation and Compute Node

slapos_cloud: JIO API Revision depend on web section

slapos_cloud: Fixes to Software Instance Document and ip list is empty for shared instances

* getSlapTimeStamp use unrestricted method
* use sort by jip_api_revision and not slap_date when sorting shared instances to calculate timestamp
* ip list is empty for shared instances

slapos_cloud: Add missing JIOAPIRevisionMixin to necessary document

slapos_cloud: Add missing dependency to erp5_api_style

slapos_cloud: remove unecessary elements from Software Installation JSON

slapos_cloud: add missing portal type in Software Installation asJSONText

slapos_cloud: Add useRevision to SoftwareInstance

slapos_cloud: Only add api_revision to JSON Data when defined

slapos_cloud: something on Software Installation

slapos_cloud: getComputePartitionUid
parent ab24dacc
##############################################################################
#
# Copyright (c) 2008 Nexedi SA and Contributors. All Rights Reserved.
# Yusei TAHARA <yusei@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from erp5.component.document.Item import Item
from erp5.component.document.JSONType import JSONType
import json
class SoftwareInstallation(Item, JSONType):
"""
This class represents a computer like personal computer, printer, router.
"""
portal_type = 'Software Installation'
add_permission = Permissions.AddPortalContent
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative properties
property_sheets = ( PropertySheet.TextDocument
, PropertySheet.JSONTypeConstraint
)
def useRevision(self):
return getattr(self, "use_jio_api_revision", False)
security.declareProtected(Permissions.AccessContentsInformation,
'asJSONText')
def asJSONText(self):
requested_state = self.getSlapState()
if requested_state == "stop_requested":
state = 'stopped'
elif requested_state in ("start_requested", "started"):
state = 'available'
elif requested_state == "destroy_requested":
state = 'destroyed'
else:
raise ValueError("Unknown slap state : %s" % requested_state)
# software instance has to define an xml parameter
status_dict = self.getAccessStatus()
result = {
"$schema": self.getJSONSchemaUrl(),
"software_release_uri": self.getUrlString(),
"compute_node_id": self.getAggregateReference(),
"state": state,
"reported_state": status_dict.get("state"),
"status_message": status_dict.get("text"),
"portal_type": "Software Installation",
}
if self.useRevision():
web_section = self.getWebSectionValue()
web_section = web_section.getRelativeUrl() if web_section else self.REQUEST.get("web_section_relative_url", None)
if web_section:
revision = self.getJIOAPIRevision(web_section)
if revision:
result["api_revision"] = revision
return json.dumps(result, indent=2)
def getSlapTimestamp(self):
return int(self.getModificationDate())
security.declareProtected(Permissions.AccessContentsInformation,
'getJSONSchemaUrl')
def getJSONSchemaUrl(self):
"""
This is an attempt to provide stability to the Schema URL and by extension to asJSONText
"""
portal = self.getPortalObject()
portal_type_path = portal.portal_types.restrictedTraverse(self.getPortalType())
base_url = portal.portal_preferences.getPreferredSlaposWebSiteUrl().strip("/")
return "/".join([base_url, portal_type_path.getRelativeUrl(), "getTextContent"])
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SoftwareInstallation</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.SoftwareInstallation</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<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>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -26,8 +26,11 @@ ...@@ -26,8 +26,11 @@
# #
############################################################################## ##############################################################################
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from App.Common import rfc1123_date
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from erp5.component.document.Item import Item from erp5.component.document.Item import Item
from erp5.component.document.JSONType import JSONType
import json
from lxml import etree from lxml import etree
import collections import collections
...@@ -37,12 +40,10 @@ from erp5.component.module.SlapOSCloud import _assertACI ...@@ -37,12 +40,10 @@ from erp5.component.module.SlapOSCloud import _assertACI
from zLOG import LOG, INFO from zLOG import LOG, INFO
try: try:
from slapos.util import xml2dict, loads from slapos.util import xml2dict
except ImportError: except ImportError:
def xml2dict(dictionary): def xml2dict(dictionary):
raise ImportError raise ImportError
def loads(*args):
raise ImportError
class DisconnectedSoftwareTree(Exception): class DisconnectedSoftwareTree(Exception):
pass pass
...@@ -50,7 +51,7 @@ class DisconnectedSoftwareTree(Exception): ...@@ -50,7 +51,7 @@ class DisconnectedSoftwareTree(Exception):
class CyclicSoftwareTree(Exception): class CyclicSoftwareTree(Exception):
pass pass
class SoftwareInstance(Item): class SoftwareInstance(Item, JSONType):
""" """
""" """
...@@ -157,6 +158,8 @@ class SoftwareInstance(Item): ...@@ -157,6 +158,8 @@ class SoftwareInstance(Item):
state = 'started' state = 'started'
elif requested_state == "destroy_requested": elif requested_state == "destroy_requested":
state = 'destroyed' state = 'destroyed'
elif requested_state == "draft":
state = 'draft'
else: else:
raise ValueError("Unknown slap state : %s" % requested_state) raise ValueError("Unknown slap state : %s" % requested_state)
...@@ -177,38 +180,82 @@ class SoftwareInstance(Item): ...@@ -177,38 +180,82 @@ class SoftwareInstance(Item):
software_instance_dict['_instance_guid'] = instance_guid software_instance_dict['_instance_guid'] = instance_guid
return software_instance_dict return software_instance_dict
def _getModificationDateAsTimestamp(self, document): def getSlapTimestamp(self):
return int(float(document.getModificationDate()) * 1e6) return self._getSlapTimestamp()
def useRevision(self):
return getattr(self, "use_jio_api_revision", False)
@UnrestrictedMethod
def _getSlapTimestamp(self):
compute_partition = self.getAggregateValue(portal_type="Compute Partition")
if compute_partition is None:
return int(self.getModificationDate())
timestamp = int(compute_partition.getModificationDate())
newtimestamp = int(self.getBangTimestamp(int(self.getModificationDate())))
if (newtimestamp > timestamp):
timestamp = newtimestamp
# Check if any of the Shared instances hosted in the software instance have been reprocessed
# XXX In the current what shared instances are processed, they cannot be reprocessed if the
# host instance is not processed
if (self.getPortalType() == "Software Instance"):
shared_instance_sql_list = []
if self.useRevision():
shared_instance_sql_list = self.getPortalObject().portal_catalog.unrestrictedSearchResults(
default_aggregate_uid=compute_partition.getUid(),
portal_type='Slave Instance',
validation_state="validated",
sort_on=(("jio_api_revision.revision", "DESC"),),
select_list=('jio_api_revision.revision',),
limit=1,
**{"slapos_item.slap_state": "start_requested"}
)
else:
shared_instance_sql_list = self.getPortalObject().portal_catalog.unrestrictedSearchResults(
default_aggregate_uid=compute_partition.getUid(),
portal_type='Slave Instance',
validation_state="validated",
**{"slapos_item.slap_state": "start_requested"}
)
for shared_instance in shared_instance_sql_list:
shared_instance = _assertACI(shared_instance.getObject())
# XXX Use catalog to filter more efficiently
if shared_instance.getSlapState() == "start_requested":
newtimestamp = int(shared_instance.getBangTimestamp(int(shared_instance.getModificationDate())))
if (newtimestamp > timestamp):
timestamp = newtimestamp
return timestamp
@UnrestrictedMethod @UnrestrictedMethod
def _asParameterDict(self, shared_instance_sql_list=None): def _asParameterDict(self, shared_instance_sql_list=None):
portal = self.getPortalObject() portal = self.getPortalObject()
compute_partition = self.getAggregateValue(portal_type="Compute Partition") compute_partition = self.getAggregateValue(portal_type="Compute Partition")
if compute_partition is None: if compute_partition is None:
raise ValueError("Instance isn't allocated to call _asParamterDict") raise ValueError("Instance isn't allocated to call _asParameterDict")
timestamp = self.getSlapTimestamp()
timestamp = max(
self._getModificationDateAsTimestamp(compute_partition),
int(self.getBangTimestamp(self._getModificationDateAsTimestamp(self))))
instance_tree = self.getSpecialiseValue() instance_tree = self.getSpecialiseValue()
ip_list = [] ip_list = []
full_ip_list = [] full_ip_list = []
for internet_protocol_address in compute_partition.contentValues(portal_type='Internet Protocol Address'): if (self.getPortalType() == "Software Instance"):
# XXX - There is new values, and we must keep compatibility for internet_protocol_address in compute_partition.contentValues(portal_type='Internet Protocol Address'):
address_tuple = ( # XXX - There is new values, and we must keep compatibility
internet_protocol_address.getNetworkInterface('').decode("UTF-8"), address_tuple = (
internet_protocol_address.getIpAddress().decode("UTF-8")) internet_protocol_address.getNetworkInterface('').decode("UTF-8"),
if internet_protocol_address.getGatewayIpAddress('') and \ internet_protocol_address.getIpAddress().decode("UTF-8"))
internet_protocol_address.getNetmask(''): if internet_protocol_address.getGatewayIpAddress('') and \
address_tuple = address_tuple + ( internet_protocol_address.getNetmask(''):
internet_protocol_address.getGatewayIpAddress().decode("UTF-8"), address_tuple = address_tuple + (
internet_protocol_address.getNetmask().decode("UTF-8"), internet_protocol_address.getGatewayIpAddress().decode("UTF-8"),
internet_protocol_address.getNetworkAddress('').decode("UTF-8")) internet_protocol_address.getNetmask().decode("UTF-8"),
full_ip_list.append(address_tuple) internet_protocol_address.getNetworkAddress('').decode("UTF-8"))
else: full_ip_list.append(address_tuple)
ip_list.append(address_tuple) else:
ip_list.append(address_tuple)
shared_instance_list = [] shared_instance_list = []
if (self.getPortalType() == "Software Instance"): if (self.getPortalType() == "Software Instance"):
...@@ -282,19 +329,21 @@ class SoftwareInstance(Item): ...@@ -282,19 +329,21 @@ class SoftwareInstance(Item):
return ip_address_list return ip_address_list
def _updateSucessorList(self, instance_reference_xml): def updateRequestedInstanceList(self, instance_reference_list):
return self._updateSucessorList(instance_reference_list)
def _updateSucessorList(self, instance_reference_list):
""" """
Update Software Instance successor list to match the given list. If one Update Software Instance successor list to match the given list. If one
instance was not requested by this compute partition, it should be removed instance was not requested by this compute partition, it should be removed
in the successor_list of this instance. in the successor_list of this instance.
Once the link is removed, this instance will be trashed by Garbage Collect! Once the link is removed, this instance will be trashed by Garbage Collect!
instance_reference_xml contain list of title of sub-instances requested by instance_reference_list contain list of title of sub-instances requested by
this instance. this instance.
""" """
cache_reference = '%s-PREDLIST' % self.getReference() cache_reference = '%s-PREDLIST' % self.getReference()
if not self.isLastData(cache_reference, instance_reference_xml): if not self.isLastData(cache_reference, str(instance_reference_list)):
instance_reference_list = loads(instance_reference_xml)
current_successor_list = self.getSuccessorValueList( current_successor_list = self.getSuccessorValueList(
portal_type=['Software Instance', 'Slave Instance']) portal_type=['Software Instance', 'Slave Instance'])
current_successor_title_list = [i.getTitle() for i in current_successor_list] current_successor_title_list = [i.getTitle() for i in current_successor_list]
...@@ -308,4 +357,86 @@ class SoftwareInstance(Item): ...@@ -308,4 +357,86 @@ class SoftwareInstance(Item):
self.getReference(), successor_list), error=False) self.getReference(), successor_list), error=False)
self.edit(successor_list=successor_list, self.edit(successor_list=successor_list,
comment='successor_list edited to unlink non commited instances') comment='successor_list edited to unlink non commited instances')
self.setLastData(instance_reference_xml, key=cache_reference) self.setLastData(str(instance_reference_list), key=cache_reference)
\ No newline at end of file
security.declareProtected(Permissions.AccessContentsInformation,
'getJSONSchemaUrl')
def getJSONSchemaUrl(self):
"""
This is an attempt to provide stability to the Schema URL and by extension to asJSONText
"""
portal = self.getPortalObject()
portal_type_path = portal.portal_types.restrictedTraverse("Software Instance")
base_url = portal.portal_preferences.getPreferredSlaposWebSiteUrl().strip("/")
return "/".join([base_url, portal_type_path.getRelativeUrl(), "getTextContent"])
security.declareProtected(Permissions.AccessContentsInformation,
'asJSONText')
def asJSONText(self):
try:
parameter_dict = self._asParameterDict()
except ValueError:
parameter_dict = {}
requested_state = self.getSlapState()
if requested_state == "stop_requested":
state = 'stopped'
elif requested_state == "start_requested":
state = 'started'
elif requested_state == "destroy_requested":
state = 'destroyed'
elif requested_state == "draft":
state = 'draft'
else:
raise ValueError("Unknown slap state : %s" % requested_state)
# software instance has to define an xml parameter
result = {
"$schema": self.getJSONSchemaUrl(),
"title": self.getTitle().decode("UTF-8"),
"reference": self.getReference().decode("UTF-8"),
"software_release_uri": self.getUrlString(),
"software_type": self.getSourceReference().decode("UTF-8"),
"state": state,
"connection_parameters": self.getConnectionXmlAsDict(),
"parameters": self.getInstanceXmlAsDict(),
"shared": False,
"root_instance_title": parameter_dict.get("root_instance_title"),
"ip_list": parameter_dict.get("ip_list"),
"full_ip_list": parameter_dict.get("full_ip_list"),
"sla_parameters": self.getSlaXmlAsDict(),
"compute_node_id": parameter_dict.get("slap_computer_id"),
"compute_partition_id": parameter_dict.get("slap_computer_partition_id"),
"processing_timestamp": self.getSlapTimestamp(),
"access_status_message": self.getTextAccessStatus(),
"portal_type": self.getPortalType(),
}
if self.useRevision():
web_section = self.getWebSectionValue()
web_section = web_section.getRelativeUrl() if web_section else self.REQUEST.get("web_section_relative_url", None)
if web_section:
revision = self.getJIOAPIRevision(web_section)
if revision:
result["api_revision"] = revision
self.REQUEST.response.setHeader('Cache-Control',
'private, max-age=0, must-revalidate')
self.REQUEST.response.setHeader('Vary',
'REMOTE_USER')
self.REQUEST.response.setHeader('Last-Modified',
rfc1123_date(self.getModificationDate()))
return json.dumps(result, indent=2)
security.declareProtected(Permissions.ModifyPortalContent, 'fromJSONText')
def fromJSONText(self, json_content):
return self.setJsonContent(json_content)
def getComputePartitionUid(self):
"""
Get Compute Partition Uid.
Used by software instances as Compute Partition deosn't have access to Compute Node Module.
"""
return self._getComputePartitionUid()
@UnrestrictedMethod
def _getComputePartitionUid(self):
return self.getAggregateUid()
...@@ -30,7 +30,6 @@ from OFS.Traversable import NotFound ...@@ -30,7 +30,6 @@ from OFS.Traversable import NotFound
from Products.ERP5Type.Cache import CachingMethod from Products.ERP5Type.Cache import CachingMethod
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
class SlapOSCatalogToolCacheMixin(object): class SlapOSCatalogToolCacheMixin(object):
""" Quering Caching Extension for Catalog for handle specific queries """ Quering Caching Extension for Catalog for handle specific queries
relying on caching. relying on caching.
...@@ -72,9 +71,13 @@ class SlapOSCatalogToolCacheMixin(object): ...@@ -72,9 +71,13 @@ class SlapOSCatalogToolCacheMixin(object):
@UnrestrictedMethod @UnrestrictedMethod
def _getNonCachedComputeNodeUid(self, reference): def _getNonCachedComputeNodeUid(self, reference):
return self.unrestrictedSearchResults( compute_node_list = self.unrestrictedSearchResults(
portal_type=['Compute Node', 'Remote Node'], reference=reference, portal_type='Compute Node', reference=reference,
validation_state="validated")[0].UID validation_state="validated")
if len(compute_node_list) != 1:
raise NotFound, "No document found with parameters: %s" % reference
return compute_node_list[0].UID
def getComputePartitionObject(self, compute_node_reference, def getComputePartitionObject(self, compute_node_reference,
compute_partition_reference): compute_partition_reference):
...@@ -92,3 +95,28 @@ class SlapOSCatalogToolCacheMixin(object): ...@@ -92,3 +95,28 @@ class SlapOSCatalogToolCacheMixin(object):
(compute_node_reference, compute_partition_reference)) (compute_node_reference, compute_partition_reference))
else: else:
return _assertACI(compute_partition_list[0].getObject()) return _assertACI(compute_partition_list[0].getObject())
def _getNonCachedSoftwareInstance(self, reference, include_shared=False):
# No need to get all results if an error is raised when at least 2 objects
# are found
if not include_shared:
portal_type = "Software Instance"
else:
portal_type = ("Software Instance", "Slave Instance")
software_instance_list = self.unrestrictedSearchResults(limit=2,
portal_type=portal_type,
validation_state="validated",
reference=reference)
if len(software_instance_list) != 1:
raise NotFound, "No document found with parameters: %s" % reference
else:
return _assertACI(software_instance_list[0].getObject()).getRelativeUrl()
def getSoftwareInstanceObject(self, reference, include_shared=False):
"""
Get the validated compute_node with this reference.
"""
result = CachingMethod(self._getNonCachedSoftwareInstance,
id='_getSoftwareInstanceObject',
cache_factory='slap_cache_factory')(reference, include_shared=include_shared)
return self.getPortalObject().restrictedTraverse(result)
\ No newline at end of file
...@@ -6,6 +6,12 @@ ...@@ -6,6 +6,12 @@
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item> <item>
<key> <string>default_reference</string> </key> <key> <string>default_reference</string> </key>
<value> <string>SlapOSCatalogToolCacheMixin</string> </value> <value> <string>SlapOSCatalogToolCacheMixin</string> </value>
...@@ -55,13 +61,28 @@ ...@@ -55,13 +61,28 @@
<item> <item>
<key> <string>workflow_history</string> </key> <key> <string>workflow_history</string> </key>
<value> <value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent> <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
<record id="2" aka="AAAAAAAAAAI="> <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> <pickle>
<global name="PersistentMapping" module="Persistence.mapping"/> <global name="PersistentMapping" module="Persistence.mapping"/>
</pickle> </pickle>
...@@ -74,7 +95,7 @@ ...@@ -74,7 +95,7 @@
<item> <item>
<key> <string>component_validation_workflow</string> </key> <key> <string>component_validation_workflow</string> </key>
<value> <value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent> <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value> </value>
</item> </item>
</dictionary> </dictionary>
...@@ -83,7 +104,7 @@ ...@@ -83,7 +104,7 @@
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
<record id="3" aka="AAAAAAAAAAM="> <record id="4" aka="AAAAAAAAAAQ=">
<pickle> <pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/> <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle> </pickle>
......
...@@ -115,9 +115,7 @@ class SlapOSComputeNodeMixin(object): ...@@ -115,9 +115,7 @@ class SlapOSComputeNodeMixin(object):
dict ( dict (
time=time.time(), time=time.time(),
refresh_etag=refresh_etag, refresh_etag=refresh_etag,
data=computer_dict, data=computer_dict
# Store the XML while SlapTool Still used
data_xml=self.getPortalObject().portal_slap._getSlapComputeNodeXMLFromDict(computer_dict)
), ),
cache_duration=self.getPortalObject().portal_caches\ cache_duration=self.getPortalObject().portal_caches\
.getRamCacheRoot().get('compute_node_information_cache_factory'\ .getRamCacheRoot().get('compute_node_information_cache_factory'\
...@@ -316,7 +314,7 @@ class SlapOSComputeNodeMixin(object): ...@@ -316,7 +314,7 @@ class SlapOSComputeNodeMixin(object):
return partition_dict return partition_dict
def _getSoftwareInstallationFromUrl(self, url): def getSoftwareInstallationFromUrl(self, url):
software_installation_list = self.getPortalObject().portal_catalog.unrestrictedSearchResults( software_installation_list = self.getPortalObject().portal_catalog.unrestrictedSearchResults(
portal_type='Software Installation', portal_type='Software Installation',
default_aggregate_uid=self.getUid(), default_aggregate_uid=self.getUid(),
...@@ -335,4 +333,71 @@ class SlapOSComputeNodeMixin(object): ...@@ -335,4 +333,71 @@ class SlapOSComputeNodeMixin(object):
raise ValueError('Wrong list of software releases on %r: %s' % ( raise ValueError('Wrong list of software releases on %r: %s' % (
self.getReference(), ', '.join([q.getRelativeUrl() for q \ self.getReference(), ', '.join([q.getRelativeUrl() for q \
in software_installation_list]) in software_installation_list])
)) ))
\ No newline at end of file
def getComputePartitionNewsDict(self):
key = '%s_partition_news' % self.getReference()
cache_plugin = self._getCachePlugin()
refresh_etag = self._calculateRefreshEtag()
try:
entry = cache_plugin.get(key, DEFAULT_CACHE_SCOPE)
except KeyError:
entry = None
if entry is not None and isinstance(entry.getValue(), dict):
cached_dict = entry.getValue()
cached_etag = cached_dict.get('refresh_etag', None)
if (refresh_etag != cached_etag):
return self._getCachedComputePartitionNewsDict(key, refresh_etag)
else:
return cached_dict.get('data')
return self._getCachedComputePartitionNewsDict(key, refresh_etag)
def _getCachedComputePartitionNewsDict(self, key, refresh_etag):
unrestrictedSearchResults = self.getPortalObject().portal_catalog.unrestrictedSearchResults
compute_partition_uid_list = [x.uid for x in unrestrictedSearchResults(
parent_uid=self.getUid(),
validation_state="validated",
portal_type="Compute Partition")]
software_instance_list = unrestrictedSearchResults(
portal_type="Software Instance",
default_aggregate_uid=compute_partition_uid_list,
validation_state="validated",
group_by_list=['default_aggregate_uid'],
select_list=['default_aggregate_uid', 'default_aggregate_title']
)
compute_partition_dict = { }
for software_instance in software_instance_list:
compute_partition_dict[software_instance.default_aggregate_title] = software_instance.getAccessStatus()
try:
self._getCachePlugin().set(key, DEFAULT_CACHE_SCOPE,
dict (
time=time.time(),
refresh_etag=refresh_etag,
data=compute_partition_dict
),
cache_duration=self.getPortalObject().portal_caches\
.getRamCacheRoot().get('compute_node_information_cache_factory'\
).cache_duration
)
except (Unauthorized, IndexError):
# XXX: Unauthorized hack. Race condition of not ready setup delivery which provides
# security information shall not make this method fail, as it will be
# called later anyway
# Note: IndexError ignored, as it happend in case if full reindex is
# called on site
pass
return compute_partition_dict
def getJSONSchemaUrl(self):
"""
This is an attempt to provide stability to the Schema URL and by extension to asJSONText
"""
portal = self.getPortalObject()
portal_type_path = portal.portal_types.restrictedTraverse(self.getPortalType())
base_url = portal.portal_preferences.getPreferredSlaposWebSiteUrl().strip("/")
return "/".join([base_url, portal_type_path.getRelativeUrl(), "getTextContent"])
...@@ -45,7 +45,7 @@ except ImportError: ...@@ -45,7 +45,7 @@ except ImportError:
class SlapOSComputePartitionMixin(object): class SlapOSComputePartitionMixin(object):
def _getSoftwareInstance(self, slave_reference=None): def getSoftwareInstance(self, slave_reference=None):
if self.getSlapState() != 'busy': if self.getSlapState() != 'busy':
LOG('SlapOSComputePartitionMixin::_getSoftwareInstance', INFO, LOG('SlapOSComputePartitionMixin::_getSoftwareInstance', INFO,
'Compute partition %s shall be busy, is free' % 'Compute partition %s shall be busy, is free' %
......
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010-2022 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly advised to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
class SlapOSInstanceTreeMixin(object):
def getSlapTimestamp(self):
return int(self.getModificationDate())
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Mixin Component" module="erp5.portal_type"/>
</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>SlapOSInstanceTreeMixin</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>mixin.erp5.SlapOSInstanceTreeMixin</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Mixin Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</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>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -104,6 +104,14 @@ ...@@ -104,6 +104,14 @@
<tuple/> <tuple/>
</value> </value>
</item> </item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple>
<string>SlapOSInstanceTreeMixin</string>
</tuple>
</value>
</item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
......
...@@ -102,6 +102,15 @@ ...@@ -102,6 +102,15 @@
<tuple/> <tuple/>
</value> </value>
</item> </item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple>
<string>JIOAPIRevisionMixin</string>
<string>SlapOSCacheMixin</string>
</tuple>
</value>
</item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="Base Type" module="erp5.portal_type"/> <global name="JSON Type" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
...@@ -18,10 +18,6 @@ ...@@ -18,10 +18,6 @@
<none/> <none/>
</value> </value>
</item> </item>
<item>
<key> <string>factory</string> </key>
<value> <string>addXMLObject</string> </value>
</item>
<item> <item>
<key> <string>group_list</string> </key> <key> <string>group_list</string> </key>
<value> <value>
...@@ -48,22 +44,61 @@ ...@@ -48,22 +44,61 @@
</item> </item>
<item> <item>
<key> <string>portal_type</string> </key> <key> <string>portal_type</string> </key>
<value> <string>Base Type</string> </value> <value> <string>JSON Type</string> </value>
</item> </item>
<item> <item>
<key> <string>searchable_text_property_id</string> </key> <key> <string>text_content</string> </key>
<value> <value> <string>{\n
<tuple> "$schema": "http://json-schema.org/draft-07/schema#",\n
<string>title</string> "$id": "software-instance-base-schema.json",\n
<string>description</string> "title": "Software Installation",\n
<string>reference</string> "description": "Software Installation",\n
<string>short_title</string> "type": "object",\n
</tuple> "properties": {\n
</value> "software_release_uri": {\n
"title": "Software Release URI",\n
"type": "string"\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
"state": {\n
"title": "Requested State",\n
"type": "string",\n
"enum": ["available", "destroyed"],\n
"description": "State of the requested software",\n
"default": "available"\n
},\n
"reported_state": {\n
"title": "Reported State",\n
"type": "string",\n
"enum": ["available", "destroyed", "building", ""],\n
"description": "State reported by the node installing the Software Installation"\n
},\n
"status_message": {\n
"title": "Status Message",\n
"description": "Last Message received for the Software Installation",\n
"type": "string"\n
},\n
"api_revision": {\n
"title": "API Revision",\n
"type": "string",\n
"description": "The API Revision is set by the master node to mark when the element was last processed. It is incremental. If revision has changed, critical data has been updated"\n
},\n
"portal_type": {\n
"title": "Portal Type",\n
"const": "Software Installation",\n
"type": "string"\n
}\n
}\n
}\n
</string> </value>
</item> </item>
<item> <item>
<key> <string>type_class</string> </key> <key> <string>type_class</string> </key>
<value> <string>Item</string> </value> <value> <string>SoftwareInstallation</string> </value>
</item> </item>
<item> <item>
<key> <string>type_interface</string> </key> <key> <string>type_interface</string> </key>
...@@ -71,6 +106,15 @@ ...@@ -71,6 +106,15 @@
<tuple/> <tuple/>
</value> </value>
</item> </item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple>
<string>JIOAPIRevisionMixin</string>
<string>SlapOSCacheMixin</string>
</tuple>
</value>
</item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
......
...@@ -2,27 +2,14 @@ ...@@ -2,27 +2,14 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="Base Type" module="erp5.portal_type"/> <global name="JSON Type" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item> <item>
<key> <string>_property_domain_dict</string> </key> <key> <string>_property_domain_dict</string> </key>
<value> <value>
<dictionary> <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
<item>
<key> <string>short_title</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value> </value>
</item> </item>
<item> <item>
...@@ -33,10 +20,6 @@ ...@@ -33,10 +20,6 @@
<key> <string>description</string> </key> <key> <string>description</string> </key>
<value> <string>ERP5 default document. Supports synchronisation and XML.</string> </value> <value> <string>ERP5 default document. Supports synchronisation and XML.</string> </value>
</item> </item>
<item>
<key> <string>factory</string> </key>
<value> <string>addSoftwareInstance</string> </value>
</item>
<item> <item>
<key> <string>group_list</string> </key> <key> <string>group_list</string> </key>
<value> <value>
...@@ -45,26 +28,14 @@ ...@@ -45,26 +28,14 @@
</tuple> </tuple>
</value> </value>
</item> </item>
<item>
<key> <string>icon</string> </key>
<value> <string>document_icon.gif</string> </value>
</item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>Software Instance</string> </value> <value> <string>Software Instance</string> </value>
</item> </item>
<item>
<key> <string>immediate_view</string> </key>
<value> <string>XMLObject_view</string> </value>
</item>
<item> <item>
<key> <string>init_script</string> </key> <key> <string>init_script</string> </key>
<value> <string>SoftwareInstance_init</string> </value> <value> <string>SoftwareInstance_init</string> </value>
</item> </item>
<item>
<key> <string>meta_type</string> </key>
<value> <string>ERP5 XML Object</string> </value>
</item>
<item> <item>
<key> <string>permission</string> </key> <key> <string>permission</string> </key>
<value> <value>
...@@ -73,11 +44,7 @@ ...@@ -73,11 +44,7 @@
</item> </item>
<item> <item>
<key> <string>portal_type</string> </key> <key> <string>portal_type</string> </key>
<value> <string>Base Type</string> </value> <value> <string>JSON Type</string> </value>
</item>
<item>
<key> <string>product</string> </key>
<value> <string>ERP5Type</string> </value>
</item> </item>
<item> <item>
<key> <string>searchable_text_property_id</string> </key> <key> <string>searchable_text_property_id</string> </key>
...@@ -90,6 +57,159 @@ ...@@ -90,6 +57,159 @@
</tuple> </tuple>
</value> </value>
</item> </item>
<item>
<key> <string>text_content</string> </key>
<value> <string>{\n
"$schema": "http://json-schema.org/draft-07/schema#",\n
"$id": "software-instance-base-schema.json",\n
"title": "Software Instance",\n
"description": "Software Instance",\n
"type": "object",\n
"properties": {\n
"$schema": {\n
"title": "Schema URL",\n
"type": "string",\n
"description": "URL of the response schema"\n
},\n
"title": {\n
"title": "Title",\n
"type": "string",\n
"description": "Unique Name of the Software Instance",\n
"maxLength": 200\n
},\n
"reference": {\n
"title": "Software Instance Reference",\n
"description": "Unique identifier of the Software Instance",\n
"type": "string",\n
"maxLength": 50\n
},\n
"software_release_uri": {\n
"title": "Software Release URI",\n
"type": "string",\n
"description": "URL of the software release used by the software instance"\n
},\n
"software_type": {\n
"title": "Software Type",\n
"type": "string",\n
"description": "Software type of the instance, it define the type of the instance according to the software release"\n
},\n
"state": {\n
"title": "Requested State",\n
"type": "string",\n
"enum": ["started", "stopped", "destroyed"],\n
"description": "State of the requested instance. It is functionnal when started. In stopped state, all services are stopped. If destroyed, it will remove the instance."\n
},\n
"connection_parameters": {\n
"title": "Connections Parameters",\n
"type": "object",\n
"description": "List of parameters provided by the instance to access it. Updated by the instance.",\n
"additionalProperties": { "type": "string" }\n
},\n
"parameters": {\n
"title": "Instance Parameters",\n
"type": "object",\n
"description": "Parameters provided to the instance when requested to configure it.",\n
"additionalProperties": { "type": "string" }\n
},\n
"shared": {\n
"title": "Shared Instance",\n
"type": "boolean",\n
"description": "This instance is Shared Instance hosted on another instance. It doesn\'t use a computer partition."\n
},\n
"root_instance_title": {\n
"title": "Root Instance Title",\n
"type": "string",\n
"description": "Title of the Instance at the root of the instance tree. This is the title of the instance that has been requested by the user."\n
},\n
"ip_list": {\n
"title": "IP List",\n
"type": "array",\n
"descritpion": "List of IPs usable by the Software Instance on the partition",\n
"items": {\n
"type": "array",\n
"items": {\n
"type": "string"\n
}\n
}\n
},\n
"full_ip_list": {\n
"title": "Full IP List",\n
"type": "array",\n
"descritpion": "XXXX List of IPs usable by the Software Instance on the partition",\n
"items": {\n
"type": "array",\n
"items": {\n
"type": "string"\n
}\n
}\n
},\n
"sla_parameters": {\n
"title": "Target Node Selection Parameters",\n
"type": "object",\n
"description": "Also known as SLA parameters. Used to pick where an how the instance is to be deployed",\n
"properties": {\n
"computer_guid": {\n
"title": "Requested Compute Node",\n
"descritpion": "Requested Compute Node Reference, like COMP-1234",\n
"type": "string"\n
},\n
"project_guid": {\n
"title": "Requested Project",\n
"descritpion": "Requested Project Reference",\n
"type": "string"\n
},\n
"instance_guid": {\n
"title": "Requested Host Instance",\n
"descritpion": "Only applicable to shared instance. Requested Host Instance Reference, like SOFTINST-1234",\n
"type": "string"\n
},\n
"network_guid": {\n
"title": "Requested Network",\n
"descritpion": "Requested Network Reference",\n
"type": "string"\n
},\n
"retention_delay": {\n
"title": "Retention Delay",\n
"Description": "Number of days during the data is preserved after the instance is destroyed",\n
"type": "number"\n
}\n
},\n
"additionalProperties": { "type": "string" }\n
},\n
"compute_node_id": {\n
"title": "Compute Node Id",\n
"type": "string",\n
"description": "Id Of the Requesting Compute Node, used by Slap Client when an instance is requesting an instance"\n
},\n
"compute_partition_id": {\n
"title": "Compute Partition Id",\n
"type": "string",\n
"description": "Id Of the Requesting Compute Partition, used by Slap Client when an instance is requesting an instance"\n
},\n
"processing_timestamp": {\n
"title": "Processing Timestamp",\n
"type": "number",\n
"description": "Timestamp set by the master node to mark when it was last processed in the master node. If it has been processed on master, it needs reprocessiing on the compute node."\n
},\n
"api_revision": {\n
"title": "API Revision",\n
"type": "string",\n
"description": "The API Revision is set by the master node to mark when the element was last processed. It is incremental. If revision has changed, critical data has been updated"\n
},\n
"access_status_message": {\n
"title": "Access Status",\n
"type": "string",\n
"description": "Get latest software instance Access message state"\n
},\n
"portal_type": {\n
"title": "Portal Type",\n
"const": "Software Instance",\n
"type": "string"\n
}\n
}\n
}\n
</string> </value>
</item>
<item> <item>
<key> <string>type_class</string> </key> <key> <string>type_class</string> </key>
<value> <string>SoftwareInstance</string> </value> <value> <string>SoftwareInstance</string> </value>
...@@ -100,10 +220,72 @@ ...@@ -100,10 +220,72 @@
<tuple/> <tuple/>
</value> </value>
</item> </item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple>
<string>JIOAPIRevisionMixin</string>
<string>SlapOSCacheMixin</string>
</tuple>
</value>
</item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
<record id="2" aka="AAAAAAAAAAI="> <record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>description</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>short_title</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="TranslationInformation" module="Products.ERP5Type.TranslationProviderBase"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>domain_name</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>property_name</string> </key>
<value> <string>description</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle> <pickle>
<global name="TranslationInformation" module="Products.ERP5Type.TranslationProviderBase"/> <global name="TranslationInformation" module="Products.ERP5Type.TranslationProviderBase"/>
</pickle> </pickle>
...@@ -120,7 +302,7 @@ ...@@ -120,7 +302,7 @@
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
<record id="3" aka="AAAAAAAAAAM="> <record id="5" aka="AAAAAAAAAAU=">
<pickle> <pickle>
<global name="TranslationInformation" module="Products.ERP5Type.TranslationProviderBase"/> <global name="TranslationInformation" module="Products.ERP5Type.TranslationProviderBase"/>
</pickle> </pickle>
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
<item>SlapOSCatalogToolCacheMixin</item> <item>SlapOSCatalogToolCacheMixin</item>
</portal_type> </portal_type>
<portal_type id="Compute Node"> <portal_type id="Compute Node">
<item>JIOAPIRevisionMixin</item>
<item>SlapOSCacheMixin</item> <item>SlapOSCacheMixin</item>
<item>SlapOSComputeNodeMixin</item> <item>SlapOSComputeNodeMixin</item>
</portal_type> </portal_type>
...@@ -10,8 +11,8 @@ ...@@ -10,8 +11,8 @@
<item>SlapOSCacheMixin</item> <item>SlapOSCacheMixin</item>
<item>SlapOSComputePartitionMixin</item> <item>SlapOSComputePartitionMixin</item>
</portal_type> </portal_type>
<portal_type id="Instance Node"> <portal_type id="Instance Tree">
<item>SlapOSCacheMixin</item> <item>SlapOSInstanceTreeMixin</item>
</portal_type> </portal_type>
<portal_type id="Person"> <portal_type id="Person">
<item>SlapOSCacheMixin</item> <item>SlapOSCacheMixin</item>
...@@ -27,5 +28,12 @@ ...@@ -27,5 +28,12 @@
</portal_type> </portal_type>
<portal_type id="Software Instance"> <portal_type id="Software Instance">
<item>SlapOSCacheMixin</item> <item>SlapOSCacheMixin</item>
<item>JIOAPIRevisionMixin</item>
</portal_type>
<portal_type id="Software Installation">
<item>JIOAPIRevisionMixin</item>
</portal_type>
<portal_type id="Software Instance">
<item>JIOAPIRevisionMixin</item>
</portal_type> </portal_type>
</type_mixin> </type_mixin>
\ No newline at end of file
...@@ -100,6 +100,7 @@ ...@@ -100,6 +100,7 @@
<value> <value>
<list> <list>
<string>my_preferred_hateoas_url</string> <string>my_preferred_hateoas_url</string>
<string>my_preferred_jio_api_url</string>
<string>my_preferred_slapos_web_site_url</string> <string>my_preferred_slapos_web_site_url</string>
<string>my_preferred_shacache_website_expected_state</string> <string>my_preferred_shacache_website_expected_state</string>
<string>my_preferred_wechat_integration_site</string> <string>my_preferred_wechat_integration_site</string>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_preferred_jio_api_url</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>items</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_reference</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>items</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Preferred JIO API URL</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: [(\'\', \'\')] + [(x.getTitle(), x.getRelativeUrl()) for x in here.portal_catalog(portal_type=\'Service\', sort_on=((\'title\', \'ASC\'),),checked_permission=\'View\')]</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -40,7 +40,7 @@ compute_node_list = portal.portal_catalog.portal_catalog( ...@@ -40,7 +40,7 @@ compute_node_list = portal.portal_catalog.portal_catalog(
if len(compute_node_list) == 2: if len(compute_node_list) == 2:
raise NotImplementedError raise NotImplementedError
elif len(compute_node_list) == 1: elif len(compute_node_list) == 1:
compute_node = compute_node_list[0] compute_node = compute_node_list[0].getObject()
assert compute_node.getFollowUp() == project_list[0].getRelativeUrl() assert compute_node.getFollowUp() == project_list[0].getRelativeUrl()
else: else:
...@@ -55,10 +55,9 @@ else: ...@@ -55,10 +55,9 @@ else:
follow_up_value=project_list[0], follow_up_value=project_list[0],
activate_kw={'tag': tag} activate_kw={'tag': tag}
) )
compute_node.approveComputeNodeRegistration() compute_node.requestComputeNodeRegistration()
if kwargs.get("approve_registration", True):
compute_node.approveComputeNodeRegistration()
compute_node = context.restrictedTraverse(compute_node.getRelativeUrl())
context.REQUEST.set("compute_node", compute_node.getRelativeUrl()) context.REQUEST.set("compute_node", compute_node.getRelativeUrl())
context.REQUEST.set("compute_node_url", compute_node.absolute_url()) context.REQUEST.set("compute_node_url", compute_node.absolute_url())
......
erp5_json_editor erp5_json_editor
erp5_access_token erp5_access_token
erp5_api_style
erp5_item erp5_item
erp5_computer_immobilisation erp5_computer_immobilisation
erp5_software_pdm erp5_software_pdm
slapos_mysql_innodb_catalog slapos_mysql_innodb_catalog
erp5_certificate_authority erp5_certificate_authority
erp5_open_trade erp5_open_trade
erp5_interaction_drop erp5_interaction_drop
\ No newline at end of file
document.erp5.SoftwareInstance document.erp5.SoftwareInstance
\ No newline at end of file document.erp5.SoftwareInstallation
\ No newline at end of file
mixin.erp5.SlapOSCacheMixin mixin.erp5.SlapOSCacheMixin
mixin.erp5.SlapOSComputeNodeMixin mixin.erp5.SlapOSComputeNodeMixin
mixin.erp5.SlapOSComputePartitionMixin mixin.erp5.SlapOSComputePartitionMixin
mixin.erp5.SlapOSCatalogToolCacheMixin mixin.erp5.SlapOSCatalogToolCacheMixin
\ No newline at end of file mixin.erp5.SlapOSInstanceTreeMixin
\ No newline at end of file
Catalog Tool | SlapOSCatalogToolCacheMixin Catalog Tool | SlapOSCatalogToolCacheMixin
Compute Node | JIOAPIRevisionMixin
Compute Node | SlapOSCacheMixin Compute Node | SlapOSCacheMixin
Compute Node | SlapOSComputeNodeMixin Compute Node | SlapOSComputeNodeMixin
Compute Partition | SlapOSCacheMixin Compute Partition | SlapOSCacheMixin
...@@ -7,5 +8,9 @@ Instance Node | SlapOSCacheMixin ...@@ -7,5 +8,9 @@ Instance Node | SlapOSCacheMixin
Person | SlapOSCacheMixin Person | SlapOSCacheMixin
Remote Node | SlapOSCacheMixin Remote Node | SlapOSCacheMixin
Slave Instance | SlapOSCacheMixin Slave Instance | SlapOSCacheMixin
Software Instance | SlapOSCacheMixin
Software Installation | SlapOSCacheMixin Software Installation | SlapOSCacheMixin
Software Instance | SlapOSCacheMixin Instance Tree | SlapOSInstanceTreeMixin
\ No newline at end of file Slave Instance | JIOAPIRevisionMixin
Software Instance | JIOAPIRevisionMixin
Software Installation | JIOAPIRevisionMixin
erp5_full_text_mroonga_catalog
slapos_configurator
\ No newline at end of file
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