From 8db76f83077ff519ebbb433e7ee9a1309a9b659a Mon Sep 17 00:00:00 2001
From: Alain Takoudjou <alain.takoudjou@nexedi.com>
Date: Mon, 11 Apr 2016 12:26:49 +0000
Subject: [PATCH] slapos_hypermedia: migrate bt to new format

---
 .../Base_getHateoasMaster.py                  | 37 +++++++++++
 .../Base_getHateoasMaster.xml                 | 41 -------------
 ...uter_getHateoasSoftwareInstallationList.py | 43 +++++++++++++
 ...ter_getHateoasSoftwareInstallationList.xml | 47 --------------
 ...tingSubscription_getHateoasInstanceList.py | 42 +++++++++++++
 ...ingSubscription_getHateoasInstanceList.xml | 46 --------------
 ...cription_getHateoasRootSoftwareInstance.py | 42 +++++++++++++
 ...ription_getHateoasRootSoftwareInstance.xml | 46 --------------
 .../Instance_getHateoasInformation.py         | 49 +++++++++++++++
 .../Instance_getHateoasInformation.xml        | 53 ----------------
 .../Instance_getHateoasNews.py                | 47 ++++++++++++++
 .../Instance_getHateoasNews.xml               | 51 ----------------
 ...ce_getHateoasRelatedHostingSubscription.py | 42 +++++++++++++
 ...e_getHateoasRelatedHostingSubscription.xml | 46 --------------
 .../Person_getHateoasComputerList.py          | 43 +++++++++++++
 .../Person_getHateoasComputerList.xml         | 47 --------------
 ...erson_getHateoasHostingSubscriptionList.py | 44 +++++++++++++
 ...rson_getHateoasHostingSubscriptionList.xml | 48 ---------------
 ...erson_requestHateoasHostingSubscription.py | 53 ++++++++++++++++
 ...rson_requestHateoasHostingSubscription.xml | 61 -------------------
 ...twareInstallation_getHateoasInformation.py | 44 +++++++++++++
 ...wareInstallation_getHateoasInformation.xml | 48 ---------------
 .../SoftwareInstallation_getHateoasNews.py    | 48 +++++++++++++++
 .../SoftwareInstallation_getHateoasNews.xml   | 52 ----------------
 .../bt5/slapos_hypermedia/bt/dependency_list  |  2 +-
 25 files changed, 535 insertions(+), 587 deletions(-)
 create mode 100644 master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Base_getHateoasMaster.py
 create mode 100644 master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Computer_getHateoasSoftwareInstallationList.py
 create mode 100644 master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/HostingSubscription_getHateoasInstanceList.py
 create mode 100644 master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/HostingSubscription_getHateoasRootSoftwareInstance.py
 create mode 100644 master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasInformation.py
 create mode 100644 master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasNews.py
 create mode 100644 master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasRelatedHostingSubscription.py
 create mode 100644 master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_getHateoasComputerList.py
 create mode 100644 master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_getHateoasHostingSubscriptionList.py
 create mode 100644 master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_requestHateoasHostingSubscription.py
 create mode 100644 master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/SoftwareInstallation_getHateoasInformation.py
 create mode 100644 master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/SoftwareInstallation_getHateoasNews.py

diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Base_getHateoasMaster.py b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Base_getHateoasMaster.py
new file mode 100644
index 000000000..ba8f70437
--- /dev/null
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Base_getHateoasMaster.py
@@ -0,0 +1,37 @@
+from zExceptions import Unauthorized
+from AccessControl import getSecurityManager
+
+if REQUEST is None:
+  raise Unauthorized
+
+response = REQUEST.RESPONSE
+mime_type = 'application/hal+json'
+
+if REQUEST.other['method'] != "GET":
+  response.setStatus(405)
+  return ""
+elif mime_type != context.Base_handleAcceptHeader([mime_type]):
+  response.setStatus(406)
+  return ""
+
+import json
+result_dict = json.loads(context.ERP5Document_getHateoas(REQUEST))
+
+portal = context.getPortalObject()
+
+person = portal.ERP5Site_getAuthenticatedMemberPersonValue()
+if person is not None:
+  result_dict['_links']['me'] = {
+    "href": "urn:jio:get:%s" % person.getRelativeUrl(),
+  }
+
+else:
+  user = str(portal.portal_membership.getAuthenticatedMember())
+  if user != "Anonymous User":
+    user_document = context.ERP5Site_getUserDocument(user)
+    result_dict['_links']['me'] = {
+      'href': 'urn:jio:get:%s' % user_document.getRelativeUrl(),
+    }
+
+response.setHeader('Content-Type', mime_type)
+return json.dumps(result_dict, indent=2)
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Base_getHateoasMaster.xml b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Base_getHateoasMaster.xml
index 288af9b64..dfc2249dd 100644
--- a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Base_getHateoasMaster.xml
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Base_getHateoasMaster.xml
@@ -48,47 +48,6 @@
               </object>
             </value>
         </item>
