Commit c647aab4 authored by Rafael Monnerat's avatar Rafael Monnerat

slapos_cloud: Introduce SlapOSCacheMixin

   This API replaces the usage of SlapTool code for handling data stored in memcached. It introduces an New API for it at the context of the objects to handle volatile data used on SlapOS context.

   Replace Base_getNewsDict by getAccessStatus

   Drop direct access to memcache, use Cache Plugin instead to load and
set information.
parent 307e1012
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2005-2010 Nexedi SA and Contributors. All Rights Reserved.
# Romain Courteaud <romain@nexedi.com>
#
# 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 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
from DateTime import DateTime
from App.Common import rfc1123_date
from Products.ERP5Type.Cache import DEFAULT_CACHE_SCOPE
import json
class SlapOSCacheMixin:
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
def _getAccessStatusCacheFactory(self):
return self.getPortalObject().portal_caches\
.getRamCacheRoot().get('access_status_data_cache_factory')
def _getAccessStatusPlugin(self):
return self._getAccessStatusCacheFactory().getCachePluginList()[0]
def _getAccessStatusCacheKey(self):
return "%s-ACCESS" % self.getReference()
def _getCachedAccessInfo(self):
if not self.getReference():
return None
try:
entry = self._getAccessStatusPlugin().get(
self._getAccessStatusCacheKey(), DEFAULT_CACHE_SCOPE)
except KeyError:
entry = None
else:
entry = entry.getValue()
return entry
def getAccessStatus(self):
data_json = self._getCachedAccessInfo()
last_modified = rfc1123_date(DateTime())
if data_json is None:
data_dict = {
"user": "SlapOS Master",
'created_at': '%s' % last_modified,
'since': '%s' % last_modified,
'state': "",
"text": "#error no data found for %s" % self.getReference(),
"no_data": 1
}
# Prepare for xml marshalling
#data_dict["text"] = data_dict["text"].decode("UTF-8")
#data_dict["user"] = data_dict["user"].decode("UTF-8")
return data_dict
data_dict = json.loads(data_json)
last_contact = DateTime(data_dict.get('created_at'))
data_dict["no_data_since_15_minutes"] = 0
data_dict["no_data_since_5_minutes"] = 0
if (DateTime() - last_contact) > 0.005:
data_dict["no_data_since_15_minutes"] = 1
data_dict["no_data_since_5_minutes"] = 1
elif (DateTime() - last_contact) > 0.0025:
data_dict["no_data_since_5_minutes"] = 1
return data_dict
def setAccessStatus(self, text, state=""):
user_reference = self.getPortalObject().portal_membership.getAuthenticatedMember()\
.getUserName()
previous = self._getCachedAccessInfo()
created_at = rfc1123_date(DateTime())
since = created_at
status_changed = True
if previous is not None:
previous_json = json.loads(previous)
if text.split(" ")[0] == previous_json.get("text", "").split(" ")[0]:
since = previous_json.get("since",
previous_json.get("created_at", rfc1123_date(DateTime())))
status_changed = False
if state == "":
state = previous_json.get("state", "")
value = json.dumps({
'user': '%s' % user_reference,
'created_at': '%s' % created_at,
'text': '%s' % text,
'since': '%s' % since,
'state': state
})
cache_duration = self._getAccessStatusCacheFactory().cache_duration
self._getAccessStatusPlugin().set(self._getAccessStatusCacheKey(),
DEFAULT_CACHE_SCOPE, value, cache_duration=cache_duration)
return status_changed
def getTextAccessStatus(self):
return self.getAccessStatus()['text']
def getLastAccessDate(self):
data_dict = self.getAccessStatus()
if data_dict.get("no_data") == 1:
return "%s didn't contact the server" % self.getPortalType()
date = DateTime(data_dict['created_at'])
return date.strftime('%Y/%m/%d %H:%M')
#####################
# SlapOS Last Data
#####################
def _getLastDataCacheFactory(self):
return self.getPortalObject().portal_caches\
.getRamCacheRoot().get('last_stored_data_cache_factory')
def _getLastDataPlugin(self):
return self._getLastDataCacheFactory().getCachePluginList()[0]
def setLastData(self, value, key=None):
cache_key = self.getReference()
if key is not None:
cache_key = key
cache_duration = self._getLastDataCacheFactory().cache_duration
self._getLastDataPlugin().set(cache_key, DEFAULT_CACHE_SCOPE,
value, cache_duration=cache_duration)
def getLastData(self, key=None):
cache_key = self.getReference()
if key is not None:
cache_key = key
try:
entry = self._getLastDataPlugin().get(cache_key, DEFAULT_CACHE_SCOPE)
except KeyError:
entry = None
else:
entry = entry.getValue()
return entry
\ No newline at end of file
<?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>SlapOSCacheMixin</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.SlapOSCacheMixin</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>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Cache Factory" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_count</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>cache_duration</string> </key>
<value> <int>86400</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Stores last transmitted values in order to avoid multiple writes on repetitive calls to request and set connection dict.</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>access_status_data_cache_factory</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Cache Factory</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Access Status data Cache Factory</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Length" module="BTrees.Length"/>
</pickle>
<pickle> <int>0</int> </pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Distributed Ram Cache" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>specialise/portal_memcached/default_memcached_plugin</string>
</tuple>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>volatile_cache_plugin</string> </value>
</item>
<item>
<key> <string>int_index</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Distributed Ram Cache</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Volatile Distributed Ram Cache</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -107,7 +107,9 @@
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple/>
<tuple>
<string>SlapOSCacheMixin</string>
</tuple>
</value>
</item>
</dictionary>
......
......@@ -74,7 +74,9 @@
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple/>
<tuple>
<string>SlapOSCacheMixin</string>
</tuple>
</value>
</item>
</dictionary>
......
......@@ -105,7 +105,9 @@
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple/>
<tuple>
<string>SlapOSCacheMixin</string>
</tuple>
</value>
</item>
</dictionary>
......
<type_mixin>
<portal_type id="Compute Node">
<item>SlapOSCacheMixin</item>
</portal_type>
<portal_type id="Compute Partition">
<item>SlapOSCacheMixin</item>
</portal_type>
<portal_type id="Person">
<item>SlapOSCacheMixin</item>
</portal_type>
</type_mixin>
\ No newline at end of file
import json
from DateTime import DateTime
memcached_dict = context.Base_getSlapToolMemcachedDict()
try:
d = memcached_dict[document.getReference()]
except (KeyError, TypeError):
d = {
"user": "SlapOS Master",
"text": "#error no data found for %s" % document.getReference(),
"no_data": 1
}
else:
d = json.loads(d)
last_contact = DateTime(d.get('created_at'))
d["no_data_since_15_minutes"] = 0
d["no_data_since_5_minutes"] = 0
if (DateTime() - last_contact) > 0.005:
d["no_data_since_15_minutes"] = 1
d["no_data_since_5_minutes"] = 1
elif (DateTime() - last_contact) > 0.0025:
d["no_data_since_5_minutes"] = 1
return d
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>document</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_getNewsDict</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
return context.getPortalObject().portal_memcached.getMemcachedDict(
key_prefix='slap_tool',
plugin_path='portal_memcached/default_memcached_plugin')
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_getSlapToolMemcachedDict</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
import json
compute_node = context
portal = context.getPortalObject()
from zExceptions import Unauthorized
......@@ -22,14 +21,11 @@ comment = ''
if can_allocate:
# Check if compute_node has error reported
memcached_dict = context.Base_getSlapToolMemcachedDict()
try:
d = memcached_dict[compute_node.getReference()]
except KeyError:
log_dict = compute_node.getAccessStatus()
if log_dict.get("no_data") == 1:
can_allocate = False
comment = "Compute Node didn't contact the server"
else:
log_dict = json.loads(d)
if '#error' in log_dict.get('text', '#error'):
can_allocate = False
comment = 'Compute Node reported an error'
......
from DateTime import DateTime
import json
memcached_dict = context.Base_getSlapToolMemcachedDict()
try:
d = memcached_dict[context.getReference()]
except KeyError:
return "Compute Node didn't contact the server"
else:
log_dict = json.loads(d)
date = DateTime(log_dict['created_at'])
return date.strftime('%Y/%m/%d %H:%M')
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ComputeNode_getLastContactDate</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -125,7 +125,7 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: context.ComputeNode_getLastContactDate()</string> </value>
<value> <string>python: context.getLastAccessDate()</string> </value>
</item>
</dictionary>
</pickle>
......
from DateTime import DateTime
import json
partition = context
memcached_dict = context.Base_getSlapToolMemcachedDict()
result = ""
date = None
for si in partition.getAggregateRelatedValueList(portal_type=["Software Instance", "Slave Instance"]):
for si in context.getAggregateRelatedValueList(portal_type=["Software Instance"]):
obj = si.getObject()
if obj.getValidationState() != "validated":
......@@ -15,13 +6,6 @@ for si in partition.getAggregateRelatedValueList(portal_type=["Software Instance
if obj.getSlapState() == "destroy_requested":
continue
try:
d = memcached_dict[obj.getReference()]
except KeyError:
result = "#missing no data found for %s" % obj.getReference()
else:
d = json.loads(d)
date = DateTime(d['created_at'])
result = date.strftime('%Y/%m/%d %H:%M')
return obj.getLastAccessDate()
return result
return ""
......@@ -134,7 +134,7 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>cell/ComputeNode_getLastContactDate</string> </value>
<value> <string>cell/getLastAccessDate</string> </value>
</item>
</dictionary>
</pickle>
......
"""Dirty script to return Software Instance state"""
import json
state = context.getSlapState()
has_partition = context.getAggregate(portal_type="Compute Partition")
result = 'Unable to calculate the status...'
if has_partition:
try:
memcached_dict = context.Base_getSlapToolMemcachedDict()
try:
d = memcached_dict[context.getReference()]
except KeyError:
d = context.getAccessStatus()
if d.get("no_data") == 1:
result = context.getSlapStateTitle()
else:
d = json.loads(d)
result = d['text']
if result.startswith('#access '):
result = result[len('#access '):]
except Exception:
raise
# result = 'There is system issue, please try again later.'
else:
if state in ["start_requested", "stop_requested"]:
result = 'Looking for a free partition'
......
from DateTime import DateTime
portal = context.getPortalObject()
import json
error_style = 'background-color: red; display: block; height: 2em; width: 2em; float: left; margin: 5px;'
access_style = 'background-color: green; display: block; height: 2em; width: 2em; float: left; margin: 5px;'
......@@ -14,20 +13,17 @@ software_installation = portal.portal_catalog.getResultValue(
if not software_installation or software_installation.getSlapState() == "destroy_requested":
return '<span" style="%s" title="Information not available"></a>' % error_style
memcached_dict = context.Base_getSlapToolMemcachedDict()
try:
d = memcached_dict[software_installation.getReference()]
except KeyError:
d = software_installation.getAccessStatus()
if d.get("no_data") == 1:
return "<a href='%s' style='%s'></a>" % (software_installation.getRelativeUrl(),
error_style)
else:
d = json.loads(d)
result = d['text']
date = DateTime(d['created_at'])
limit_date = DateTime() - 0.084
if result.startswith('#error ') or (date - limit_date) < 0:
result = d['text']
date = DateTime(d['created_at'])
limit_date = DateTime() - 0.084
if result.startswith('#error ') or (date - limit_date) < 0:
access_style = error_style
return "<a href='%s' style='%s' title='%s at %s'></a>" % (
return "<a href='%s' style='%s' title='%s at %s'></a>" % (
software_installation.getRelativeUrl(),
access_style, result, d['created_at'])
......@@ -7,12 +7,10 @@
from erp5.component.test.testSlapOSCloudSecurityGroup import TestSlapOSSecurityMixin
from erp5.component.test.SlapOSTestCaseMixin import changeSkin
import json
import re
import xml_marshaller
from AccessControl.SecurityManagement import getSecurityManager, \
setSecurityManager
from DateTime import DateTime
class DefaultScenarioMixin(TestSlapOSSecurityMixin):
......@@ -103,14 +101,7 @@ class DefaultScenarioMixin(TestSlapOSSecurityMixin):
return []
def setAccessToMemcached(self, agent):
memcached_dict = self.portal.portal_memcached.getMemcachedDict(
key_prefix='slap_tool',
plugin_path='portal_memcached/default_memcached_plugin')
access_date = DateTime()
memcached_dict[agent.getReference()] = json.dumps(
{"created_at":"%s" % access_date, "text": "#access "}
)
agent.setAccessStatus("#access ")
def requestComputeNode(self, title):
requestXml = self.portal.portal_slap.requestComputer(title)
......
......@@ -2,12 +2,10 @@
import transaction
from erp5.component.test.SlapOSTestCaseMixin import SlapOSTestCaseMixin
from Products.ERP5Type.tests.utils import createZODBPythonScript
import json
import time
from zExceptions import Unauthorized
from DateTime import DateTime
from erp5.component.module.DateUtils import addToDate
from App.Common import rfc1123_date
class TestSlapOSCoreSlapOSAssertInstanceTreeSuccessorAlarm(
SlapOSTestCaseMixin):
......@@ -443,13 +441,7 @@ class TestSlapOSUpdateComputeNodeCapacityScopeAlarm(SlapOSTestCaseMixin):
)
self.compute_node.edit(capacity_scope='open')
self.compute_node.validate()
memcached_dict = self.portal.portal_memcached.getMemcachedDict(
key_prefix='slap_tool',
plugin_path='portal_memcached/default_memcached_plugin')
memcached_dict[self.compute_node.getReference()] = json.dumps({
'text': '#access ok',
'created_at': rfc1123_date(DateTime())
})
self.compute_node.setAccessStatus("#access ok")
transaction.commit()
def test_ComputeNode_checkAndUpdateCapacityScope(self):
......@@ -517,14 +509,12 @@ class TestSlapOSUpdateComputeNodeCapacityScopeAlarm(SlapOSTestCaseMixin):
self.compute_node.getCapacityQuantity())
def test_ComputeNode_checkAndUpdateCapacityScope_with_old_access(self):
memcached_dict = self.portal.portal_memcached.getMemcachedDict(
key_prefix='slap_tool',
plugin_path='portal_memcached/default_memcached_plugin')
memcached_dict[self.compute_node.getReference()] = json.dumps({
'text': '#access ok',
'created_at': rfc1123_date(addToDate(DateTime(),
to_add={'minute': -11}))
})
try:
self.pinDateTime(addToDate(DateTime(),to_add={'minute': -11}))
self.compute_node.setAccessStatus("#access ok")
finally:
self.unpinDateTime()
self.compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('close', self.compute_node.getCapacityScope())
self.assertEqual("Compute Node didn't contact for more than 10 minutes",
......@@ -552,24 +542,14 @@ class TestSlapOSUpdateComputeNodeCapacityScopeAlarm(SlapOSTestCaseMixin):
self.assertEqual('open', self.compute_node.getCapacityScope())
def test_ComputeNode_checkAndUpdateCapacityScope_with_error(self):
memcached_dict = self.portal.portal_memcached.getMemcachedDict(
key_prefix='slap_tool',
plugin_path='portal_memcached/default_memcached_plugin')
memcached_dict[self.compute_node.getReference()] = json.dumps({
'text': '#error not ok'
})
self.compute_node.setAccessStatus('#error not ok')
self.compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('close', self.compute_node.getCapacityScope())
self.assertEqual("Compute Node reported an error",
self.compute_node.workflow_history['edit_workflow'][-1]['comment'])
def test_ComputeNode_checkAndUpdateCapacityScope_with_error_non_public(self):
memcached_dict = self.portal.portal_memcached.getMemcachedDict(
key_prefix='slap_tool',
plugin_path='portal_memcached/default_memcached_plugin')
memcached_dict[self.compute_node.getReference()] = json.dumps({
'text': '#error not ok'
})
self.compute_node.setAccessStatus('#error not ok')
self.compute_node.edit(allocation_scope='open/personal')
self.compute_node.ComputeNode_checkAndUpdateCapacityScope()
self.assertEqual('open', self.compute_node.getCapacityScope())
......
mixin.erp5.SlapOSCacheMixin
\ No newline at end of file
acl_users/slapos_access_token_extraction
acl_users/slapos_machine
acl_users/slapos_shadow
computer_model_module/template_computer_model
computer_model_module/template_computer_model/**
compute_node_module/template_compute_node
compute_node_module/template_compute_node/**
computer_model_module/template_computer_model
computer_model_module/template_computer_model/**
instance_tree_module/template_instance_tree
person_module/template_member
person_module/template_member/**
......@@ -17,6 +17,10 @@ portal_alarms/slapos_garbage_collect_destroyed_root_tree
portal_alarms/slapos_garbage_collect_non_allocated_root_tree
portal_alarms/slapos_stop_collect_instance
portal_alarms/slapos_update_compute_node_capacity_scope
portal_caches/access_status_data_cache_factory
portal_caches/access_status_data_cache_factory/volatile_cache_plugin
portal_caches/last_stored_data_cache_factory
portal_caches/last_stored_data_cache_factory/volatile_cache_plugin
product_module/compute_node
software_installation_module/template_software_installation
software_instance_module/template_slave_instance
......
Compute Node | SlapOSCacheMixin
Compute Partition | SlapOSCacheMixin
Person | SlapOSCacheMixin
\ No newline at end of file
from DateTime import DateTime
import json
portal = context.getPortalObject()
from Products.ERP5Type.Document import newTempBase
......@@ -19,26 +18,11 @@ show_all = False
if "show_all" in kw:
show_all = kw.pop("omit_zero_ticket")
memcached_dict = context.getPortalObject().portal_memcached.getMemcachedDict(
key_prefix='slap_tool',
plugin_path='portal_memcached/default_memcached_plugin')
def checkForError(reference):
try:
d = memcached_dict[reference]
except KeyError:
return 1
d = json.loads(d)
result = d['text']
#last_contact = DateTime(d.get('created_at'))
# Optimise by checking memcache information first.
result = context.getAccessStatusText()
if result.startswith('#error '):
return 1
for compute_node in portal.portal_catalog(
default_allocation_scope_uid = [personal_category_uid, public_category_uid, friend_category_uid],
select_list={"reference": None},
......
from DateTime import DateTime
import json
portal = context.getPortalObject()
if portal.ERP5Site_isSupportRequestCreationClosed():
......@@ -22,7 +20,6 @@ compute_node_reference = context.getReference()
compute_node_title = context.getTitle()
should_notify = True
memcached_dict = context.Base_getSlapToolMemcachedDict()
tolerance = DateTime()-0.5
for software_installation in software_installation_list:
should_notify = False
......@@ -31,9 +28,12 @@ for software_installation in software_installation_list:
continue
reference = software_installation.getReference()
try:
d = memcached_dict[reference]
d = json.loads(d)
d = software_installation.getAccessStatus()
if d.get("no_data", None) == 1:
ticket_title = "[MONITORING] No information for %s on %s" % (reference, compute_node_reference)
description = "The software release %s did not started to build on %s since %s" % \
(software_installation.getUrlString(), compute_node_title, software_installation.getCreationDate())
else:
last_contact = DateTime(d.get('created_at'))
if d.get("text").startswith("building"):
should_notify = True
......@@ -49,13 +49,7 @@ for software_installation in software_installation_list:
description = "The software release %s is failing to build for too long on %s, started on %s" % \
(software_installation.getUrlString(), compute_node_title, software_installation.getCreationDate())
except KeyError:
ticket_title = "[MONITORING] No information for %s on %s" % (reference, compute_node_reference)
description = "The software release %s did not started to build on %s since %s" % \
(software_installation.getUrlString(), compute_node_title, software_installation.getCreationDate())
if should_notify:
support_request = context.Base_generateSupportRequestForSlapOS(
ticket_title,
description,
......
from DateTime import DateTime
import json
portal = context.getPortalObject()
if portal.ERP5Site_isSupportRequestCreationClosed():
......@@ -18,50 +16,49 @@ reference = context.getReference()
compute_node_title = context.getTitle()
ticket_title = "[MONITORING] Lost contact with compute_node %s" % reference
description = ""
should_notify = True
last_contact = "No Contact Information"
memcached_dict = context.Base_getSlapToolMemcachedDict()
try:
d = memcached_dict[reference]
d = json.loads(d)
d = context.getAccessStatus()
# Ignore if data isn't present.
if d.get("no_data") == 1:
description = "The Compute Node %s (%s) has not contacted the server (No Contact Information)" % (
compute_node_title, reference)
else:
last_contact = DateTime(d.get('created_at'))
if (DateTime() - last_contact) > 0.01:
description = "The Compute Node %s (%s) has not contacted the server for more than 30 minutes" \
"(last contact date: %s)" % (compute_node_title, reference, last_contact)
else:
should_notify = False
except KeyError:
description = "The Compute Node %s (%s) has not contacted the server (No Contact Information)" % (
compute_node_title, reference)
# Nothing to notify.
return
if should_notify:
support_request = context.Base_generateSupportRequestForSlapOS(
support_request = context.Base_generateSupportRequestForSlapOS(
ticket_title,
description,
context.getRelativeUrl()
)
)
person = context.getSourceAdministrationValue(portal_type="Person")
if not person:
person = context.getSourceAdministrationValue(portal_type="Person")
if not person:
return support_request
# Send Notification message
notification_reference = 'slapos-crm-compute_node_check_state.notification'
notification_message = portal.portal_notifications.getDocumentValue(
# Send Notification message
notification_reference = 'slapos-crm-compute_node_check_state.notification'
notification_message = portal.portal_notifications.getDocumentValue(
reference=notification_reference)
if notification_message is None:
if notification_message is None:
message = """%s""" % description
else:
else:
mapping_dict = {'compute_node_title':context.getTitle(),
'compute_node_id':reference,
'last_contact':last_contact}
message = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict':mapping_dict})
support_request.SupportRequest_trySendNotificationMessage(
support_request.SupportRequest_trySendNotificationMessage(
ticket_title,
message, person.getRelativeUrl())
return support_request
return support_request
import json
portal = context.getPortalObject()
compute_node = context
now_date = DateTime()
......@@ -7,20 +6,16 @@ if (now_date - compute_node.getCreationDate()) < maximum_days:
# This compute_node was created recently skip
return True
memcached_dict = context.Base_getSlapToolMemcachedDict()
# Check if there is some information in memcached
try:
d = memcached_dict[compute_node.getReference()]
except KeyError:
message_dict = context.getAccessStatus()
# Ignore if data isn't present.
if message_dict.get("no_data", None) == 1:
message_dict = {}
else:
message_dict = json.loads(d)
if message_dict.has_key('created_at'):
contact_date = DateTime(message_dict.get('created_at').encode('utf-8'))
return (now_date - contact_date) < maximum_days
# If no memcached, check in consumption report
# If no access status information, check in consumption report
for sale_packing_list in portal.portal_catalog(
portal_type="Sale Packing List Line",
simulation_state="delivered",
......
from DateTime import DateTime
import json
memcached_dict = context.Base_getSlapToolMemcachedDict()
try:
d = memcached_dict[context.getReference()]
except KeyError:
# Information not available
return None
d = context.getAccessStatus()
# Ignore if data isn't present.
if d.get("no_data", None) == 1:
return
d = json.loads(d)
result = d['text']
last_contact = DateTime(d.get('created_at'))
# Optimise by checking memcache information first.
if result.startswith('#error '):
return last_contact
return None
if d['text'].startswith('#error '):
return DateTime(d.get('created_at'))
from DateTime import DateTime
import json
if context.getAggregateValue(portal_type="Compute Partition") is not None:
memcached_dict = context.Base_getSlapToolMemcachedDict()
try:
d = memcached_dict[context.getReference()]
except KeyError:
d = context.getAccessStatus()
# Ignore if data isn't present.
if d.get("no_data", None) == 1:
if include_message:
return "Not possible to connect"
return
d = json.loads(d)
result = d['text']
last_contact = DateTime(d.get('created_at'))
since = DateTime(d.get('since'))
# Optimise by checking memcache information first.
if result.startswith('#error '):
if ((DateTime()-since)*24*60) > tolerance:
if include_created_at and not include_since:
......@@ -24,7 +20,6 @@ if context.getAggregateValue(portal_type="Compute Partition") is not None:
return result, last_contact, since
return result
# XXX time limit of 48 hours for run at least once.
if include_message and include_created_at and not include_since:
return result, last_contact
elif include_message and include_created_at and include_since:
......
......@@ -6,7 +6,6 @@
#
from DateTime import DateTime
import json
if context.getSimulationState() == "invalidated":
return "Closed Ticket"
......@@ -18,21 +17,19 @@ if document is None:
aggregate_portal_type = document.getPortalType()
memcached_dict = context.Base_getSlapToolMemcachedDict()
if aggregate_portal_type == "Compute Node":
if document.getMonitorScope() == "disabled":
return "Monitor is disabled to the related %s." % document.getPortalType()
try:
d = memcached_dict[document.getReference()]
d = json.loads(d)
d = context.getAccessStatus()
if d.get("no_data", None) == 1:
return "No Contact Information"
last_contact = DateTime(d.get('created_at'))
if (DateTime() - last_contact) < 0.01:
return "All OK, latest contact: %s " % last_contact
else:
return "Problem, latest contact: %s" % last_contact
except KeyError:
return "No Contact Information"
if aggregate_portal_type == "Software Installation":
compute_node_title = document.getAggregateTitle()
......@@ -42,9 +39,11 @@ if aggregate_portal_type == "Software Installation":
if document.getSlapState() not in ["start_requested", "stop_requested"]:
return "Software Installation is Destroyed."
try:
d = memcached_dict[document.getReference()]
d = json.loads(d)
d = context.getAccessStatus()
if d.get("no_data", None) == 1:
return "The software release %s did not started to build on %s since %s" % \
(document.getUrlString(), compute_node_title, document.getCreationDate())
last_contact = DateTime(d.get('created_at'))
if d.get("text").startswith("building"):
return "The software release %s is building for mode them 12 hours on %s, started on %s" % \
......@@ -55,11 +54,6 @@ if aggregate_portal_type == "Software Installation":
return "The software release %s is failing to build for too long on %s, started on %s" % \
(document.getUrlString(), compute_node_title, document.getCreationDate())
except KeyError:
return "The software release %s did not started to build on %s since %s" % \
(document.getUrlString(), compute_node_title, document.getCreationDate())
if aggregate_portal_type == "Instance Tree":
if document.getMonitorScope() == "disabled":
return "Monitor is disabled to the related %s." % document.getPortalType()
......
......@@ -25,6 +25,9 @@ import transaction
from erp5.component.test.SlapOSTestCaseMixin import \
SlapOSTestCaseMixin,SlapOSTestCaseMixinWithAbort, simulate
from DateTime import DateTime
from App.Common import rfc1123_date
from Products.ERP5Type.Cache import DEFAULT_CACHE_SCOPE
from Products.ERP5Type.tests.utils import createZODBPythonScript
import json
......@@ -826,13 +829,7 @@ class TestComputeNode_hasContactedRecently(SlapOSTestCaseMixinWithAbort):
@simulate('ComputeNode_getCreationDate', '*args, **kwargs','return DateTime() - 32')
def test_ComputeNode_hasContactedRecently_memcached(self):
compute_node = self._makeComputeNode()[0]
memcached_dict = self.portal.portal_memcached.getMemcachedDict(
key_prefix='slap_tool',
plugin_path='portal_memcached/default_memcached_plugin')
memcached_dict[compute_node.getReference()] = json.dumps({
"created_at": DateTime().strftime("%Y/%m/%d %H:%M")
})
compute_node.setAccessStatus("#access ")
self.tic()
compute_node.getCreationDate = self.portal.ComputeNode_getCreationDate
......@@ -843,13 +840,12 @@ class TestComputeNode_hasContactedRecently(SlapOSTestCaseMixinWithAbort):
@simulate('ComputeNode_getCreationDate', '*args, **kwargs','return DateTime() - 32')
def test_ComputeNode_hasContactedRecently_memcached_oudated_no_spl(self):
compute_node = self._makeComputeNode()[0]
memcached_dict = self.portal.portal_memcached.getMemcachedDict(
key_prefix='slap_tool',
plugin_path='portal_memcached/default_memcached_plugin')
try:
self.pinDateTime(DateTime()-32)
compute_node.setAccessStatus("#access ")
finally:
self.unpinDateTime()
memcached_dict[compute_node.getReference()] = json.dumps({
"created_at": (DateTime() - 32).strftime("%Y/%m/%d %H:%M")
})
self.tic()
compute_node.getCreationDate = self.portal.ComputeNode_getCreationDate
......@@ -860,13 +856,12 @@ class TestComputeNode_hasContactedRecently(SlapOSTestCaseMixinWithAbort):
@simulate('ComputeNode_getCreationDate', '*args, **kwargs','return DateTime() - 32')
def test_ComputeNode_hasContactedRecently_memcached_oudated_with_spl(self):
compute_node = self._makeComputeNode()[0]
memcached_dict = self.portal.portal_memcached.getMemcachedDict(
key_prefix='slap_tool',
plugin_path='portal_memcached/default_memcached_plugin')
try:
self.pinDateTime(DateTime()-32)
compute_node.setAccessStatus("#access ")
finally:
self.unpinDateTime()
memcached_dict[compute_node.getReference()] = json.dumps({
"created_at": (DateTime() - 32).strftime("%Y/%m/%d %H:%M")
})
self.createSPL(compute_node)
self.tic()
......@@ -1224,13 +1219,11 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin):
@simulate('ERP5Site_isSupportRequestCreationClosed', '*args, **kwargs','return 0')
def test_ComputeNode_checkState_call_support_request(self):
compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0]
memcached_dict = self.portal.portal_memcached.getMemcachedDict(
key_prefix='slap_tool',
plugin_path='portal_memcached/default_memcached_plugin')
memcached_dict[compute_node.getReference()] = json.dumps(
{"created_at":"%s" % (DateTime() - 1.1)}
)
try:
self.pinDateTime(DateTime()-1.1)
compute_node.setAccessStatus("#access ")
finally:
self.unpinDateTime()
self._simulateBase_generateSupportRequestForSlapOS()
support_request = self._makeSupportRequest()
......@@ -1279,14 +1272,11 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin):
compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0]
person = compute_node.getSourceAdministrationValue()
memcached_dict = self.portal.portal_memcached.getMemcachedDict(
key_prefix='slap_tool',
plugin_path='portal_memcached/default_memcached_plugin')
memcached_dict[compute_node.getReference()] = json.dumps(
{"created_at":"%s" % (DateTime() - 0.1)}
)
try:
self.pinDateTime(DateTime()-1.1)
compute_node.setAccessStatus("#access ")
finally:
self.unpinDateTime()
self.portal.REQUEST['test_ComputeNode_checkState_notify'] = \
self._makeNotificationMessage(compute_node.getReference())
......@@ -1524,14 +1514,7 @@ class TestSlapOSHasError(SlapOSTestCaseMixin):
self._makeComputeNode()
self._makeComputePartitionList()
memcached_dict = self.portal.portal_memcached.getMemcachedDict(
key_prefix='slap_tool',
plugin_path='portal_memcached/default_memcached_plugin')
error_date = DateTime()
memcached_dict[instance.getReference()] = json.dumps(
{"created_at":"%s" % error_date, "text": "#error "}
)
instance.setAccessStatus("#error ")
self.assertEqual(instance.SoftwareInstance_hasReportedError(), None)
......@@ -1539,10 +1522,7 @@ class TestSlapOSHasError(SlapOSTestCaseMixin):
self.assertEqual(str(instance.SoftwareInstance_hasReportedError()), '#error ')
memcached_dict[instance.getReference()] = json.dumps(
{"created_at":"%s" % error_date, "text": "#access "}
)
instance.setAccessStatus("#access ")
self.assertEqual(instance.SoftwareInstance_hasReportedError(), None)
def test_SoftwareInstallation_hasReportedError(self):
......@@ -1552,22 +1532,19 @@ class TestSlapOSHasError(SlapOSTestCaseMixin):
software_release.getUrlString()
)
memcached_dict = self.portal.portal_memcached.getMemcachedDict(
key_prefix='slap_tool',
plugin_path='portal_memcached/default_memcached_plugin')
self.assertEqual(installation.SoftwareInstallation_hasReportedError(), None)
error_date = DateTime()
memcached_dict[installation.getReference()] = json.dumps(
{"created_at":"%s" % error_date, "text": "#error "}
)
self.assertEqual(installation.SoftwareInstallation_hasReportedError(), error_date)
try:
self.pinDateTime(error_date)
installation.setAccessStatus("#error ")
finally:
self.unpinDateTime()
memcached_dict[installation.getReference()] = json.dumps(
{"created_at":"%s" % error_date, "text": "#building "}
)
self.assertEqual(
rfc1123_date(installation.SoftwareInstallation_hasReportedError()),
rfc1123_date(error_date))
installation.setAccessStatus("#building ")
self.assertEqual(installation.SoftwareInstallation_hasReportedError(), None)
......@@ -1600,14 +1577,13 @@ class TestSlapOSHasError(SlapOSTestCaseMixin):
self._makeComputePartitionList()
instance.setAggregateValue(self.compute_node.partition1)
memcached_dict = self.portal.portal_memcached.getMemcachedDict(
key_prefix='slap_tool',
plugin_path='portal_memcached/default_memcached_plugin')
error_date = DateTime()
memcached_dict[instance.getReference()] = json.dumps(
value = json.dumps(
{"created_at":"%s" % error_date, "text": "#error ", "since": "%s" % (error_date - 2)}
)
cache_duration = instance._getAccessStatusCacheFactory().cache_duration
instance._getAccessStatusPlugin().set(instance._getAccessStatusCacheKey(),
DEFAULT_CACHE_SCOPE, value, cache_duration=cache_duration)
self.assertEqual(
'Visited by InstanceTree_createSupportRequestEvent %s %s' % \
......@@ -1615,9 +1591,7 @@ class TestSlapOSHasError(SlapOSTestCaseMixin):
"slapos-crm-instance-tree-instance-state.notification"),
instance_tree.InstanceTree_checkSoftwareInstanceState())
memcached_dict[instance.getReference()] = json.dumps(
{"created_at":"%s" % error_date, "text": "#access "}
)
instance.setAccessStatus("#access ")
self.assertEqual(None,
instance_tree.InstanceTree_checkSoftwareInstanceState())
......@@ -1720,13 +1694,7 @@ class TestSlapOSHasError(SlapOSTestCaseMixin):
instance.requestInstance(**kw)
self.tic()
memcached_dict = self.portal.portal_memcached.getMemcachedDict(
key_prefix='slap_tool',
plugin_path='portal_memcached/default_memcached_plugin')
error_date = DateTime()
memcached_dict[instance.getReference()] = json.dumps(
{"created_at":"%s" % error_date, "text": "#access "}
)
instance.setAccessStatus("#access ")
self.assertEqual(
'Visited by InstanceTree_createSupportRequestEvent %s %s' % \
......@@ -1761,15 +1729,7 @@ class TestSlapOSHasError(SlapOSTestCaseMixin):
self._makeComputePartitionList()
instance.setAggregateValue(self.compute_node.partition1)
memcached_dict = self.portal.portal_memcached.getMemcachedDict(
key_prefix='slap_tool',
plugin_path='portal_memcached/default_memcached_plugin')
error_date = DateTime()
memcached_dict[instance.getReference()] = json.dumps(
{"created_at":"%s" % error_date, "text": "#error "}
)
instance.setAccessStatus("#error ")
self.assertEqual(
None,
instance_tree.InstanceTree_checkSoftwareInstanceState())
......
......@@ -3,12 +3,12 @@ if REQUEST is not None:
raise Unauthorized
def get_compute_partition_dict(reference):
compute_node_dict = context.Base_getNewsDict(context)
compute_node_dict = context.getAccessStatus()
compute_partition_dict = { }
for compute_partition in context.objectValues(portal_type="Compute Partition"):
software_instance = compute_partition.getAggregateRelatedValue(portal_type="Software Instance")
if software_instance is not None:
compute_partition_dict[compute_partition.getTitle()] = context.Base_getNewsDict(software_instance)
compute_partition_dict[compute_partition.getTitle()] = software_instance.getAccessStatus()
return {"compute_node": compute_node_dict,
"partition": compute_partition_dict}
......
......@@ -2,4 +2,4 @@ from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
return context.Base_getNewsDict(context)
return context.getAccessStatus()
......@@ -25,4 +25,4 @@ if portal_type == "Software Instance" and slap_state == "destroy_requested":
"is_destroyed": 1
}
return context.Base_getNewsDict(context)
return context.getAccessStatus()
......@@ -3,10 +3,7 @@ if REQUEST is not None:
raise Unauthorized
from DateTime import DateTime
import json
slap_state = context.getSlapState()
_translate = context.Base_translateString
NOT_ALLOCATED = _translate("Searching for partition")
......@@ -26,13 +23,10 @@ if compute_partition is not None:
if instance.getPortalType() == "Slave Instance":
instance = compute_partition.getAggregateRelatedValue(portal_type="Software Instance")
memcached_dict = instance.Base_getSlapToolMemcachedDict()
try:
d = memcached_dict[instance.getReference()]
except KeyError:
d = instance.getAccessStatus()
if d.get("no_data") == 1:
return _translate(instance.getSlapStateTitle())
d = json.loads(d)
result = d['text']
reported_state = d.get("state", "")
if reported_state == "":
......
......@@ -24,6 +24,7 @@ from erp5.component.test.SlapOSTestCaseMixin import \
SlapOSTestCaseMixinWithAbort, simulate
from zExceptions import Unauthorized
from App.Common import rfc1123_date
from Products.ERP5Type.Cache import DEFAULT_CACHE_SCOPE
from DateTime import DateTime
import json
......@@ -38,10 +39,18 @@ class TestSlapOSHalJsonStyleMixin(SlapOSTestCaseMixinWithAbort):
maxDiff = None
def afterSetUp(self):
SlapOSTestCaseMixinWithAbort.afterSetUp(self)
self.created_at = rfc1123_date(DateTime())
d = DateTime()
self.pinDateTime(d)
self.created_at = rfc1123_date(d)
self.changeSkin('Hal')
def _logFakeAccess(self, reference, text="#access OK", state='start_requested'):
def beforeTearDown(self):
SlapOSTestCaseMixinWithAbort.beforeTearDown(self)
self.unpinDateTime()
def _logFakeAccess(self, document, text="#access OK", state='start_requested'):
value = json.dumps({
'user': 'SlapOS Master',
'created_at': '%s' % self.created_at,
......@@ -49,8 +58,9 @@ class TestSlapOSHalJsonStyleMixin(SlapOSTestCaseMixinWithAbort):
'since': '%s' % self.created_at,
'state': state
})
memcached_dict = self.portal.Base_getSlapToolMemcachedDict()
memcached_dict[reference] = value
cache_duration = document._getAccessStatusCacheFactory().cache_duration
document._getAccessStatusPlugin().set(document._getAccessStatusCacheKey(),
DEFAULT_CACHE_SCOPE, value, cache_duration=cache_duration)
def _makePerson(self, **kw):
person_user = self.makePerson(**kw)
......@@ -71,8 +81,8 @@ class TestSlapOSHalJsonStyleMixin(SlapOSTestCaseMixinWithAbort):
.template_software_instance.Base_createCloneDocument(batch_mode=1)
instance.edit(reference="TESTSOFTINST-%s" % instance.getId())
instance.validate()
self.changeSkin('Hal')
self.tic()
self.changeSkin('Hal')
return instance
def _makeSlaveInstance(self):
......@@ -80,6 +90,7 @@ class TestSlapOSHalJsonStyleMixin(SlapOSTestCaseMixinWithAbort):
.template_slave_instance.Base_createCloneDocument(batch_mode=1)
instance.validate()
self.tic()
self.changeSkin('Hal')
return instance
def _makeComputeNode(self, owner=None, allocation_scope='open/public'):
......@@ -179,7 +190,10 @@ class TestInstanceTree_getNewsDict(TestSlapOSHalJsonStyleMixin):
self.tic()
self.changeSkin('Hal')
news_dict = instance_tree.InstanceTree_getNewsDict()
expected_news_dict = {'instance': [{'no_data': 1,
expected_news_dict = {'instance': [{'created_at': self.created_at,
'no_data': 1,
'since': self.created_at,
'state': '',
'text': '#error no data found for %s' % instance.getReference(),
'user': 'SlapOS Master'}]}
self.assertEqual(news_dict, expected_news_dict)
......@@ -208,10 +222,16 @@ class TestInstanceTree_getNewsDict(TestSlapOSHalJsonStyleMixin):
self.tic()
self.changeSkin('Hal')
news_dict = instance_tree.InstanceTree_getNewsDict()
expected_news_dict = {'instance': [{'no_data': 1,
expected_news_dict = {'instance': [{'created_at': self.created_at,
'no_data': 1,
'since': self.created_at,
'state': '',
'text': '#error no data found for %s' % instance0.getReference(),
'user': 'SlapOS Master'},
{'no_data': 1,
{'created_at': self.created_at,
'no_data': 1,
'since': self.created_at,
'state': '',
'text': '#error no data found for %s' % instance.getReference(),
'user': 'SlapOS Master'}]}
self.assertEqual(news_dict["instance"], expected_news_dict["instance"])
......@@ -222,15 +242,15 @@ class TestSoftwareInstance_getNewsDict(TestSlapOSHalJsonStyleMixin):
def test(self):
instance = self._makeInstance()
self._logFakeAccess(instance.getReference())
self._logFakeAccess(instance)
news_dict = instance.SoftwareInstance_getNewsDict()
expected_news_dict = {u'created_at': self.created_at,
expected_news_dict = {'created_at': self.created_at,
'no_data_since_15_minutes': 0,
'no_data_since_5_minutes': 0,
'since': self.created_at,
'state': 'start_requested',
'text': u'#access OK',
u'user': u'SlapOS Master'}
'text': '#access OK',
'user': 'SlapOS Master'}
self.assertEqual(news_dict, expected_news_dict)
# Ensure it don't raise error when converting to JSON
json.dumps(news_dict)
......@@ -238,8 +258,13 @@ class TestSoftwareInstance_getNewsDict(TestSlapOSHalJsonStyleMixin):
def test_no_data(self):
instance = self._makeInstance()
self.changeSkin('Hal')
news_dict = instance.SoftwareInstance_getNewsDict()
expected_news_dict = {'no_data': 1,
expected_news_dict = {'created_at': self.created_at,
'no_data': 1,
'since': self.created_at,
'state': '',
'text': '#error no data found for %s' % instance.getReference(),
'user': 'SlapOS Master'}
self.assertEqual(news_dict, expected_news_dict)
......@@ -286,51 +311,51 @@ class TestSoftwareInstallation_getNewsDict(TestSlapOSHalJsonStyleMixin):
def test(self):
installation = self._makeSoftwareInstallation()
self._logFakeAccess(installation.getReference())
self._logFakeAccess(installation)
news_dict = installation.SoftwareInstallation_getNewsDict()
expected_news_dict = {u'created_at': self.created_at,
expected_news_dict = {'created_at': self.created_at,
'no_data_since_15_minutes': 0,
'no_data_since_5_minutes': 0,
'since': self.created_at,
'state': 'start_requested',
'text': u'#access OK',
u'user': u'SlapOS Master'}
'text': '#access OK',
'user': 'SlapOS Master'}
self.assertEqual(news_dict, expected_news_dict)
# Ensure it don't raise error when converting to JSON
json.dumps(news_dict)
def test_stopped(self):
installation = self._makeSoftwareInstallation()
self._logFakeAccess(installation.getReference(),
self._logFakeAccess(installation,
state='stop_requested')
news_dict = installation.SoftwareInstallation_getNewsDict()
installation.getSlapState = fakeStopRequestedSlapState
expected_news_dict = {u'created_at': self.created_at,
expected_news_dict = {'created_at': self.created_at,
'no_data_since_15_minutes': 0,
'no_data_since_5_minutes': 0,
'since': self.created_at,
'state': 'stop_requested',
'text': u'#access OK',
u'user': u'SlapOS Master'}
'text': '#access OK',
'user': 'SlapOS Master'}
self.assertEqual(news_dict, expected_news_dict)
# Ensure it don't raise error when converting to JSON
json.dumps(news_dict)
def test_destroyed(self):
installation = self._makeSoftwareInstallation()
self._logFakeAccess(installation.getReference(),
self._logFakeAccess(installation,
state='destroy_requested')
news_dict = installation.SoftwareInstallation_getNewsDict()
installation.getSlapState = fakeDestroyRequestedSlapState
expected_news_dict = {u'created_at': self.created_at,
expected_news_dict = {'created_at': self.created_at,
'no_data_since_15_minutes': 0,
'no_data_since_5_minutes': 0,
'since': self.created_at,
'state': 'destroy_requested',
'text': u'#access OK',
u'user': u'SlapOS Master'}
'text': '#access OK',
'user': 'SlapOS Master'}
self.assertEqual(news_dict, expected_news_dict)
# Ensure it don't raise error when converting to JSON
json.dumps(news_dict)
......@@ -338,7 +363,10 @@ class TestSoftwareInstallation_getNewsDict(TestSlapOSHalJsonStyleMixin):
def test_no_data(self):
installation = self._makeSoftwareInstallation()
news_dict = installation.SoftwareInstallation_getNewsDict()
expected_news_dict = {'no_data': 1,
expected_news_dict = {'created_at': self.created_at,
'no_data': 1,
'since': self.created_at,
'state': '',
'text': '#error no data found for %s' % installation.getReference(),
'user': 'SlapOS Master'}
self.assertEqual(news_dict, expected_news_dict)
......@@ -349,16 +377,16 @@ class TestComputeNode_getNewsDict(TestSlapOSHalJsonStyleMixin):
def test(self):
compute_node = self._makeComputeNode()
self._logFakeAccess(compute_node.getReference())
self._logFakeAccess(compute_node)
news_dict = compute_node.ComputeNode_getNewsDict()
expected_news_dict = {'compute_node':
{u'created_at': self.created_at,
{'created_at': self.created_at,
'no_data_since_15_minutes': 0,
'no_data_since_5_minutes': 0,
'since': self.created_at,
'state': 'start_requested',
'text': u'#access OK',
u'user': u'SlapOS Master'},
'text': '#access OK',
'user': 'SlapOS Master'},
'partition': {}
}
self.assertEqual(news_dict, expected_news_dict)
......@@ -367,7 +395,7 @@ class TestComputeNode_getNewsDict(TestSlapOSHalJsonStyleMixin):
def test_stopped(self):
compute_node = self._makeComputeNode()
self._logFakeAccess(compute_node.getReference(),
self._logFakeAccess(compute_node,
state='stop_requested')
news_dict = compute_node.ComputeNode_getNewsDict()
compute_node.getSlapState = fakeStopRequestedSlapState
......@@ -388,7 +416,7 @@ class TestComputeNode_getNewsDict(TestSlapOSHalJsonStyleMixin):
def test_destroyed(self):
compute_node = self._makeComputeNode()
self._logFakeAccess(compute_node.getReference(),
self._logFakeAccess(compute_node,
state='destroy_requested')
news_dict = compute_node.ComputeNode_getNewsDict()
compute_node.getSlapState = fakeDestroyRequestedSlapState
......@@ -399,8 +427,8 @@ class TestComputeNode_getNewsDict(TestSlapOSHalJsonStyleMixin):
'no_data_since_5_minutes': 0,
'since': self.created_at,
'state': 'destroy_requested',
'text': u'#access OK',
'user': u'SlapOS Master'},
'text': '#access OK',
'user': 'SlapOS Master'},
'partition': {}
}
self.assertEqual(news_dict, expected_news_dict)
......@@ -411,7 +439,10 @@ class TestComputeNode_getNewsDict(TestSlapOSHalJsonStyleMixin):
compute_node = self._makeComputeNode()
news_dict = compute_node.ComputeNode_getNewsDict()
expected_news_dict = {'compute_node':
{'no_data': 1,
{'created_at': self.created_at,
'no_data': 1,
'since': self.created_at,
'state': '',
'text': '#error no data found for %s' % compute_node.getReference(),
'user': 'SlapOS Master'},
'partition': {}
......@@ -426,17 +457,20 @@ class TestComputeNode_getNewsDict(TestSlapOSHalJsonStyleMixin):
instance.setAggregateValue(compute_node.slappart0)
self.tic()
self._logFakeAccess(compute_node.getReference())
self._logFakeAccess(compute_node)
news_dict = compute_node.ComputeNode_getNewsDict()
expected_news_dict = {'compute_node':
{'created_at': self.created_at,
{u'created_at': u'%s' % self.created_at,
'no_data_since_15_minutes': 0,
'no_data_since_5_minutes': 0,
u'since': u'%s' % self.created_at,
u'state': u'start_requested',
u'text': u'#access OK',
u'user': u'SlapOS Master'},
'partition': {'slappart0': {'created_at': self.created_at,
'no_data': 1,
'since': self.created_at,
'state': 'start_requested',
'text': '#access OK',
'user': 'SlapOS Master'},
'partition': {'slappart0': {'no_data': 1,
'state': '',
'text': '#error no data found for %s' % (instance.getReference()),
'user': 'SlapOS Master'}}
}
......@@ -454,34 +488,36 @@ class TestComputerNetwork_getNewsDict(TestSlapOSHalJsonStyleMixin):
compute_node.setSubordinationValue(network)
self.tic()
self._logFakeAccess(compute_node.getReference())
self._logFakeAccess(compute_node)
news_dict = network.ComputerNetwork_getNewsDict()
expected_news_dict = {'compute_node':
{ compute_node.getReference():
{'created_at': self.created_at,
{u'created_at': u'%s' % self.created_at,
'no_data_since_15_minutes': 0,
'no_data_since_5_minutes': 0,
'since': self.created_at,
'state': 'start_requested',
'text': '#access OK',
'user': 'SlapOS Master'}
},
u'since': u'%s' % self.created_at,
u'state': u'start_requested',
u'text': u'#access OK',
u'user': u'SlapOS Master'}},
'partition':
{ compute_node.getReference():
{'slappart0': {'no_data': 1,
{'slappart0': {'created_at': self.created_at,
'no_data': 1,
'since': self.created_at,
'state': '',
'text': '#error no data found for %s' % (instance.getReference()),
'user': 'SlapOS Master'}
}
}
}
self.assertEqual(news_dict, expected_news_dict)
# Ensure it don't raise error when converting to JSON
json.dumps(news_dict)
def test_no_data(self):
network = self._makeComputerNetwork()
self._logFakeAccess(network.getReference())
news_dict = network.ComputerNetwork_getNewsDict()
expected_news_dict = {'compute_node': {}, 'partition': {}}
self.assertEqual(news_dict, expected_news_dict)
......@@ -500,27 +536,30 @@ class TestOrganisation_getNewsDict(TestSlapOSHalJsonStyleMixin):
organisation.fake_compute_node_list = [compute_node]
self.tic()
self._logFakeAccess(compute_node.getReference())
self._logFakeAccess(compute_node)
news_dict = organisation.Organisation_getNewsDict()
expected_news_dict = {'compute_node':
{ compute_node.getReference():
{'created_at': self.created_at,
{u'created_at': u'%s' % self.created_at,
'no_data_since_15_minutes': 0,
'no_data_since_5_minutes': 0,
'since': self.created_at,
'state': 'start_requested',
'text': '#access OK',
'user': 'SlapOS Master'}
},
u'since': u'%s' % self.created_at,
u'state': u'start_requested',
u'text': u'#access OK',
u'user': u'SlapOS Master'}},
'partition':
{ compute_node.getReference():
{'slappart0': {'no_data': 1,
{'slappart0': {'created_at': self.created_at,
'no_data': 1,
'since': self.created_at,
'state': '',
'text': '#error no data found for %s' % (instance.getReference()),
'user': 'SlapOS Master'}
}
}
}
self.assertEqual(news_dict, expected_news_dict)
# Ensure it don't raise error when converting to JSON
json.dumps(news_dict)
......@@ -545,27 +584,30 @@ class TestProject_getNewsDict(TestSlapOSHalJsonStyleMixin):
project.fake_compute_node_list = [compute_node]
self.tic()
self._logFakeAccess(compute_node.getReference())
self._logFakeAccess(compute_node)
news_dict = project.Project_getNewsDict()
expected_news_dict = {'compute_node':
{ compute_node.getReference():
{'created_at': self.created_at,
{u'created_at': u'%s' % self.created_at,
'no_data_since_15_minutes': 0,
'no_data_since_5_minutes': 0,
'since': self.created_at,
'state': 'start_requested',
'text': '#access OK',
'user': 'SlapOS Master'}
},
u'since': u'%s' % self.created_at,
u'state': u'start_requested',
u'text': u'#access OK',
u'user': u'SlapOS Master'}},
'partition':
{ compute_node.getReference():
{'slappart0': {'no_data': 1,
{'slappart0': {'created_at': self.created_at,
'no_data': 1,
'since': self.created_at,
'state': '',
'text': '#error no data found for %s' % (instance.getReference()),
'user': 'SlapOS Master'}
}
}
}
self.assertEqual(news_dict, expected_news_dict)
# Ensure it don't raise error when converting to JSON
json.dumps(news_dict)
......@@ -1158,11 +1200,3 @@ class TestInstanceTree_edit(TestSlapOSHalJsonStyleMixin):
self.assertEqual(new_parameter,
self.instance_tree.getTextContent())
\ No newline at end of file
......@@ -36,6 +36,6 @@ if len(full_software_installation_list) > 0 and \
len(full_software_installation_list) == len(set(compute_node_list)):
# Software is available for the root instance
software_installation = full_software_installation_list[0]
message = software_installation.Base_getNewsDict(software_installation)['text']
message = software_installation.getAccessStatusText()
if message.startswith("#access"):
return True
......@@ -297,7 +297,7 @@ class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
</tuple>
<dictionary id='i8'>
<string>_access_status</string>
<string>%(access_status)s</string>
<string>#error no data found for %(partition_3_instance_guid)s</string>
<string>_computer_id</string>
<string>%(compute_node_id)s</string>
<string>_connection_dict</string>
......@@ -373,7 +373,7 @@ class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
</tuple>
<dictionary id='i19'>
<string>_access_status</string>
<string>%(access_status)s</string>
<string>#error no data found for %(partition_2_instance_guid)s</string>
<string>_computer_id</string>
<string>%(compute_node_id)s</string>
<string>_connection_dict</string>
......@@ -449,7 +449,7 @@ class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
</tuple>
<dictionary id='i30'>
<string>_access_status</string>
<string>%(access_status)s</string>
<string>#error no data found for %(partition_1_instance_guid)s</string>
<string>_computer_id</string>
<string>%(compute_node_id)s</string>
<string>_connection_dict</string>
......@@ -642,6 +642,8 @@ class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data</string>
<int>1</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -690,6 +692,10 @@ class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data_since_15_minutes</string>
<int>0</int>
<string>no_data_since_5_minutes</string>
<int>0</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -743,6 +749,10 @@ class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data_since_15_minutes</string>
<int>0</int>
<string>no_data_since_5_minutes</string>
<int>0</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -830,6 +840,8 @@ class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data</string>
<int>1</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -898,6 +910,10 @@ class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data_since_15_minutes</string>
<int>0</int>
<string>no_data_since_5_minutes</string>
<int>0</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -943,6 +959,10 @@ class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data_since_15_minutes</string>
<int>0</int>
<string>no_data_since_5_minutes</string>
<int>0</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -988,6 +1008,10 @@ class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data_since_15_minutes</string>
<int>0</int>
<string>no_data_since_5_minutes</string>
<int>0</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -1290,7 +1314,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
slave_1_software_type=self.start_requested_slave_instance.getSourceReference(),
slave_1_instance_guid=self.start_requested_slave_instance.getReference(),
slave_1_title=self.start_requested_slave_instance.getTitle(),
access_status="#error no data found!",
access_status="#error no data found for %s" % self.start_requested_software_instance.getReference(),
)
self.assertEqual(expected_xml, got_xml,
'\n'.join([q for q in difflib.unified_diff(expected_xml.split('\n'), got_xml.split('\n'))]))
......@@ -1325,6 +1349,8 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data</string>
<int>1</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -1374,6 +1400,8 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data</string>
<int>1</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -1744,6 +1772,10 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data_since_15_minutes</string>
<int>0</int>
<string>no_data_since_5_minutes</string>
<int>0</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -1788,6 +1820,10 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data_since_15_minutes</string>
<int>0</int>
<string>no_data_since_5_minutes</string>
<int>0</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -1834,6 +1870,10 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data_since_15_minutes</string>
<int>0</int>
<string>no_data_since_5_minutes</string>
<int>0</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -1890,6 +1930,10 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data_since_15_minutes</string>
<int>0</int>
<string>no_data_since_5_minutes</string>
<int>0</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -2206,6 +2250,10 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data_since_15_minutes</string>
<int>0</int>
<string>no_data_since_5_minutes</string>
<int>0</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -2249,6 +2297,10 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data_since_15_minutes</string>
<int>0</int>
<string>no_data_since_5_minutes</string>
<int>0</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -2493,6 +2545,8 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data</string>
<int>1</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -2541,6 +2595,10 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data_since_15_minutes</string>
<int>0</int>
<string>no_data_since_5_minutes</string>
<int>0</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -2593,6 +2651,10 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data_since_15_minutes</string>
<int>0</int>
<string>no_data_since_5_minutes</string>
<int>0</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -2646,6 +2708,8 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data</string>
<int>1</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -2697,6 +2761,8 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data</string>
<int>1</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......@@ -3004,6 +3070,10 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data_since_15_minutes</string>
<int>0</int>
<string>no_data_since_5_minutes</string>
<int>0</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
......
......@@ -79,7 +79,6 @@ except ImportError:
from zLOG import LOG, INFO
import StringIO
import pkg_resources
import json
from DateTime import DateTime
from App.Common import rfc1123_date
class SoftwareInstanceNotReady(Exception):
......@@ -119,6 +118,25 @@ def convertToREST(function):
wrapper.__doc__ = function.__doc__
return wrapper
def convertToStatus(function):
def wrapper(self, *args, **kwd):
data_dict = function(self, *args, **kwd)
last_modified = rfc1123_date(DateTime())
# Keep in cache server for 7 days
self.REQUEST.response.setStatus(200)
self.REQUEST.response.setHeader('Cache-Control',
'public, max-age=60, stale-if-error=604800')
self.REQUEST.response.setHeader('Vary',
'REMOTE_USER')
self.REQUEST.response.setHeader('Last-Modified', last_modified)
self.REQUEST.response.setHeader('Content-Type', 'text/xml; charset=utf-8')
self.REQUEST.response.setBody(dumps(data_dict))
return self.REQUEST.response
return wrapper
def _assertACI(document):
sm = getSecurityManager()
if sm.checkPermission(access_contents_information,
......@@ -216,25 +234,6 @@ class SlapTool(BaseTool):
# called on site
pass
def _storeLastData(self, key, value):
cache_plugin = self.getPortalObject().portal_caches\
.getRamCacheRoot().get('last_stored_data_cache_factory')\
.getCachePluginList()[0]
cache_plugin.set(key, DEFAULT_CACHE_SCOPE, value,
cache_duration=self.getPortalObject().portal_caches\
.getRamCacheRoot().get('last_stored_data_cache_factory').cache_duration)
def _getLastData(self, key):
cache_plugin = self.getPortalObject().portal_caches\
.getRamCacheRoot().get('last_stored_data_cache_factory')\
.getCachePluginList()[0]
try:
entry = cache_plugin.get(key, DEFAULT_CACHE_SCOPE)
except KeyError:
entry = None
else:
entry = entry.getValue()
return entry
def _activateFillComputeNodeInformationCache(self, compute_node_id, user):
tag = 'compute_node_information_cache_fill_%s_%s' % (compute_node_id, user)
......@@ -380,7 +379,8 @@ class SlapTool(BaseTool):
"""
user = self.getPortalObject().portal_membership.getAuthenticatedMember().getUserName()
if str(user) == computer_id:
self._logAccess(user, user, '#access %s' % computer_id)
compute_node = self.getPortalObject().portal_membership.getAuthenticatedMember().getUserValue()
compute_node.setAccessStatus('#access %s' % computer_id)
refresh_etag = self._calculateRefreshEtag()
body, etag = self._getComputeNodeInformation(computer_id, user, refresh_etag)
......@@ -448,6 +448,7 @@ class SlapTool(BaseTool):
security.declareProtected(Permissions.AccessContentsInformation,
'getComputerPartitionStatus')
@convertToStatus
def getComputerPartitionStatus(self, computer_id, computer_partition_id):
"""
Get the connection status of the partition
......@@ -459,10 +460,11 @@ class SlapTool(BaseTool):
except NotFound:
return self._getAccessStatus(None)
else:
return self._getAccessStatus(instance.getReference())
return instance.getAccessStatus()
security.declareProtected(Permissions.AccessContentsInformation,
'getComputerStatus')
@convertToStatus
def getComputerStatus(self, computer_id):
"""
Get the connection status of the partition
......@@ -472,10 +474,11 @@ class SlapTool(BaseTool):
validation_state="validated")[0].getObject()
# Be sure to prevent accessing information to disallowed users
compute_node = _assertACI(compute_node)
return self._getAccessStatus(computer_id)
return compute_node.getAccessStatus()
security.declareProtected(Permissions.AccessContentsInformation,
'getSoftwareInstallationStatus')
@convertToStatus
def getSoftwareInstallationStatus(self, url, computer_id):
"""
Get the connection status of the software installation
......@@ -492,7 +495,7 @@ class SlapTool(BaseTool):
except NotFound:
return self._getAccessStatus(None)
else:
return self._getAccessStatus(software_installation.getReference())
return software_installation.getAccessStatus()
security.declareProtected(Permissions.AccessContentsInformation,
'getSoftwareReleaseListFromSoftwareProduct')
......@@ -771,11 +774,9 @@ class SlapTool(BaseTool):
"""
Fire up bung on Compute Node
"""
user = self.getPortalObject().portal_membership.getAuthenticatedMember()\
.getUserName()
self._logAccess(user, compute_node_id, '#error bang')
return self._getComputeNodeDocument(compute_node_id).reportComputeNodeBang(
comment=message)
compute_node = self._getComputeNodeDocument(compute_node_id)
compute_node.setAccessStatus('#error bang')
return compute_node.reportComputeNodeBang(comment=message)
security.declareProtected(Permissions.AccessContentsInformation,
'computerBang')
......@@ -925,34 +926,6 @@ class SlapTool(BaseTool):
# Internal methods
####################################################
def _logAccess(self, user_reference, context_reference, text, state=""):
memcached_dict = self.Base_getSlapToolMemcachedDict()
previous = self._getCachedAccessInfo(context_reference)
created_at = rfc1123_date(DateTime())
since = created_at
status_changed = True
if previous is not None:
previous_json = json.loads(previous)
if text.split(" ")[0] == previous_json.get("text", "").split(" ")[0]:
since = previous_json.get("since",
previous_json.get("created_at", rfc1123_date(DateTime())))
status_changed = False
if state == "":
state = previous_json.get("state", "")
value = json.dumps({
'user': '%s' % user_reference,
'created_at': '%s' % created_at,
'text': '%s' % text,
'since': '%s' % since,
'state': state
})
memcached_dict[context_reference] = value
return status_changed
def _validateXML(self, to_be_validated, xsd_model):
"""Will validate the xml file"""
#We parse the XSD model
......@@ -1015,8 +988,7 @@ class SlapTool(BaseTool):
slap_partition._requested_state = 'stopped'
if state == "start_requested":
slap_partition._requested_state = 'started'
slap_partition._access_status = self._getTextAccessStatus(
software_instance.getReference())
slap_partition._access_status = software_instance.getTextAccessStatus()
slap_partition._software_release_document = SoftwareRelease(
software_release=software_instance.getUrlString().decode("UTF-8"),
......@@ -1061,11 +1033,9 @@ class SlapTool(BaseTool):
Log the software release status
"""
compute_node_document = self._getComputeNodeDocument(compute_node_id)
software_installation_reference = self._getSoftwareInstallationReference(url,
software_installation = self._getSoftwareInstallationForComputeNode(url,
compute_node_document)
user = self.getPortalObject().portal_membership.\
getAuthenticatedMember().getUserName()
self._logAccess(user, software_installation_reference,
software_installation.setAccessStatus(
'#building software release %s' % url, "building")
@convertToREST
......@@ -1074,11 +1044,9 @@ class SlapTool(BaseTool):
Log the software release status
"""
compute_node_document = self._getComputeNodeDocument(compute_node_id)
software_installation_reference = self._getSoftwareInstallationReference(url,
software_installation = self._getSoftwareInstallationForComputeNode(url,
compute_node_document)
user = self.getPortalObject().portal_membership.\
getAuthenticatedMember().getUserName()
self._logAccess(user, software_installation_reference,
software_installation.setAccessStatus(
'#access software release %s available' % url, "available")
@convertToREST
......@@ -1108,9 +1076,8 @@ class SlapTool(BaseTool):
instance = self._getSoftwareInstanceForComputePartition(
compute_node_id,
compute_partition_id)
user = self.getPortalObject().portal_membership.getAuthenticatedMember()\
.getUserName()
status_changed = self._logAccess(user, instance.getReference(),
status_changed = instance.setAccessStatus(
'#error while instanciating: %s' % error_log[-80:])
if status_changed:
......@@ -1126,7 +1093,7 @@ class SlapTool(BaseTool):
for name in [software_instance.getTitle(), new_name]:
# reset request cache
key = '_'.join([hosting, name])
self._storeLastData(key, {})
software_instance.setLastData({}, key=key)
return software_instance.rename(new_name=new_name,
comment="Rename %s into %s" % (software_instance.title, new_name))
......@@ -1140,79 +1107,19 @@ class SlapTool(BaseTool):
software_instance = self._getSoftwareInstanceForComputePartition(
compute_node_id,
compute_partition_id)
user = self.getPortalObject().portal_membership.\
getAuthenticatedMember().getUserName()
self._logAccess(user, software_instance.getReference(),
'#error bang called')
software_instance.setAccessStatus('#error bang called')
timestamp = str(int(software_instance.getModificationDate()))
key = "%s_bangstamp" % software_instance.getReference()
self.getPortalObject().portal_workflow.getInfoFor(
software_instance, 'action', wf_id='instance_slap_interface_workflow')
if (self._getLastData(key) != timestamp):
if (software_instance.getLastData(key) != timestamp):
software_instance.bang(bang_tree=True, comment=message)
self._storeLastData(key, str(int(software_instance.getModificationDate())))
software_instance.setLastData(key, str(int(software_instance.getModificationDate())))
return "OK"
def _getCachedAccessInfo(self, context_reference):
memcached_dict = self.Base_getSlapToolMemcachedDict()
try:
if context_reference is None:
raise KeyError
else:
data = memcached_dict[context_reference]
except KeyError:
return None
return data
def _getTextAccessStatus(self, context_reference):
status_string = self._getCachedAccessInfo(context_reference)
access_status = "#error no data found!"
if status_string is not None:
try:
access_status = json.loads(status_string)['text']
except ValueError:
pass
return access_status
def _getAccessStatus(self, context_reference):
d = self._getCachedAccessInfo(context_reference)
last_modified = rfc1123_date(DateTime())
if d is None:
if context_reference is None:
d = {
"user": "SlapOS Master",
'created_at': '%s' % last_modified,
'since': '%s' % last_modified,
'state': "",
"text": "#error no data found"
}
else:
d = {
"user": "SlapOS Master",
'created_at': '%s' % last_modified,
'since': '%s' % last_modified,
'state': "",
"text": "#error no data found for %s" % context_reference
}
# Prepare for xml marshalling
d["user"] = d["user"].decode("UTF-8")
d["text"] = d["text"].decode("UTF-8")
else:
d = json.loads(d)
# Keep in cache server for 7 days
self.REQUEST.response.setStatus(200)
self.REQUEST.response.setHeader('Cache-Control',
'public, max-age=60, stale-if-error=604800')
self.REQUEST.response.setHeader('Vary',
'REMOTE_USER')
self.REQUEST.response.setHeader('Last-Modified', last_modified)
self.REQUEST.response.setHeader('Content-Type', 'text/xml; charset=utf-8')
self.REQUEST.response.setBody(dumps(d))
return self.REQUEST.response
@convertToREST
def _startedComputePartition(self, compute_node_id, compute_partition_id):
"""
......@@ -1221,10 +1128,7 @@ class SlapTool(BaseTool):
instance = self._getSoftwareInstanceForComputePartition(
compute_node_id,
compute_partition_id)
user = self.getPortalObject().portal_membership.getAuthenticatedMember()\
.getUserName()
status_changed = self._logAccess(user, instance.getReference(),
'#access Instance correctly started', "started")
status_changed = instance.setAccessStatus('#access Instance correctly started', "started")
if status_changed:
instance.reindexObject()
......@@ -1236,10 +1140,7 @@ class SlapTool(BaseTool):
instance = self._getSoftwareInstanceForComputePartition(
compute_node_id,
compute_partition_id)
user = self.getPortalObject().portal_membership.getAuthenticatedMember()\
.getUserName()
status_changed = self._logAccess(user, instance.getReference(),
'#access Instance correctly stopped', "stopped")
status_changed = instance.setAccessStatus('#access Instance correctly stopped', "stopped")
if status_changed:
instance.reindexObject()
......@@ -1288,12 +1189,11 @@ class SlapTool(BaseTool):
compute_partition_id,
slave_reference)
connection_xml = dict2xml(loads(connection_xml))
reference = software_instance.getReference()
if self._getLastData(reference) != connection_xml:
if software_instance.getLastData() != connection_xml:
software_instance.updateConnection(
connection_xml=connection_xml,
)
self._storeLastData(reference, connection_xml)
software_instance.setLastData(connection_xml)
@convertToREST
def _requestComputePartition(self, compute_node_id, compute_partition_id,
......@@ -1368,7 +1268,7 @@ class SlapTool(BaseTool):
value = dict(
hash='_'.join([software_instance_document.getRelativeUrl(), str(kw)]),
)
last_data = self._getLastData(key)
last_data = software_instance_document.getLastData(key)
requested_software_instance = None
if last_data is not None and isinstance(last_data, dict):
requested_software_instance = portal.restrictedTraverse(
......@@ -1381,7 +1281,7 @@ class SlapTool(BaseTool):
if requested_software_instance is not None:
value['request_instance'] = requested_software_instance\
.getRelativeUrl()
self._storeLastData(key, value)
software_instance_document.setLastData(value, key=key)
else:
# requested as root, so done by human
person = portal.portal_membership.getAuthenticatedMember().getUserValue()
......@@ -1396,7 +1296,7 @@ class SlapTool(BaseTool):
value = dict(
hash=str(kw)
)
last_data = self._getLastData(key)
last_data = person.getLastData(key)
if last_data is not None and isinstance(last_data, dict):
requested_software_instance = portal.restrictedTraverse(
last_data.get('request_instance'), None)
......@@ -1408,7 +1308,7 @@ class SlapTool(BaseTool):
if requested_software_instance is not None:
value['request_instance'] = requested_software_instance\
.getRelativeUrl()
self._storeLastData(key, value)
requested_software_instance.setLastData(value, key=key)
if requested_software_instance is None:
raise SoftwareInstanceNotReady
......@@ -1452,7 +1352,7 @@ class SlapTool(BaseTool):
compute_partition_id)
cache_reference = '%s-PREDLIST' % software_instance_document.getReference()
if self._getLastData(cache_reference) != instance_reference_xml:
if software_instance_document.getLastData(cache_reference) != instance_reference_xml:
instance_reference_list = loads(instance_reference_xml)
current_successor_list = software_instance_document.getSuccessorValueList(
......@@ -1470,7 +1370,7 @@ class SlapTool(BaseTool):
compute_node_id, compute_partition_id, successor_list), error=False)
software_instance_document.edit(successor_list=successor_list,
comment='successor_list edited to unlink non commited instances')
self._storeLastData(cache_reference, instance_reference_xml)
software_instance_document.setLastData(instance_reference_xml, key=cache_reference)
####################################################
# Internals methods
......@@ -1678,7 +1578,7 @@ class SlapTool(BaseTool):
else:
software_release_response._requested_state = 'available'
known_state = self._getTextAccessStatus(software_installation.getReference())
known_state = software_installation.getTextAccessStatus()
if known_state.startswith("#access"):
software_release_response._known_state = 'available'
elif known_state.startswith("#building"):
......@@ -1695,11 +1595,8 @@ class SlapTool(BaseTool):
Log the compute_node status
"""
compute_node_document = self._getComputeNodeDocument(compute_node_id)
software_installation_reference = self._getSoftwareInstallationReference(url,
software_installation = self._getSoftwareInstallationForComputeNode(url,
compute_node_document)
user = self.getPortalObject().portal_membership.\
getAuthenticatedMember().getUserName()
self._logAccess(user, software_installation_reference,
'#error while installing %s' % url)
software_installation.setAccessStatus('#error while installing %s' % url)
InitializeClass(SlapTool)
portal_caches/last_stored_data_cache_factory
portal_caches/last_stored_data_cache_factory/volatile_cache_plugin
\ No newline at end of file
portal_caches/compute_node_information_cache_factory
portal_caches/compute_node_information_cache_factory/persistent_cache_plugin
portal_caches/last_stored_data_cache_factory
portal_caches/last_stored_data_cache_factory/volatile_cache_plugin
portal_caches/slap_cache_factory
portal_caches/slap_cache_factory/persistent_cache_plugin
web_site_module/slapos_hateoas
......
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