Commit e4ae5155 authored by Romain Courteaud's avatar Romain Courteaud

XXX REVERT: stop spreading api code in slapos_cloud

Include code to move
parent 97b80f6e
##############################################################################
#
# 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
...@@ -26,11 +26,8 @@ ...@@ -26,11 +26,8 @@
# #
############################################################################## ##############################################################################
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
...@@ -40,10 +37,12 @@ from erp5.component.module.SlapOSCloud import _assertACI ...@@ -40,10 +37,12 @@ from erp5.component.module.SlapOSCloud import _assertACI
from zLOG import LOG, INFO from zLOG import LOG, INFO
try: try:
from slapos.util import xml2dict from slapos.util import xml2dict, loads
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
...@@ -51,7 +50,7 @@ class DisconnectedSoftwareTree(Exception): ...@@ -51,7 +50,7 @@ class DisconnectedSoftwareTree(Exception):
class CyclicSoftwareTree(Exception): class CyclicSoftwareTree(Exception):
pass pass
class SoftwareInstance(Item, JSONType): class SoftwareInstance(Item):
""" """
""" """
...@@ -158,8 +157,6 @@ class SoftwareInstance(Item, JSONType): ...@@ -158,8 +157,6 @@ class SoftwareInstance(Item, JSONType):
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)
...@@ -180,68 +177,24 @@ class SoftwareInstance(Item, JSONType): ...@@ -180,68 +177,24 @@ class SoftwareInstance(Item, JSONType):
software_instance_dict['_instance_guid'] = instance_guid software_instance_dict['_instance_guid'] = instance_guid
return software_instance_dict return software_instance_dict
def getSlapTimestamp(self): def _getModificationDateAsTimestamp(self, document):
return self._getSlapTimestamp() return int(float(document.getModificationDate()) * 1e6)
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 _asParameterDict") raise ValueError("Instance isn't allocated to call _asParamterDict")
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 = []
if (self.getPortalType() == "Software Instance"):
for internet_protocol_address in compute_partition.contentValues(portal_type='Internet Protocol Address'): for internet_protocol_address in compute_partition.contentValues(portal_type='Internet Protocol Address'):
# XXX - There is new values, and we must keep compatibility # XXX - There is new values, and we must keep compatibility
address_tuple = ( address_tuple = (
...@@ -329,21 +282,19 @@ class SoftwareInstance(Item, JSONType): ...@@ -329,21 +282,19 @@ class SoftwareInstance(Item, JSONType):
return ip_address_list return ip_address_list
def updateRequestedInstanceList(self, instance_reference_list): def _updateSucessorList(self, instance_reference_xml):
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_list contain list of title of sub-instances requested by instance_reference_xml 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, str(instance_reference_list)): if not self.isLastData(cache_reference, instance_reference_xml):
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]
...@@ -357,86 +308,4 @@ class SoftwareInstance(Item, JSONType): ...@@ -357,86 +308,4 @@ class SoftwareInstance(Item, JSONType):
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(str(instance_reference_list), key=cache_reference) self.setLastData(instance_reference_xml, 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,6 +30,7 @@ from OFS.Traversable import NotFound ...@@ -30,6 +30,7 @@ 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.
...@@ -71,13 +72,9 @@ class SlapOSCatalogToolCacheMixin(object): ...@@ -71,13 +72,9 @@ class SlapOSCatalogToolCacheMixin(object):
@UnrestrictedMethod @UnrestrictedMethod
def _getNonCachedComputeNodeUid(self, reference): def _getNonCachedComputeNodeUid(self, reference):
compute_node_list = self.unrestrictedSearchResults( return self.unrestrictedSearchResults(
portal_type='Compute Node', reference=reference, portal_type=['Compute Node', 'Remote Node'], reference=reference,
validation_state="validated") validation_state="validated")[0].UID
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):
...@@ -95,28 +92,3 @@ class SlapOSCatalogToolCacheMixin(object): ...@@ -95,28 +92,3 @@ 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,12 +6,6 @@ ...@@ -6,12 +6,6 @@
</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>
...@@ -61,28 +55,13 @@ ...@@ -61,28 +55,13 @@
<item> <item>
<key> <string>workflow_history</string> </key> <key> <string>workflow_history</string> </key>
<value> <value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent> <persistent> <string encoding="base64">AAAAAAAAAAI=</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>
...@@ -95,7 +74,7 @@ ...@@ -95,7 +74,7 @@
<item> <item>
<key> <string>component_validation_workflow</string> </key> <key> <string>component_validation_workflow</string> </key>
<value> <value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent> <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value> </value>
</item> </item>
</dictionary> </dictionary>
...@@ -104,7 +83,7 @@ ...@@ -104,7 +83,7 @@
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
<record id="4" aka="AAAAAAAAAAQ="> <record id="3" aka="AAAAAAAAAAM=">
<pickle> <pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/> <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle> </pickle>
......
...@@ -115,7 +115,9 @@ class SlapOSComputeNodeMixin(object): ...@@ -115,7 +115,9 @@ 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'\
...@@ -314,7 +316,7 @@ class SlapOSComputeNodeMixin(object): ...@@ -314,7 +316,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(),
...@@ -334,70 +336,3 @@ class SlapOSComputeNodeMixin(object): ...@@ -334,70 +336,3 @@ class SlapOSComputeNodeMixin(object):
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,14 +104,6 @@ ...@@ -104,14 +104,6 @@
<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,15 +102,6 @@ ...@@ -102,15 +102,6 @@
<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="JSON Type" module="erp5.portal_type"/> <global name="Base Type" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
<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>
...@@ -44,61 +48,22 @@ ...@@ -44,61 +48,22 @@
</item> </item>
<item> <item>
<key> <string>portal_type</string> </key> <key> <string>portal_type</string> </key>
<value> <string>JSON Type</string> </value> <value> <string>Base Type</string> </value>
</item> </item>
<item> <item>
<key> <string>text_content</string> </key> <key> <string>searchable_text_property_id</string> </key>
<value> <string>{\n <value>
"$schema": "http://json-schema.org/draft-07/schema#",\n <tuple>
"$id": "software-instance-base-schema.json",\n <string>title</string>
"title": "Software Installation",\n <string>description</string>
"description": "Software Installation",\n <string>reference</string>
"type": "object",\n <string>short_title</string>
"properties": {\n </tuple>
"software_release_uri": {\n </value>
"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>SoftwareInstallation</string> </value> <value> <string>Item</string> </value>
</item> </item>
<item> <item>
<key> <string>type_interface</string> </key> <key> <string>type_interface</string> </key>
...@@ -106,15 +71,6 @@ ...@@ -106,15 +71,6 @@
<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>
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
<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>
...@@ -11,8 +10,8 @@ ...@@ -11,8 +10,8 @@
<item>SlapOSCacheMixin</item> <item>SlapOSCacheMixin</item>
<item>SlapOSComputePartitionMixin</item> <item>SlapOSComputePartitionMixin</item>
</portal_type> </portal_type>
<portal_type id="Instance Tree"> <portal_type id="Instance Node">
<item>SlapOSInstanceTreeMixin</item> <item>SlapOSCacheMixin</item>
</portal_type> </portal_type>
<portal_type id="Person"> <portal_type id="Person">
<item>SlapOSCacheMixin</item> <item>SlapOSCacheMixin</item>
...@@ -28,12 +27,5 @@ ...@@ -28,12 +27,5 @@
</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,7 +100,6 @@ ...@@ -100,7 +100,6 @@
<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>
...@@ -2,19 +2,13 @@ ...@@ -2,19 +2,13 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="Document Component" module="erp5.portal_type"/> <global name="Test Component" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item> <item>
<key> <string>default_reference</string> </key> <key> <string>default_reference</string> </key>
<value> <string>SoftwareInstallation</string> </value> <value> <string>SlapOSTestCaseDefaultScenarioMixin</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value>
<none/>
</value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
...@@ -24,11 +18,11 @@ ...@@ -24,11 +18,11 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>document.erp5.SoftwareInstallation</string> </value> <value> <string>test.erp5.SlapOSTestCaseDefaultScenarioMixin</string> </value>
</item> </item>
<item> <item>
<key> <string>portal_type</string> </key> <key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value> <value> <string>Test Component</string> </value>
</item> </item>
<item> <item>
<key> <string>sid</string> </key> <key> <string>sid</string> </key>
......
...@@ -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].getObject() compute_node = compute_node_list[0]
assert compute_node.getFollowUp() == project_list[0].getRelativeUrl() assert compute_node.getFollowUp() == project_list[0].getRelativeUrl()
else: else:
...@@ -57,6 +57,9 @@ else: ...@@ -57,6 +57,9 @@ else:
) )
compute_node.approveComputeNodeRegistration() 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())
context.REQUEST.set("compute_node_reference", compute_node.getReference()) context.REQUEST.set("compute_node_reference", compute_node.getReference())
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
......
document.erp5.SoftwareInstance document.erp5.SoftwareInstance
document.erp5.SoftwareInstallation
\ No newline at end of file
...@@ -2,4 +2,3 @@ mixin.erp5.SlapOSCacheMixin ...@@ -2,4 +2,3 @@ mixin.erp5.SlapOSCacheMixin
mixin.erp5.SlapOSComputeNodeMixin mixin.erp5.SlapOSComputeNodeMixin
mixin.erp5.SlapOSComputePartitionMixin mixin.erp5.SlapOSComputePartitionMixin
mixin.erp5.SlapOSCatalogToolCacheMixin mixin.erp5.SlapOSCatalogToolCacheMixin
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
...@@ -8,9 +7,5 @@ Instance Node | SlapOSCacheMixin ...@@ -8,9 +7,5 @@ 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
Instance Tree | SlapOSInstanceTreeMixin Software Instance | SlapOSCacheMixin
Slave Instance | JIOAPIRevisionMixin \ No newline at end of file
Software Instance | JIOAPIRevisionMixin
Software Installation | JIOAPIRevisionMixin
...@@ -14,5 +14,4 @@ test.erp5.testSlapOSCloudPersonSlapInterfaceWorkflow ...@@ -14,5 +14,4 @@ test.erp5.testSlapOSCloudPersonSlapInterfaceWorkflow
test.erp5.testSlapOSCloudProjectSlapInterfaceWorkflow test.erp5.testSlapOSCloudProjectSlapInterfaceWorkflow
test.erp5.testSlapOSCloudSecurityGroup test.erp5.testSlapOSCloudSecurityGroup
test.erp5.testSlapOSCloudShadow test.erp5.testSlapOSCloudShadow
test.erp5.SlapOSTestCaseMixin test.erp5.testSlapOSCloudUpgrader
test.erp5.testSlapOSCloud \ No newline at end of file
\ No newline at end of file
erp5_full_text_mroonga_catalog
slapos_configurator
\ No newline at end of file
<type_mixin>
<portal_type id="Compute Node">
<item>JIOAPIRevisionMixin</item>
</portal_type>
<portal_type id="Slave Instance">
<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>
</type_mixin>
\ No newline at end of file
Compute Node | JIOAPIRevisionMixin
Slave Instance | JIOAPIRevisionMixin
Software Installation | JIOAPIRevisionMixin
Software Instance | JIOAPIRevisionMixin
\ 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