-        <item>
-            <key> <string>_body</string> </key>
-            <value> <string>from zExceptions import Unauthorized\n
-from AccessControl import getSecurityManager\n
-\n
-if REQUEST is None:\n
-  raise Unauthorized\n
-\n
-response = REQUEST.RESPONSE\n
-mime_type = \'application/hal+json\'\n
-\n
-if REQUEST.other[\'method\'] != "GET":\n
-  response.setStatus(405)\n
-  return ""\n
-elif mime_type != context.Base_handleAcceptHeader([mime_type]):\n
-  response.setStatus(406)\n
-  return ""\n
-\n
-import json\n
-result_dict = json.loads(context.ERP5Document_getHateoas(REQUEST))\n
-\n
-portal = context.getPortalObject()\n
-\n
-person = portal.ERP5Site_getAuthenticatedMemberPersonValue()\n
-if person is not None:\n
-  result_dict[\'_links\'][\'me\'] = {\n
-    "href": "urn:jio:get:%s" % person.getRelativeUrl(),\n
-  }\n
-\n
-else:\n
-  user = str(portal.portal_membership.getAuthenticatedMember())\n
-  if user != "Anonymous User":\n
-    user_document = context.ERP5Site_getUserDocument(user)\n
-    result_dict[\'_links\'][\'me\'] = {\n
-      \'href\': \'urn:jio:get:%s\' % user_document.getRelativeUrl(),\n
-    }\n
-\n
-response.setHeader(\'Content-Type\', mime_type)\n
-return json.dumps(result_dict, indent=2)\n
-</string> </value>
-        </item>
         <item>
             <key> <string>_params</string> </key>
             <value> <string>REQUEST=None</string> </value>
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Computer_getHateoasSoftwareInstallationList.py b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Computer_getHateoasSoftwareInstallationList.py
new file mode 100644
index 000000000..3fb56552f
--- /dev/null
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Computer_getHateoasSoftwareInstallationList.py
@@ -0,0 +1,43 @@
+from zExceptions import Unauthorized
+from AccessControl import getSecurityManager
+if REQUEST is None:
+  raise Unauthorized
+
+response = REQUEST.RESPONSE
+mime_type = 'application/hal+json'
+
+if REQUEST.other['method'] != "GET":
+  response.setStatus(405)
+  return ""
+elif mime_type != context.Base_handleAcceptHeader([mime_type]):
+  response.setStatus(406)
+  return ""
+elif context.getPortalType() != "Computer":
+  response.setStatus(403)
+  return ""
+
+import json
+result_dict = {
+  '_links': {
+    "self": { "href": context.Base_getRequestUrl() },
+    "index": {
+      "href": "urn:jio:get:%s" % context.getRelativeUrl(),
+      "title": "Computer"
+    },
+    "content": [],
+  },
+}
+
+for sql_obj in context.getPortalObject().portal_catalog(
+                                               portal_type='Software Installation',
+                                               default_aggregate_uid=context.getUid(),
+                                               validation_state='validated',
+                                               ):
+  obj = sql_obj.getObject()
+  result_dict['_links']['content'].append({
+    'href': '%s/ERP5Document_getHateoas' % obj.absolute_url(),
+    'title': obj.getUrlString()
+  })
+
+response.setHeader('Content-Type', mime_type)
+return json.dumps(result_dict, indent=2)
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Computer_getHateoasSoftwareInstallationList.xml b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Computer_getHateoasSoftwareInstallationList.xml
index 483047235..d4f899ea7 100644
--- a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Computer_getHateoasSoftwareInstallationList.xml
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Computer_getHateoasSoftwareInstallationList.xml
@@ -48,53 +48,6 @@
               </object>
             </value>
         </item>
-        <item>
-            <key> <string>_body</string> </key>
-            <value> <string>from zExceptions import Unauthorized\n
-from AccessControl import getSecurityManager\n
-if REQUEST is None:\n
-  raise Unauthorized\n
-\n
-response = REQUEST.RESPONSE\n
-mime_type = \'application/hal+json\'\n
-\n
-if REQUEST.other[\'method\'] != "GET":\n
-  response.setStatus(405)\n
-  return ""\n
-elif mime_type != context.Base_handleAcceptHeader([mime_type]):\n
-  response.setStatus(406)\n
-  return ""\n
-elif context.getPortalType() != "Computer":\n
-  response.setStatus(403)\n
-  return ""\n
-\n
-import json\n
-result_dict = {\n
-  \'_links\': {\n
-    "self": { "href": context.Base_getRequestUrl() },\n
-    "index": {\n
-      "href": "urn:jio:get:%s" % context.getRelativeUrl(),\n
-      "title": "Computer"\n
-    },\n
-    "content": [],\n
-  },\n
-}\n
-\n
-for sql_obj in context.getPortalObject().portal_catalog(\n
-                                               portal_type=\'Software Installation\',\n
-                                               default_aggregate_uid=context.getUid(),\n
-                                               validation_state=\'validated\',\n
-                                               ):\n
-  obj = sql_obj.getObject()\n
-  result_dict[\'_links\'][\'content\'].append({\n
-    \'href\': \'%s/ERP5Document_getHateoas\' % obj.absolute_url(),\n
-    \'title\': obj.getUrlString()\n
-  })\n
-\n
-response.setHeader(\'Content-Type\', mime_type)\n
-return json.dumps(result_dict, indent=2)\n
-</string> </value>
-        </item>
         <item>
             <key> <string>_params</string> </key>
             <value> <string>REQUEST=None</string> </value>
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/HostingSubscription_getHateoasInstanceList.py b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/HostingSubscription_getHateoasInstanceList.py
new file mode 100644
index 000000000..34b3cdc78
--- /dev/null
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/HostingSubscription_getHateoasInstanceList.py
@@ -0,0 +1,42 @@
+from zExceptions import Unauthorized
+from AccessControl import getSecurityManager
+if REQUEST is None:
+  raise Unauthorized
+
+response = REQUEST.RESPONSE
+mime_type = 'application/hal+json'
+
+if REQUEST.other['method'] != "GET":
+  response.setStatus(405)
+  return ""
+elif mime_type != context.Base_handleAcceptHeader([mime_type]):
+  response.setStatus(406)
+  return ""
+elif context.getPortalType() != "Hosting Subscription":
+  response.setStatus(403)
+  return ""
+
+import json
+result_dict = {
+  '_links': {
+    "self": { "href": context.Base_getRequestUrl() },
+    "content": [],
+    "index": {
+      "href": "urn:jio:get:%s" % context.getRelativeUrl(),
+      "title": "Hosting Subscription"
+    },
+  },
+}
+
+for sql_obj in context.getPortalObject().portal_catalog(
+                                               portal_type=['Software Instance', 'Slave Instance'],
+                                               default_specialise_uid=context.getUid(),
+                                               ):
+  obj = sql_obj.getObject()
+  result_dict['_links']['content'].append({
+    'href': '%s/ERP5Document_getHateoas' % obj.absolute_url(),
+    'title': obj.getTitle()
+  })
+
+response.setHeader('Content-Type', mime_type)
+return json.dumps(result_dict, indent=2)
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/HostingSubscription_getHateoasInstanceList.xml b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/HostingSubscription_getHateoasInstanceList.xml
index dea6c3923..dc16f77e1 100644
--- a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/HostingSubscription_getHateoasInstanceList.xml
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/HostingSubscription_getHateoasInstanceList.xml
@@ -48,52 +48,6 @@
               </object>
             </value>
         </item>
-        <item>
-            <key> <string>_body</string> </key>
-            <value> <string>from zExceptions import Unauthorized\n
-from AccessControl import getSecurityManager\n
-if REQUEST is None:\n
-  raise Unauthorized\n
-\n
-response = REQUEST.RESPONSE\n
-mime_type = \'application/hal+json\'\n
-\n
-if REQUEST.other[\'method\'] != "GET":\n
-  response.setStatus(405)\n
-  return ""\n
-elif mime_type != context.Base_handleAcceptHeader([mime_type]):\n
-  response.setStatus(406)\n
-  return ""\n
-elif context.getPortalType() != "Hosting Subscription":\n
-  response.setStatus(403)\n
-  return ""\n
-\n
-import json\n
-result_dict = {\n
-  \'_links\': {\n
-    "self": { "href": context.Base_getRequestUrl() },\n
-    "content": [],\n
-    "index": {\n
-      "href": "urn:jio:get:%s" % context.getRelativeUrl(),\n
-      "title": "Hosting Subscription"\n
-    },\n
-  },\n
-}\n
-\n
-for sql_obj in context.getPortalObject().portal_catalog(\n
-                                               portal_type=[\'Software Instance\', \'Slave Instance\'],\n
-                                               default_specialise_uid=context.getUid(),\n
-                                               ):\n
-  obj = sql_obj.getObject()\n
-  result_dict[\'_links\'][\'content\'].append({\n
-    \'href\': \'%s/ERP5Document_getHateoas\' % obj.absolute_url(),\n
-    \'title\': obj.getTitle()\n
-  })\n
-\n
-response.setHeader(\'Content-Type\', mime_type)\n
-return json.dumps(result_dict, indent=2)\n
-</string> </value>
-        </item>
         <item>
             <key> <string>_params</string> </key>
             <value> <string>REQUEST=None</string> </value>
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/HostingSubscription_getHateoasRootSoftwareInstance.py b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/HostingSubscription_getHateoasRootSoftwareInstance.py
new file mode 100644
index 000000000..eec458593
--- /dev/null
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/HostingSubscription_getHateoasRootSoftwareInstance.py
@@ -0,0 +1,42 @@
+from zExceptions import Unauthorized
+from AccessControl import getSecurityManager
+if REQUEST is None:
+  raise Unauthorized
+
+response = REQUEST.RESPONSE
+mime_type = 'application/hal+json'
+
+if REQUEST.other['method'] != "GET":
+  response.setStatus(405)
+  return ""
+elif mime_type != context.Base_handleAcceptHeader([mime_type]):
+  response.setStatus(406)
+  return ""
+elif context.getPortalType() != "Hosting Subscription":
+  response.setStatus(403)
+  return ""
+
+instance_list = context.getPredecessorValueList()
+for instance in instance_list:
+  if instance.getTitle() == context.getTitle():
+    root_instance = instance
+    break
+else:
+  raise Exception('Root instance not found.')
+
+import json
+result_dict = {
+  '_links': {
+    "self": { "href": context.Base_getRequestUrl() },
+    "content": [
+       {'href': '%s/ERP5Document_getHateoas' % root_instance.getAbsoluteUrl()},
+     ],
+    "index": {
+      "href": "urn:jio:get:%s" % context.getRelativeUrl(),
+      "title": "Hosting Subscription"
+    },
+  },
+}
+
+response.setHeader('Content-Type', mime_type)
+return json.dumps(result_dict, indent=2)
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/HostingSubscription_getHateoasRootSoftwareInstance.xml b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/HostingSubscription_getHateoasRootSoftwareInstance.xml
index 1ebaafaaa..c59856b2c 100644
--- a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/HostingSubscription_getHateoasRootSoftwareInstance.xml
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/HostingSubscription_getHateoasRootSoftwareInstance.xml
@@ -48,52 +48,6 @@
               </object>
             </value>
         </item>
-        <item>
-            <key> <string>_body</string> </key>
-            <value> <string>from zExceptions import Unauthorized\n
-from AccessControl import getSecurityManager\n
-if REQUEST is None:\n
-  raise Unauthorized\n
-\n
-response = REQUEST.RESPONSE\n
-mime_type = \'application/hal+json\'\n
-\n
-if REQUEST.other[\'method\'] != "GET":\n
-  response.setStatus(405)\n
-  return ""\n
-elif mime_type != context.Base_handleAcceptHeader([mime_type]):\n
-  response.setStatus(406)\n
-  return ""\n
-elif context.getPortalType() != "Hosting Subscription":\n
-  response.setStatus(403)\n
-  return ""\n
-\n
-instance_list = context.getPredecessorValueList()\n
-for instance in instance_list:\n
-  if instance.getTitle() == context.getTitle():\n
-    root_instance = instance\n
-    break\n
-else:\n
-  raise Exception(\'Root instance not found.\')\n
-\n
-import json\n
-result_dict = {\n
-  \'_links\': {\n
-    "self": { "href": context.Base_getRequestUrl() },\n
-    "content": [\n
-       {\'href\': \'%s/ERP5Document_getHateoas\' % root_instance.getAbsoluteUrl()},\n
-     ],\n
-    "index": {\n
-      "href": "urn:jio:get:%s" % context.getRelativeUrl(),\n
-      "title": "Hosting Subscription"\n
-    },\n
-  },\n
-}\n
-\n
-response.setHeader(\'Content-Type\', mime_type)\n
-return json.dumps(result_dict, indent=2)\n
-</string> </value>
-        </item>
         <item>
             <key> <string>_params</string> </key>
             <value> <string>REQUEST=None</string> </value>
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasInformation.py b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasInformation.py
new file mode 100644
index 000000000..54e201427
--- /dev/null
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasInformation.py
@@ -0,0 +1,49 @@
+from zExceptions import Unauthorized
+from AccessControl import getSecurityManager
+if REQUEST is None:
+  raise Unauthorized
+
+response = REQUEST.RESPONSE
+mime_type = 'application/hal+json'
+
+if REQUEST.other['method'] != "GET":
+  response.setStatus(405)
+  return ""
+elif mime_type != context.Base_handleAcceptHeader([mime_type]):
+  response.setStatus(406)
+  return ""
+elif context.getPortalType() not in ["Software Instance", "Slave Instance"]:
+  response.setStatus(403)
+  return ""
+
+if context.getSlapState() == "stop_requested":
+  state = 'stopped'
+elif context.getSlapState() == "start_requested":
+  state = 'started'
+else:
+  state = 'destroyed'
+
+import json
+result_dict = {
+  'title': context.getTitle(),
+  'slave': context.getPortalType() == 'Slave Instance',
+  'software_type': context.getSourceReference(),
+  'parameter_dict': context.getInstanceXmlAsDict(),
+  'sla_dict': context.getSlaXmlAsDict(),
+  'connection_dict': context.getConnectionXmlAsDict(),
+  'requested_state': state,
+  'instance_guid': context.getId(),
+  '_links': {
+    "self": { "href": context.Base_getRequestUrl() },
+    "index": {
+      "href": "urn:jio:get:%s" % context.getRelativeUrl(),
+      "title": "Software Instance",
+    },
+    'software_release': {
+      "href": context.getUrlString(),
+    }
+  },
+}
+
+response.setHeader('Content-Type', mime_type)
+return json.dumps(result_dict, indent=2)
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasInformation.xml b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasInformation.xml
index 3c31a30a5..1db680233 100644
--- a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasInformation.xml
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasInformation.xml
@@ -48,59 +48,6 @@
               </object>
             </value>
         </item>
-        <item>
-            <key> <string>_body</string> </key>
-            <value> <string>from zExceptions import Unauthorized\n
-from AccessControl import getSecurityManager\n
-if REQUEST is None:\n
-  raise Unauthorized\n
-\n
-response = REQUEST.RESPONSE\n
-mime_type = \'application/hal+json\'\n
-\n
-if REQUEST.other[\'method\'] != "GET":\n
-  response.setStatus(405)\n
-  return ""\n
-elif mime_type != context.Base_handleAcceptHeader([mime_type]):\n
-  response.setStatus(406)\n
-  return ""\n
-elif context.getPortalType() not in ["Software Instance", "Slave Instance"]:\n
-  response.setStatus(403)\n
-  return ""\n
-\n
-if context.getSlapState() == "stop_requested":\n
-  state = \'stopped\'\n
-elif context.getSlapState() == "start_requested":\n
-  state = \'started\'\n
-else:\n
-  state = \'destroyed\'\n
-\n
-import json\n
-result_dict = {\n
-  \'title\': context.getTitle(),\n
-  \'slave\': context.getPortalType() == \'Slave Instance\',\n
-  \'software_type\': context.getSourceReference(),\n
-  \'parameter_dict\': context.getInstanceXmlAsDict(),\n
-  \'sla_dict\': context.getSlaXmlAsDict(),\n
-  \'connection_dict\': context.getConnectionXmlAsDict(),\n
-  \'requested_state\': state,\n
-  \'instance_guid\': context.getId(),\n
-  \'_links\': {\n
-    "self": { "href": context.Base_getRequestUrl() },\n
-    "index": {\n
-      "href": "urn:jio:get:%s" % context.getRelativeUrl(),\n
-      "title": "Software Instance",\n
-    },\n
-    \'software_release\': {\n
-      "href": context.getUrlString(),\n
-    }\n
-  },\n
-}\n
-\n
-response.setHeader(\'Content-Type\', mime_type)\n
-return json.dumps(result_dict, indent=2)\n
-</string> </value>
-        </item>
         <item>
             <key> <string>_params</string> </key>
             <value> <string>REQUEST=None</string> </value>
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasNews.py b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasNews.py
new file mode 100644
index 000000000..4ad3af283
--- /dev/null
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasNews.py
@@ -0,0 +1,47 @@
+from zExceptions import Unauthorized
+from AccessControl import getSecurityManager
+if REQUEST is None:
+  raise Unauthorized
+
+response = REQUEST.RESPONSE
+mime_type = 'application/hal+json'
+
+if REQUEST.other['method'] != "GET":
+  response.setStatus(405)
+  return ""
+elif mime_type != context.Base_handleAcceptHeader([mime_type]):
+  response.setStatus(406)
+  return ""
+elif context.getPortalType() not in ["Software Instance", "Slave Instance"]:
+  response.setStatus(403)
+  return ""
+
+import json
+
+memcached_dict = context.getPortalObject().portal_memcached.getMemcachedDict(
+  key_prefix='slap_tool',
+  plugin_path='portal_memcached/default_memcached_plugin')
+try:
+  d = memcached_dict[context.getReference()]
+except KeyError:
+  d = {
+    "user": "SlapOS Master",
+    "text": "#error no data found for %s" % context.getReference()
+  }
+else:
+  d = json.loads(d)
+
+result_dict = {
+  'news': [d],
+  '_links': {
+    "self": { "href": context.Base_getRequestUrl() },
+    # XXX current type
+    "index": {
+      "href": "urn:jio:get:%s" % context.getRelativeUrl(),
+      "title": "Software Instance"
+    },
+  },
+}
+
+response.setHeader('Content-Type', mime_type)
+return json.dumps(result_dict, indent=2)
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasNews.xml b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasNews.xml
index 00a5b2dbe..0eab1640a 100644
--- a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasNews.xml
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasNews.xml
@@ -48,57 +48,6 @@
               </object>
             </value>
         </item>
-        <item>
-            <key> <string>_body</string> </key>
-            <value> <string>from zExceptions import Unauthorized\n
-from AccessControl import getSecurityManager\n
-if REQUEST is None:\n
-  raise Unauthorized\n
-\n
-response = REQUEST.RESPONSE\n
-mime_type = \'application/hal+json\'\n
-\n
-if REQUEST.other[\'method\'] != "GET":\n
-  response.setStatus(405)\n
-  return ""\n
-elif mime_type != context.Base_handleAcceptHeader([mime_type]):\n
-  response.setStatus(406)\n
-  return ""\n
-elif context.getPortalType() not in ["Software Instance", "Slave Instance"]:\n
-  response.setStatus(403)\n
-  return ""\n
-\n
-import json\n
-\n
-memcached_dict = context.getPortalObject().portal_memcached.getMemcachedDict(\n
-  key_prefix=\'slap_tool\',\n
-  plugin_path=\'portal_memcached/default_memcached_plugin\')\n
-try:\n
-  d = memcached_dict[context.getReference()]\n
-except KeyError:\n
-  d = {\n
-    "user": "SlapOS Master",\n
-    "text": "#error no data found for %s" % context.getReference()\n
-  }\n
-else:\n
-  d = json.loads(d)\n
-\n
-result_dict = {\n
-  \'news\': [d],\n
-  \'_links\': {\n
-    "self": { "href": context.Base_getRequestUrl() },\n
-    # XXX current type\n
-    "index": {\n
-      "href": "urn:jio:get:%s" % context.getRelativeUrl(),\n
-      "title": "Software Instance"\n
-    },\n
-  },\n
-}\n
-\n
-response.setHeader(\'Content-Type\', mime_type)\n
-return json.dumps(result_dict, indent=2)\n
-</string> </value>
-        </item>
         <item>
             <key> <string>_params</string> </key>
             <value> <string>REQUEST=None</string> </value>
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasRelatedHostingSubscription.py b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasRelatedHostingSubscription.py
new file mode 100644
index 000000000..414326be3
--- /dev/null
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasRelatedHostingSubscription.py
@@ -0,0 +1,42 @@
+from zExceptions import Unauthorized
+from AccessControl import getSecurityManager
+if REQUEST is None:
+  raise Unauthorized
+
+response = REQUEST.RESPONSE
+mime_type = 'application/hal+json'
+
+if REQUEST.other['method'] != "GET":
+  response.setStatus(405)
+  return ""
+elif mime_type != context.Base_handleAcceptHeader([mime_type]):
+  response.setStatus(406)
+  return ""
+elif context.getPortalType() not in ["Software Instance", "Slave Instance"]:
+  response.setStatus(403)
+  return ""
+
+if context.getSlapState() == "stop_requested":
+  state = 'stopped'
+elif context.getSlapState() == "start_requested":
+  state = 'started'
+else:
+  state = 'destroyed'
+
+import json
+result_dict = {
+  '_links': {
+    "self": { "href": context.Base_getRequestUrl() },
+    "index": {
+      "href": "urn:jio:get:%s" % context.getRelativeUrl(),
+      "title": "Software Instance",
+    },
+    'action_object_jump': {
+      "href": "%s/ERP5Document_getHateoas" %  context.getSpecialiseValue().getAbsoluteUrl(),
+      "title": "Hosting Subscription",
+    }
+  },
+}
+
+response.setHeader('Content-Type', mime_type)
+return json.dumps(result_dict, indent=2)
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasRelatedHostingSubscription.xml b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasRelatedHostingSubscription.xml
index 89016dac2..f91508e94 100644
--- a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasRelatedHostingSubscription.xml
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Instance_getHateoasRelatedHostingSubscription.xml
@@ -48,52 +48,6 @@
               </object>
             </value>
         </item>
-        <item>
-            <key> <string>_body</string> </key>
-            <value> <string>from zExceptions import Unauthorized\n
-from AccessControl import getSecurityManager\n
-if REQUEST is None:\n
-  raise Unauthorized\n
-\n
-response = REQUEST.RESPONSE\n
-mime_type = \'application/hal+json\'\n
-\n
-if REQUEST.other[\'method\'] != "GET":\n
-  response.setStatus(405)\n
-  return ""\n
-elif mime_type != context.Base_handleAcceptHeader([mime_type]):\n
-  response.setStatus(406)\n
-  return ""\n
-elif context.getPortalType() not in ["Software Instance", "Slave Instance"]:\n
-  response.setStatus(403)\n
-  return ""\n
-\n
-if context.getSlapState() == "stop_requested":\n
-  state = \'stopped\'\n
-elif context.getSlapState() == "start_requested":\n
-  state = \'started\'\n
-else:\n
-  state = \'destroyed\'\n
-\n
-import json\n
-result_dict = {\n
-  \'_links\': {\n
-    "self": { "href": context.Base_getRequestUrl() },\n
-    "index": {\n
-      "href": "urn:jio:get:%s" % context.getRelativeUrl(),\n
-      "title": "Software Instance",\n
-    },\n
-    \'action_object_jump\': {\n
-      "href": "%s/ERP5Document_getHateoas" %  context.getSpecialiseValue().getAbsoluteUrl(),\n
-      "title": "Hosting Subscription",\n
-    }\n
-  },\n
-}\n
-\n
-response.setHeader(\'Content-Type\', mime_type)\n
-return json.dumps(result_dict, indent=2)\n
-</string> </value>
-        </item>
         <item>
             <key> <string>_params</string> </key>
             <value> <string>REQUEST=None</string> </value>
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_getHateoasComputerList.py b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_getHateoasComputerList.py
new file mode 100644
index 000000000..e8766b192
--- /dev/null
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_getHateoasComputerList.py
@@ -0,0 +1,43 @@
+from zExceptions import Unauthorized
+from AccessControl import getSecurityManager
+if REQUEST is None:
+  raise Unauthorized
+
+response = REQUEST.RESPONSE
+mime_type = 'application/hal+json'
+
+if REQUEST.other['method'] != "GET":
+  response.setStatus(405)
+  return ""
+elif mime_type != context.Base_handleAcceptHeader([mime_type]):
+  response.setStatus(406)
+  return ""
+elif context.getPortalType() != "Person":
+  response.setStatus(403)
+  return ""
+
+import json
+result_dict = {
+  '_links': {
+    "self": { "href": context.Base_getRequestUrl() },
+    # XXX current type
+    "index": {
+      "href": "urn:jio:get:%s" % context.getRelativeUrl(),
+      "title": "Person"
+    },
+    "content": [],
+  },
+}
+
+for sql_obj in context.getPortalObject().portal_catalog(
+                                               portal_type="Computer",
+                                               default_source_administration_uid=context.getUid(),
+                                               ):
+  obj = sql_obj.getObject()
+  result_dict['_links']['content'].append({
+    'href': '%s/ERP5Document_getHateoas' % obj.absolute_url(),
+    'title': obj.getTitle(),
+  })
+
+response.setHeader('Content-Type', mime_type)
+return json.dumps(result_dict, indent=2)
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_getHateoasComputerList.xml b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_getHateoasComputerList.xml
index 517ed1e24..5c18becd6 100644
--- a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_getHateoasComputerList.xml
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_getHateoasComputerList.xml
@@ -48,53 +48,6 @@
               </object>
             </value>
         </item>
-        <item>
-            <key> <string>_body</string> </key>
-            <value> <string>from zExceptions import Unauthorized\n
-from AccessControl import getSecurityManager\n
-if REQUEST is None:\n
-  raise Unauthorized\n
-\n
-response = REQUEST.RESPONSE\n
-mime_type = \'application/hal+json\'\n
-\n
-if REQUEST.other[\'method\'] != "GET":\n
-  response.setStatus(405)\n
-  return ""\n
-elif mime_type != context.Base_handleAcceptHeader([mime_type]):\n
-  response.setStatus(406)\n
-  return ""\n
-elif context.getPortalType() != "Person":\n
-  response.setStatus(403)\n
-  return ""\n
-\n
-import json\n
-result_dict = {\n
-  \'_links\': {\n
-    "self": { "href": context.Base_getRequestUrl() },\n
-    # XXX current type\n
-    "index": {\n
-      "href": "urn:jio:get:%s" % context.getRelativeUrl(),\n
-      "title": "Person"\n
-    },\n
-    "content": [],\n
-  },\n
-}\n
-\n
-for sql_obj in context.getPortalObject().portal_catalog(\n
-                                               portal_type="Computer",\n
-                                               default_source_administration_uid=context.getUid(),\n
-                                               ):\n
-  obj = sql_obj.getObject()\n
-  result_dict[\'_links\'][\'content\'].append({\n
-    \'href\': \'%s/ERP5Document_getHateoas\' % obj.absolute_url(),\n
-    \'title\': obj.getTitle(),\n
-  })\n
-\n
-response.setHeader(\'Content-Type\', mime_type)\n
-return json.dumps(result_dict, indent=2)\n
-</string> </value>
-        </item>
         <item>
             <key> <string>_params</string> </key>
             <value> <string>REQUEST=None</string> </value>
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_getHateoasHostingSubscriptionList.py b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_getHateoasHostingSubscriptionList.py
new file mode 100644
index 000000000..4e04b61e7
--- /dev/null
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_getHateoasHostingSubscriptionList.py
@@ -0,0 +1,44 @@
+from zExceptions import Unauthorized
+from AccessControl import getSecurityManager
+if REQUEST is None:
+  raise Unauthorized
+
+response = REQUEST.RESPONSE
+mime_type = 'application/hal+json'
+
+if REQUEST.other['method'] != "GET":
+  response.setStatus(405)
+  return ""
+elif mime_type != context.Base_handleAcceptHeader([mime_type]):
+  response.setStatus(406)
+  return ""
+elif context.getPortalType() != "Person":
+  response.setStatus(403)
+  return ""
+
+import json
+result_dict = {
+  '_links': {
+    "self": { "href": context.Base_getRequestUrl() },
+    # XXX current type
+    "index": {
+      "href": "urn:jio:get:%s" % context.getRelativeUrl(),
+      "title": "Person"
+    },
+    "content": [],
+  },
+}
+
+for sql_obj in context.getPortalObject().portal_catalog(
+                                               portal_type="Hosting Subscription",
+                                               default_destination_section_uid=context.getUid(),
+                                               validation_state="validated"
+                                               ):
+  obj = sql_obj.getObject()
+  result_dict['_links']['content'].append({
+    'href': '%s/ERP5Document_getHateoas' % obj.absolute_url(),
+    'title': obj.getTitle()
+  })
+
+response.setHeader('Content-Type', mime_type)
+return json.dumps(result_dict, indent=2)
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_getHateoasHostingSubscriptionList.xml b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_getHateoasHostingSubscriptionList.xml
index c758fc3c7..a53af5ae8 100644
--- a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_getHateoasHostingSubscriptionList.xml
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_getHateoasHostingSubscriptionList.xml
@@ -48,54 +48,6 @@
               </object>
             </value>
         </item>
-        <item>
-            <key> <string>_body</string> </key>
-            <value> <string>from zExceptions import Unauthorized\n
-from AccessControl import getSecurityManager\n
-if REQUEST is None:\n
-  raise Unauthorized\n
-\n
-response = REQUEST.RESPONSE\n
-mime_type = \'application/hal+json\'\n
-\n
-if REQUEST.other[\'method\'] != "GET":\n
-  response.setStatus(405)\n
-  return ""\n
-elif mime_type != context.Base_handleAcceptHeader([mime_type]):\n
-  response.setStatus(406)\n
-  return ""\n
-elif context.getPortalType() != "Person":\n
-  response.setStatus(403)\n
-  return ""\n
-\n
-import json\n
-result_dict = {\n
-  \'_links\': {\n
-    "self": { "href": context.Base_getRequestUrl() },\n
-    # XXX current type\n
-    "index": {\n
-      "href": "urn:jio:get:%s" % context.getRelativeUrl(),\n
-      "title": "Person"\n
-    },\n
-    "content": [],\n
-  },\n
-}\n
-\n
-for sql_obj in context.getPortalObject().portal_catalog(\n
-                                               portal_type="Hosting Subscription",\n
-                                               default_destination_section_uid=context.getUid(),\n
-                                               validation_state="validated"\n
-                                               ):\n
-  obj = sql_obj.getObject()\n
-  result_dict[\'_links\'][\'content\'].append({\n
-    \'href\': \'%s/ERP5Document_getHateoas\' % obj.absolute_url(),\n
-    \'title\': obj.getTitle()\n
-  })\n
-\n
-response.setHeader(\'Content-Type\', mime_type)\n
-return json.dumps(result_dict, indent=2)\n
-</string> </value>
-        </item>
         <item>
             <key> <string>_params</string> </key>
             <value> <string>REQUEST=None</string> </value>
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_requestHateoasHostingSubscription.py b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_requestHateoasHostingSubscription.py
new file mode 100644
index 000000000..9593386e1
--- /dev/null
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_requestHateoasHostingSubscription.py
@@ -0,0 +1,53 @@
+from zExceptions import Unauthorized
+from AccessControl import getSecurityManager
+if REQUEST is None:
+  raise Unauthorized
+
+response = REQUEST.RESPONSE
+mime_type = 'application/json'
+
+if REQUEST.other['method'] != "POST":
+  response.setStatus(405)
+  return ""
+elif mime_type != context.Base_getRequestHeader('Content-Type'):
+  response.setStatus(406)
+  return ""
+elif context.getPortalType() != "Person":
+  response.setStatus(403)
+  return ""
+else:
+  import json
+  try:
+    data_dict = json.loads(context.Base_getRequestBody())
+  except (TypeError, ValueError):
+    response.setStatus(400)
+    return ""
+  else:
+
+    def dictToXml(dict_data):
+      assert same_type(dict_data, {})
+      result = "<?xml version='1.0' encoding='utf-8'?><instance>\n"
+      for key, value in dict_data.items():
+        result += """  <parameter id="%s">%s</parameter>\n""" % (key.encode("UTF-8"), value.encode("UTF-8"))
+      result += "</instance>"
+      return result
+
+    try:
+      parameter_kw = {
+        'software_release': data_dict['software_release'].encode("UTF-8"),
+        'software_title': data_dict['title'].encode("UTF-8"),
+        'software_type': data_dict['software_type'].encode("UTF-8"),
+        'instance_xml': dictToXml(data_dict['parameter']),
+        'sla_xml': dictToXml(data_dict['sla']),
+        'shared': data_dict['slave'],
+        'state': data_dict['status'].encode("UTF-8"),
+      }
+    except KeyError:
+      response.setStatus(400)
+      return ""
+    else:
+
+      context.requestSoftwareInstance(**parameter_kw)
+      # XXX Return hosting subscription link
+      response.setStatus(201)
+      return ""
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_requestHateoasHostingSubscription.xml b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_requestHateoasHostingSubscription.xml
index 124e2d2af..334e1ac02 100644
--- a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_requestHateoasHostingSubscription.xml
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/Person_requestHateoasHostingSubscription.xml
@@ -48,67 +48,6 @@
               </object>
             </value>
         </item>
-        <item>
-            <key> <string>_body</string> </key>
-            <value> <string encoding="cdata"><![CDATA[
-
-from zExceptions import Unauthorized\n
-from AccessControl import getSecurityManager\n
-if REQUEST is None:\n
-  raise Unauthorized\n
-\n
-response = REQUEST.RESPONSE\n
-mime_type = \'application/json\'\n
-\n
-if REQUEST.other[\'method\'] != "POST":\n
-  response.setStatus(405)\n
-  return ""\n
-elif mime_type != context.Base_getRequestHeader(\'Content-Type\'):\n
-  response.setStatus(406)\n
-  return ""\n
-elif context.getPortalType() != "Person":\n
-  response.setStatus(403)\n
-  return ""\n
-else:\n
-  import json\n
-  try:\n
-    data_dict = json.loads(context.Base_getRequestBody())\n
-  except (TypeError, ValueError):\n
-    response.setStatus(400)\n
-    return ""\n
-  else:\n
-\n
-    def dictToXml(dict_data):\n
-      assert same_type(dict_data, {})\n
-      result = "<?xml version=\'1.0\' encoding=\'utf-8\'?><instance>\\n"\n
-      for key, value in dict_data.items():\n
-        result += """  <parameter id="%s">%s</parameter>\\n""" % (key.encode("UTF-8"), value.encode("UTF-8"))\n
-      result += "</instance>"\n
-      return result\n
-\n
-    try:\n
-      parameter_kw = {\n
-        \'software_release\': data_dict[\'software_release\'].encode("UTF-8"),\n
-        \'software_title\': data_dict[\'title\'].encode("UTF-8"),\n
-        \'software_type\': data_dict[\'software_type\'].encode("UTF-8"),\n
-        \'instance_xml\': dictToXml(data_dict[\'parameter\']),\n
-        \'sla_xml\': dictToXml(data_dict[\'sla\']),\n
-        \'shared\': data_dict[\'slave\'],\n
-        \'state\': data_dict[\'status\'].encode("UTF-8"),\n
-      }\n
-    except KeyError:\n
-      response.setStatus(400)\n
-      return ""\n
-    else:\n
-\n
-      context.requestSoftwareInstance(**parameter_kw)\n
-      # XXX Return hosting subscription link\n
-      response.setStatus(201)\n
-      return ""\n
-
-
-]]></string> </value>
-        </item>
         <item>
             <key> <string>_params</string> </key>
             <value> <string>REQUEST=None</string> </value>
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/SoftwareInstallation_getHateoasInformation.py b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/SoftwareInstallation_getHateoasInformation.py
new file mode 100644
index 000000000..5e4ce1a10
--- /dev/null
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/SoftwareInstallation_getHateoasInformation.py
@@ -0,0 +1,44 @@
+from zExceptions import Unauthorized
+from AccessControl import getSecurityManager
+if REQUEST is None:
+  raise Unauthorized
+
+response = REQUEST.RESPONSE
+mime_type = 'application/hal+json'
+
+if REQUEST.other['method'] != "GET":
+  response.setStatus(405)
+  return ""
+elif mime_type != context.Base_handleAcceptHeader([mime_type]):
+  response.setStatus(406)
+  return ""
+elif context.getPortalType() not in ["Software Installation"]:
+  response.setStatus(403)
+  return ""
+else:
+
+  if context.getSlapState() == "stop_requested":
+    state = 'stopped'
+  elif context.getSlapState() == "start_requested":
+    state = 'started'
+  else:
+    state = 'destroyed'
+
+  import json
+  result_dict = {
+      'title': context.getTitle(),
+      'status': state,
+      '_links': {
+        "self": { "href": context.Base_getRequestUrl() },
+        "index": {
+          "href": "urn:jio:get:%s" % context.getRelativeUrl(),
+          "title": "Software Installation"
+        },
+      },
+    }
+  url_string = context.getUrlString(None)
+  if url_string is not None:
+    result_dict["_links"]["software_release"] = { "href": url_string }
+
+  response.setHeader('Content-Type', mime_type)
+  return json.dumps(result_dict)
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/SoftwareInstallation_getHateoasInformation.xml b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/SoftwareInstallation_getHateoasInformation.xml
index 58e7d05da..b2e4fb6fc 100644
--- a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/SoftwareInstallation_getHateoasInformation.xml
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/SoftwareInstallation_getHateoasInformation.xml
@@ -48,54 +48,6 @@
               </object>
             </value>
         </item>
-        <item>
-            <key> <string>_body</string> </key>
-            <value> <string>from zExceptions import Unauthorized\n
-from AccessControl import getSecurityManager\n
-if REQUEST is None:\n
-  raise Unauthorized\n
-\n
-response = REQUEST.RESPONSE\n
-mime_type = \'application/hal+json\'\n
-\n
-if REQUEST.other[\'method\'] != "GET":\n
-  response.setStatus(405)\n
-  return ""\n
-elif mime_type != context.Base_handleAcceptHeader([mime_type]):\n
-  response.setStatus(406)\n
-  return ""\n
-elif context.getPortalType() not in ["Software Installation"]:\n
-  response.setStatus(403)\n
-  return ""\n
-else:\n
-\n
-  if context.getSlapState() == "stop_requested":\n
-    state = \'stopped\'\n
-  elif context.getSlapState() == "start_requested":\n
-    state = \'started\'\n
-  else:\n
-    state = \'destroyed\'\n
-\n
-  import json\n
-  result_dict = {\n
-      \'title\': context.getTitle(),\n
-      \'status\': state,\n
-      \'_links\': {\n
-        "self": { "href": context.Base_getRequestUrl() },\n
-        "index": {\n
-          "href": "urn:jio:get:%s" % context.getRelativeUrl(),\n
-          "title": "Software Installation"\n
-        },\n
-      },\n
-    }\n
-  url_string = context.getUrlString(None)\n
-  if url_string is not None:\n
-    result_dict["_links"]["software_release"] = { "href": url_string }\n
-\n
-  response.setHeader(\'Content-Type\', mime_type)\n
-  return json.dumps(result_dict)\n
-</string> </value>
-        </item>
         <item>
             <key> <string>_params</string> </key>
             <value> <string>REQUEST=None</string> </value>
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/SoftwareInstallation_getHateoasNews.py b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/SoftwareInstallation_getHateoasNews.py
new file mode 100644
index 000000000..3b42dddfe
--- /dev/null
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/SoftwareInstallation_getHateoasNews.py
@@ -0,0 +1,48 @@
+from zExceptions import Unauthorized
+from AccessControl import getSecurityManager
+if REQUEST is None:
+  raise Unauthorized
+
+response = REQUEST.RESPONSE
+mime_type = 'application/hal+json'
+
+if REQUEST.other['method'] != "GET":
+  response.setStatus(405)
+  return ""
+elif mime_type != context.Base_handleAcceptHeader([mime_type]):
+  response.setStatus(406)
+  return ""
+elif context.getPortalType() not in ["Software Installation"]:
+  raise
+  response.setStatus(403)
+  return ""
+
+import json
+
+memcached_dict = context.getPortalObject().portal_memcached.getMemcachedDict(
+  key_prefix='slap_tool',
+  plugin_path='portal_memcached/default_memcached_plugin')
+try:
+  d = memcached_dict[context.getReference()]
+except KeyError:
+  d = {
+    "user": "SlapOS Master",
+    "text": "#error no data found for %s" % context.getReference()
+  }
+else:
+  d = json.loads(d)
+
+result_dict = {
+  'news': [d],
+  '_links': {
+    "self": { "href": context.Base_getRequestUrl() },
+    # XXX current type
+    "index": {
+      "href": "urn:jio:get:%s" % context.getRelativeUrl(),
+      "title": "Software Instance"
+    },
+  },
+}
+
+response.setHeader('Content-Type', mime_type)
+return json.dumps(result_dict, indent=2)
diff --git a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/SoftwareInstallation_getHateoasNews.xml b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/SoftwareInstallation_getHateoasNews.xml
index 86474053f..7e3af3d32 100644
--- a/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/SoftwareInstallation_getHateoasNews.xml
+++ b/master/bt5/slapos_hypermedia/SkinTemplateItem/portal_skins/slapos_hypermedia/SoftwareInstallation_getHateoasNews.xml
@@ -48,58 +48,6 @@
               </object>
             </value>
         </item>
-        <item>
-            <key> <string>_body</string> </key>
-            <value> <string>from zExceptions import Unauthorized\n
-from AccessControl import getSecurityManager\n
-if REQUEST is None:\n
-  raise Unauthorized\n
-\n
-response = REQUEST.RESPONSE\n
-mime_type = \'application/hal+json\'\n
-\n
-if REQUEST.other[\'method\'] != "GET":\n
-  response.setStatus(405)\n
-  return ""\n
-elif mime_type != context.Base_handleAcceptHeader([mime_type]):\n
-  response.setStatus(406)\n
-  return ""\n
-elif context.getPortalType() not in ["Software Installation"]:\n
-  raise\n
-  response.setStatus(403)\n
-  return ""\n
-\n
-import json\n
-\n
-memcached_dict = context.getPortalObject().portal_memcached.getMemcachedDict(\n
-  key_prefix=\'slap_tool\',\n
-  plugin_path=\'portal_memcached/default_memcached_plugin\')\n
-try:\n
-  d = memcached_dict[context.getReference()]\n
-except KeyError:\n
-  d = {\n
-    "user": "SlapOS Master",\n
-    "text": "#error no data found for %s" % context.getReference()\n
-  }\n
-else:\n
-  d = json.loads(d)\n
-\n
-result_dict = {\n
-  \'news\': [d],\n
-  \'_links\': {\n
-    "self": { "href": context.Base_getRequestUrl() },\n
-    # XXX current type\n
-    "index": {\n
-      "href": "urn:jio:get:%s" % context.getRelativeUrl(),\n
-      "title": "Software Instance"\n
-    },\n
-  },\n
-}\n
-\n
-response.setHeader(\'Content-Type\', mime_type)\n
-return json.dumps(result_dict, indent=2)\n
-</string> </value>
-        </item>
         <item>
             <key> <string>_params</string> </key>
             <value> <string>REQUEST=None</string> </value>
diff --git a/master/bt5/slapos_hypermedia/bt/dependency_list b/master/bt5/slapos_hypermedia/bt/dependency_list
index 1d14928a9..71869251c 100644
--- a/master/bt5/slapos_hypermedia/bt/dependency_list
+++ b/master/bt5/slapos_hypermedia/bt/dependency_list
@@ -1,3 +1,3 @@
 erp5_hal_json_style
 slapos_cloud
-slapos_slap_tool
+slapos_slap_tool
\ No newline at end of file
-- 
2.30.9