Commit 6623f7e3 authored by Rafael Monnerat's avatar Rafael Monnerat

slapos_cloud: Refactor SlapTool&Mixins to drop internal slap lib usage

   The internal API only store dict, rather them store xml.

   slapos.slap.slap is only used on SlapTool context, releasing the
internal API on having it.

   The approach is deprecate the usage of it as soon clients relies on
  a different API.
parent 1ac3ec59
......@@ -31,31 +31,18 @@ from erp5.component.document.Item import Item
from lxml import etree
import collections
from AccessControl import Unauthorized
from AccessControl.Permissions import access_contents_information
from AccessControl import getSecurityManager
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
from erp5.component.module.SlapOSCloud import _assertACI
from zLOG import LOG, INFO
try:
from slapos.slap.slap import \
SoftwareInstance as SlapSoftwareInstance
from slapos.util import xml2dict, loads
except ImportError:
def xml2dict(dictionary):
raise ImportError
def loads(*args):
raise ImportError
class SlapSoftwareInstance:
def __init__(self):
raise ImportError
def _assertACI(document):
sm = getSecurityManager()
if sm.checkPermission(access_contents_information,
document):
return document
raise Unauthorized('User %r has no access to %r' % (sm.getUser(), document))
class DisconnectedSoftwareTree(Exception):
pass
......@@ -160,7 +147,7 @@ class SoftwareInstance(Item):
LOG('SoftwareInstance', INFO, 'Issue during parsing xml:', error=True)
return result_dict
def _asSoftwareInstance(self):
def _asSoftwareInstanceDict(self):
parameter_dict = self._asParameterDict()
requested_state = self.getSlapState()
......@@ -182,13 +169,13 @@ class SoftwareInstance(Item):
parameter_dict.pop('filter_xml'))
instance_guid = parameter_dict.pop('instance_guid')
software_instance = SlapSoftwareInstance(**parameter_dict)
software_instance._parameter_dict = xml
software_instance._connection_dict = connection_xml
software_instance._filter_dict = filter_xml
software_instance._requested_state = state
software_instance._instance_guid = instance_guid
return software_instance
software_instance_dict = parameter_dict
software_instance_dict['_parameter_dict'] = xml
software_instance_dict['_connection_dict'] = connection_xml
software_instance_dict['_filter_dict'] = filter_xml
software_instance_dict['_requested_state'] = state
software_instance_dict['_instance_guid'] = instance_guid
return software_instance_dict
@UnrestrictedMethod
def _asParameterDict(self, shared_instance_sql_list=None):
......
......@@ -6,12 +6,6 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SoftwareInstance</string> </value>
......@@ -55,28 +49,13 @@
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
......@@ -89,7 +68,7 @@
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
......@@ -98,7 +77,7 @@
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
......
......@@ -28,46 +28,22 @@
from Products.ERP5Type.Cache import DEFAULT_CACHE_SCOPE
from AccessControl import Unauthorized
from AccessControl.Permissions import access_contents_information
from AccessControl import getSecurityManager
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
from Products.ERP5Type.tests.utils import DummyMailHostMixin
from OFS.Traversable import NotFound
from erp5.component.module.SlapOSCloud import _assertACI
import time
from lxml import etree
from zLOG import LOG, INFO
try:
from slapos.slap.slap import (
Computer as ComputeNode,
ComputerPartition as SlapComputePartition,
SoftwareRelease)
from slapos.util import xml2dict, dumps
from slapos.util import xml2dict
except ImportError:
# Do no prevent instance from starting
# if libs are not installed
class ComputeNode:
def __init__(self):
raise ImportError
class SlapComputePartition:
def __init__(self):
raise ImportError
class SoftwareRelease:
def __init__(self):
raise ImportError
def xml2dict(dictionary):
raise ImportError
def dumps(*args):
raise ImportError
def _assertACI(document):
sm = getSecurityManager()
if sm.checkPermission(access_contents_information,
document):
return document
raise Unauthorized('User %r has no access to %r' % (sm.getUser(), document))
class SlapOSComputeNodeMixin(object):
......@@ -87,42 +63,42 @@ class SlapOSComputeNodeMixin(object):
validation_state='validated',
):
software_installation = _assertACI(software_installation.getObject())
software_release_response = SoftwareRelease(
software_release=software_installation.getUrlString().decode('UTF-8'),
computer_guid=self.getReference().decode('UTF-8'))
software_release_dict = {
"software_release": software_installation.getUrlString().decode('UTF-8'),
"computer_guid": self.getReference().decode('UTF-8')
}
if software_installation.getSlapState() == 'destroy_requested':
software_release_response._requested_state = 'destroyed'
software_release_dict["_requested_state"] = 'destroyed'
else:
software_release_response._requested_state = 'available'
software_release_dict["_requested_state"] = 'available'
known_state = software_installation.getTextAccessStatus()
if known_state.startswith("#access"):
software_release_response._known_state = 'available'
software_release_dict["_known_state"] = 'available'
elif known_state.startswith("#building"):
software_release_response._known_state = 'building'
software_release_dict["_known_state"] = 'building'
else:
software_release_response._known_state = 'error'
software_release_dict["_known_state"] = 'error'
software_release_list.append(software_release_response)
software_release_list.append(software_release_dict)
return software_release_list
def _getCacheComputeNodeInformation(self, user):
self.REQUEST.response.setHeader('Content-Type', 'text/xml; charset=utf-8')
slap_compute_node = ComputeNode(self.getReference().decode("UTF-8"))
slap_compute_node._computer_partition_list = []
slap_compute_node._software_release_list = self._getSoftwareReleaseValueList()
compute_node_dict = {
"_computer_id": self.getReference().decode("UTF-8"),
"_computer_partition_list": [],
"_software_release_list": self._getSoftwareReleaseValueList()
}
unrestrictedSearchResults = self.getPortalObject().portal_catalog.unrestrictedSearchResults
compute_partition_list = unrestrictedSearchResults(
parent_uid=self.getUid(),
validation_state="validated",
portal_type="Compute Partition"
)
self._calculateSlapComputeNodeInformation(slap_compute_node, compute_partition_list)
self._calculateSlapComputeNodeInformation(compute_node_dict, compute_partition_list)
return dumps(slap_compute_node)
return compute_node_dict
def _activateFillComputeNodeInformationCache(self, user):
tag = 'compute_node_information_cache_fill_%s_%s' % (self.getReference(), user)
......@@ -180,9 +156,6 @@ class SlapOSComputeNodeMixin(object):
user_type = user_document.getPortalType()
self.REQUEST.response.setHeader('Content-Type', 'text/xml; charset=utf-8')
slap_compute_node = ComputeNode(self.getReference().decode("UTF-8"))
slap_compute_node._computer_partition_list = []
if user_type in ('Compute Node', 'Person'):
if not self._isTestRun():
cache_plugin = self._getCachePlugin()
......@@ -207,7 +180,11 @@ class SlapOSComputeNodeMixin(object):
else:
return self._getCacheComputeNodeInformation(user), None
else:
slap_compute_node._software_release_list = []
compute_node_dict = {
"_computer_id": self.getReference().decode("UTF-8"),
"_computer_partition_list": [],
"_software_release_list": []
}
if user_type == 'Software Instance':
compute_partition_list = self.contentValues(
......@@ -219,10 +196,10 @@ class SlapOSComputeNodeMixin(object):
validation_state="validated",
portal_type="Compute Partition")
self._calculateSlapComputeNodeInformation(slap_compute_node, compute_partition_list)
return dumps(slap_compute_node), None
self._calculateSlapComputeNodeInformation(compute_node_dict, compute_partition_list)
return compute_node_dict, None
def _calculateSlapComputeNodeInformation(self, slap_compute_node, compute_partition_list):
def _calculateSlapComputeNodeInformation(self, compute_node_dict, compute_partition_list):
if len(compute_partition_list) == 0:
return
......@@ -248,7 +225,7 @@ class SlapOSComputeNodeMixin(object):
software_instance_list = [x for x in grouped_software_instance_list if (x.default_aggregate_uid == compute_partition.getUid())]
if (len(software_instance_list) == 1) and (software_instance_list[0]['count(*)'] > 1):
software_instance_list = software_instance_list + software_instance_list
slap_compute_node._computer_partition_list.append(
compute_node_dict['_computer_partition_list'].append(
self._getSlapPartitionByPackingList(
_assertACI(compute_partition.getObject()),
software_instance_list,
......@@ -273,12 +250,13 @@ class SlapOSComputeNodeMixin(object):
while compute_node.getPortalType() != 'Compute Node':
compute_node = compute_node.getParentValue()
compute_node_id = compute_node.getReference().decode("UTF-8")
slap_partition = SlapComputePartition(compute_node_id,
compute_partition_document.getReference().decode("UTF-8"))
slap_partition._software_release_document = None
slap_partition._requested_state = 'destroyed'
slap_partition._need_modification = 0
partition_dict = {
"compute_node_id": compute_node_id,
"partition_id": compute_partition_document.getReference().decode("UTF-8"),
"_software_release_document": None,
"_requested_state": 'destroyed',
"_need_modification": 0
}
software_instance = None
......@@ -294,28 +272,29 @@ class SlapOSComputeNodeMixin(object):
if software_instance is not None:
state = software_instance.getSlapState()
if state == "stop_requested":
slap_partition._requested_state = 'stopped'
partition_dict['_requested_state'] = 'stopped'
if state == "start_requested":
slap_partition._requested_state = 'started'
slap_partition._access_status = software_instance.getTextAccessStatus()
partition_dict['_requested_state'] = 'started'
partition_dict['_access_status'] = software_instance.getTextAccessStatus()
slap_partition._software_release_document = SoftwareRelease(
software_release=software_instance.getUrlString().decode("UTF-8"),
computer_guid=compute_node_id)
partition_dict['_software_release_document'] = {
"software_release": software_instance.getUrlString().decode("UTF-8"),
"computer_guid": compute_node_id
}
slap_partition._need_modification = 1
partition_dict["_need_modification"] = 1
parameter_dict = software_instance._asParameterDict(
shared_instance_sql_list=shared_instance_sql_list
)
# software instance has to define an xml parameter
slap_partition._parameter_dict = self._instanceXmlToDict(
partition_dict["_parameter_dict"] = self._instanceXmlToDict(
parameter_dict.pop('xml'))
slap_partition._connection_dict = self._instanceXmlToDict(
partition_dict['_connection_dict'] = self._instanceXmlToDict(
parameter_dict.pop('connection_xml'))
slap_partition._filter_dict = self._instanceXmlToDict(
partition_dict['_filter_dict'] = self._instanceXmlToDict(
parameter_dict.pop('filter_xml'))
slap_partition._instance_guid = parameter_dict.pop('instance_guid')
partition_dict['_instance_guid'] = parameter_dict.pop('instance_guid')
for slave_instance_dict in parameter_dict.get("slave_instance_list", []):
if slave_instance_dict.has_key("connection_xml"):
slave_instance_dict.update(self._instanceXmlToDict(
......@@ -323,9 +302,9 @@ class SlapOSComputeNodeMixin(object):
if slave_instance_dict.has_key("xml"):
slave_instance_dict.update(self._instanceXmlToDict(
slave_instance_dict.pop("xml")))
slap_partition._parameter_dict.update(parameter_dict)
partition_dict['_parameter_dict'].update(parameter_dict)
return slap_partition
return partition_dict
def _getSoftwareInstallationFromUrl(self, url):
software_installation_list = self.getPortalObject().portal_catalog.unrestrictedSearchResults(
......
......@@ -6,12 +6,6 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SlapOSComputeNodeMixin</string> </value>
......@@ -55,28 +49,13 @@
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
......@@ -89,7 +68,7 @@
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
......@@ -98,7 +77,7 @@
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
......
......@@ -25,14 +25,11 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from AccessControl.Permissions import access_contents_information
from AccessControl import getSecurityManager
from AccessControl import Unauthorized
from erp5.component.module.SlapOSCloud import _assertACI
from zLOG import LOG, INFO
from OFS.Traversable import NotFound
try:
from slapos.slap.slap import (
ComputerPartition as SlapComputePartition,
SoftwareRelease)
from slapos.util import calculate_dict_hash
except ImportError:
# Do no prevent instance from starting
......@@ -46,27 +43,48 @@ except ImportError:
def calculate_dict_hash(*args):
raise ImportError
def _assertACI(document):
sm = getSecurityManager()
if sm.checkPermission(access_contents_information,
document):
return document
raise Unauthorized('User %r has no access to %r' % (sm.getUser(), document))
class SlapOSComputePartitionMixin(object):
def _getSoftwareInstance(self, slave_reference=None):
if self.getSlapState() != 'busy':
LOG('SlapOSComputePartitionMixin::_getSoftwareInstance', INFO,
'Compute partition %s shall be busy, is free' %
self.getRelativeUrl())
raise NotFound("No software instance found for: %s - %s" % (
self.getParentValue().getTitle(), self.getTitle()))
else:
query_kw = {
'validation_state': 'validated',
'portal_type': 'Slave Instance',
'default_aggregate_uid': self.getUid(),
}
if slave_reference is None:
query_kw['portal_type'] = "Software Instance"
else:
query_kw['reference'] = slave_reference
class SlapOSComputePartitionMixin(object):
software_instance = _assertACI(
self.getPortalObject().portal_catalog.unrestrictedGetResultValue(**query_kw))
if software_instance is None:
raise NotFound("No software instance found for: %s - %s" % (
self.getParentValue().getTitle(), self.getTitle()))
else:
return software_instance
def _registerComputePartition(self):
portal = self.getPortalObject()
computer_reference = self.getParentValue().getReference()
computer_partition_reference = self.getReference()
compute_node = self
while compute_node.getPortalType() != 'Compute Node':
compute_node = compute_node.getParentValue()
compute_node_id = compute_node.getReference().decode("UTF-8")
slap_partition = SlapComputePartition(computer_reference.decode("UTF-8"),
computer_partition_reference.decode("UTF-8"))
slap_partition._software_release_document = None
slap_partition._requested_state = 'destroyed'
slap_partition._need_modification = 0
software_instance = None
partition_dict = {
"compute_node_id": compute_node_id,
"partition_id": self.getReference().decode("UTF-8"),
"_software_release_document": None,
"_requested_state": 'destroyed',
"_need_modification": 0
}
if self.getSlapState() == 'busy':
software_instance_list = portal.portal_catalog.unrestrictedSearchResults(
......@@ -85,31 +103,31 @@ class SlapOSComputePartitionMixin(object):
self.getRelativeUrl())
if software_instance is not None:
# trick client side, that data has been synchronised already for given
# document
slap_partition._synced = True
state = software_instance.getSlapState()
if state == "stop_requested":
slap_partition._requested_state = 'stopped'
partition_dict['_requested_state'] = 'stopped'
if state == "start_requested":
slap_partition._requested_state = 'started'
partition_dict['_requested_state'] = 'started'
slap_partition._software_release_document = SoftwareRelease(
software_release=software_instance.getUrlString().decode("UTF-8"),
computer_guid=computer_reference.decode("UTF-8"))
slap_partition._need_modification = 1
partition_dict['_software_release_document'] = {
"software_release": software_instance.getUrlString().decode("UTF-8"),
"computer_guid": compute_node_id
}
partition_dict['_access_status'] = software_instance.getTextAccessStatus()
partition_dict["_need_modification"] = 1
# trick client side, that data has been synchronised already for given
# document
partition_dict["_synced"] = True
parameter_dict = software_instance._asParameterDict()
# software instance has to define an xml parameter
slap_partition._parameter_dict = software_instance._instanceXmlToDict(
partition_dict["_parameter_dict"] = software_instance._instanceXmlToDict(
parameter_dict.pop('xml'))
slap_partition._connection_dict = software_instance._instanceXmlToDict(
partition_dict['_connection_dict'] = software_instance._instanceXmlToDict(
parameter_dict.pop('connection_xml'))
slap_partition._filter_dict = software_instance._instanceXmlToDict(
partition_dict['_filter_dict'] = software_instance._instanceXmlToDict(
parameter_dict.pop('filter_xml'))
slap_partition._instance_guid = parameter_dict.pop('instance_guid')
partition_dict['_instance_guid'] = parameter_dict.pop('instance_guid')
for slave_instance_dict in parameter_dict.get("slave_instance_list", []):
if slave_instance_dict.has_key("connection_xml"):
connection_dict = software_instance._instanceXmlToDict(
......@@ -120,6 +138,6 @@ class SlapOSComputePartitionMixin(object):
if slave_instance_dict.has_key("xml"):
slave_instance_dict.update(software_instance._instanceXmlToDict(
slave_instance_dict.pop("xml")))
slap_partition._parameter_dict.update(parameter_dict)
partition_dict['_parameter_dict'].update(parameter_dict)
return slap_partition
return partition_dict
......@@ -6,12 +6,6 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SlapOSComputePartitionMixin</string> </value>
......@@ -61,28 +55,13 @@
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
......@@ -95,7 +74,7 @@
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
......@@ -104,7 +83,7 @@
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
......
##############################################################################
#
# Copyright (c) 2021 Nexedi SA and Contributors. All Rights Reserved.
#
#
# 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 getSecurityManager
from zExceptions import Unauthorized
from AccessControl.Permissions import access_contents_information
def _assertACI(document):
sm = getSecurityManager()
if sm.checkPermission(access_contents_information,
document):
return document
raise Unauthorized('User %r has no access to %r' % (sm.getUser(), document))
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SlapOSCloud</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>module.erp5.SlapOSCloud</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module 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>
......@@ -35,7 +35,7 @@ import hashlib
from binascii import hexlify
def hashData(data):
return hexlify(hashlib.sha1(data).digest())
return hexlify(hashlib.sha1(json.dumps(data, sort_keys=True)).digest())
class TestSlapOSCloudSlapOSCacheMixin(
SlapOSTestCaseMixin):
......
......@@ -6,12 +6,6 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>testSlapOSCloud</string> </value>
......@@ -61,28 +55,13 @@
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
......@@ -95,7 +74,7 @@
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
......@@ -104,7 +83,7 @@
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
......
module.erp5.SlapOSCloud
\ No newline at end of file
......@@ -15,12 +15,13 @@ import xml.dom.ext
import StringIO
import difflib
import hashlib
import json
from binascii import hexlify
from OFS.Traversable import NotFound
def hashData(data):
return hexlify(hashlib.sha1(data).digest())
return hexlify(hashlib.sha1(json.dumps(data, sort_keys=True)).digest())
class Simulator:
......
......@@ -6,12 +6,6 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>testSlapOSSlapTool</string> </value>
......@@ -55,28 +49,13 @@
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
......@@ -89,7 +68,7 @@
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
......@@ -98,7 +77,7 @@
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
......
......@@ -28,10 +28,9 @@
#
##############################################################################
from AccessControl import ClassSecurityInfo
from AccessControl import Unauthorized
from AccessControl.Permissions import access_contents_information
from AccessControl import getSecurityManager
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
from OFS.Traversable import NotFound
from Products.DCWorkflow.DCWorkflow import ValidationFailed
......@@ -39,10 +38,14 @@ from Products.ERP5Type.Globals import InitializeClass
from Products.ERP5Type.Tool.BaseTool import BaseTool
from Products.ERP5Type import Permissions
from Products.ERP5Type.Cache import CachingMethod
from erp5.component.module.SlapOSCloud import _assertACI
from lxml import etree
try:
from slapos.slap.slap import (
Computer as ComputeNode)
Computer as ComputeNode,
ComputerPartition as SlapComputePartition,
SoftwareInstance as SlapSoftwareInstance,
SoftwareRelease)
from slapos.util import dict2xml, calculate_dict_hash, loads, dumps
except ImportError:
# Do no prevent instance from starting
......@@ -50,6 +53,12 @@ except ImportError:
class ComputeNode:
def __init__(self):
raise ImportError
class SlapComputePartition:
def __init__(self):
raise ImportError
class SoftwareRelease:
def __init__(self):
raise ImportError
def dict2xml(dictionary):
raise ImportError
def calculate_dict_hash(dictionary):
......@@ -58,6 +67,10 @@ except ImportError:
raise ImportError
def dumps(*args):
raise ImportError
class SlapSoftwareInstance:
def __init__(self):
raise ImportError
from zLOG import LOG, INFO
import StringIO
......@@ -111,13 +124,6 @@ def castToStr(dict_kw):
xml_declaration=True, encoding='utf-8')
def _assertACI(document):
sm = getSecurityManager()
if sm.checkPermission(access_contents_information,
document):
return document
raise Unauthorized('User %r has no access to %r' % (sm.getUser(), document))
_MARKER = object()
......@@ -175,7 +181,47 @@ class SlapTool(BaseTool):
validation_state="validated")[0].getObject()
refresh_etag = compute_node._calculateRefreshEtag()
body, etag = compute_node._getComputeNodeInformation(user, refresh_etag)
computer_dict, etag = compute_node._getComputeNodeInformation(user, refresh_etag)
## Horrible code starts
# Convert computer node into SlapComputer
slap_compute_node = ComputeNode(computer_dict["_computer_id"])
slap_compute_node._computer_partition_list = []
slap_compute_node._software_release_list = []
for partition_dict in computer_dict["_computer_partition_list"]:
slap_compute_partition = SlapComputePartition(
partition_id=partition_dict["partition_id"],
computer_id=partition_dict['compute_node_id']
)
slap_compute_partition._requested_state = partition_dict["_requested_state"]
slap_compute_partition._need_modification = partition_dict["_need_modification"]
if partition_dict["_software_release_document"] is not None:
slap_compute_partition._access_status = partition_dict["_access_status"]
slap_compute_partition._parameter_dict = partition_dict["_parameter_dict"]
slap_compute_partition._connection_dict = partition_dict["_connection_dict"]
slap_compute_partition._filter_dict = partition_dict["_filter_dict"]
slap_compute_partition._instance_guid = partition_dict["_instance_guid"]
slap_compute_partition._software_release_document = SoftwareRelease(
software_release=partition_dict["_software_release_document"]["software_release"],
computer_guid=partition_dict["_software_release_document"]["computer_guid"])
else:
slap_compute_partition._software_release_document = None
slap_compute_node._computer_partition_list.append(
slap_compute_partition
)
for software_release_dict in computer_dict['_software_release_list']:
slap_software_release = SoftwareRelease(
software_release=software_release_dict["software_release"],
computer_guid=software_release_dict['computer_guid'])
slap_software_release._requested_state = software_release_dict['_requested_state']
slap_software_release._known_state = software_release_dict['_known_state']
slap_compute_node._software_release_list.append(slap_software_release)
body = dumps(slap_compute_node)
## Horrible code ends
if self.REQUEST.response.getStatus() == 200:
# Keep in cache server for 7 days
......@@ -653,7 +699,25 @@ class SlapTool(BaseTool):
compute_partition_document = self._getComputePartitionDocument(
computer_reference, computer_partition_reference)
slap_compute_partition = compute_partition_document._registerComputePartition()
partition_dict = compute_partition_document._registerComputePartition()
slap_compute_partition = SlapComputePartition(
partition_id=partition_dict["partition_id"],
computer_id=partition_dict['compute_node_id']
)
slap_compute_partition._requested_state = partition_dict["_requested_state"]
slap_compute_partition._need_modification = partition_dict["_need_modification"]
if partition_dict["_software_release_document"] is not None:
slap_compute_partition._parameter_dict = partition_dict["_parameter_dict"]
slap_compute_partition._connection_dict = partition_dict["_connection_dict"]
slap_compute_partition._filter_dict = partition_dict["_filter_dict"]
slap_compute_partition._instance_guid = partition_dict["_instance_guid"]
slap_compute_partition._software_release_document = SoftwareRelease(
software_release=partition_dict["_software_release_document"]["software_release"],
computer_guid=partition_dict["_software_release_document"]["computer_guid"])
slap_compute_partition._synced = partition_dict["_synced"]
else:
slap_compute_partition._software_release_document = None
# Keep in cache server for 7 days
self.REQUEST.response.setStatus(200)
......@@ -923,7 +987,8 @@ class SlapTool(BaseTool):
if not requested_software_instance.getAggregate(portal_type="Compute Partition"):
raise SoftwareInstanceNotReady
else:
return dumps(requested_software_instance._asSoftwareInstance())
return dumps(SlapSoftwareInstance(
**requested_software_instance._asSoftwareInstanceDict()))
@UnrestrictedMethod
def _updateComputePartitionRelatedInstanceList(self, compute_node_id,
......@@ -1003,29 +1068,7 @@ class SlapTool(BaseTool):
compute_partition_id, slave_reference=None):
compute_partition_document = self._getComputePartitionDocument(
compute_node_id, compute_partition_id)
if compute_partition_document.getSlapState() != 'busy':
LOG('SlapTool::_getSoftwareInstanceForComputePartition', INFO,
'Compute partition %s shall be busy, is free' %
compute_partition_document.getRelativeUrl())
raise NotFound, "No software instance found for: %s - %s" % (compute_node_id,
compute_partition_id)
else:
query_kw = {
'validation_state': 'validated',
'portal_type': 'Slave Instance',
'default_aggregate_uid': compute_partition_document.getUid(),
}
if slave_reference is None:
query_kw['portal_type'] = "Software Instance"
else:
query_kw['reference'] = slave_reference
software_instance = _assertACI(self.getPortalObject().portal_catalog.unrestrictedGetResultValue(**query_kw))
if software_instance is None:
raise NotFound, "No software instance found for: %s - %s" % (
compute_node_id, compute_partition_id)
else:
return software_instance
return compute_partition_document._getSoftwareInstance(slave_reference)
@convertToREST
def _softwareReleaseError(self, url, compute_node_id, error_log):
......
......@@ -6,12 +6,6 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SlapTool</string> </value>
......@@ -55,28 +49,13 @@
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
......@@ -89,7 +68,7 @@
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
......@@ -98,7 +77,7 @@
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
......
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