Commit c281ca18 authored by Rafael Monnerat's avatar Rafael Monnerat

erp5.util: Update the SlapOS API

  The API changed on the slap, this commit follow up the changes.
parent c5e2f481
...@@ -10,6 +10,8 @@ from uritemplate import expand ...@@ -10,6 +10,8 @@ from uritemplate import expand
import slapos.slap import slapos.slap
from slapos.slap import SoftwareProductCollection from slapos.slap import SoftwareProductCollection
from slapos.client import SOFTWARE_PRODUCT_NAMESPACE
from slapos.slap.util import xml2dict
from requests.exceptions import HTTPError from requests.exceptions import HTTPError
from ..taskdistribution import SAFE_RPC_EXCEPTION_LIST from ..taskdistribution import SAFE_RPC_EXCEPTION_LIST
from . import logger from . import logger
...@@ -19,8 +21,6 @@ import six ...@@ -19,8 +21,6 @@ import six
# max time to instance changing state: 3 hour # max time to instance changing state: 3 hour
MAX_INSTANCE_TIME = 60*60*3 MAX_INSTANCE_TIME = 60*60*3
SOFTWARE_PRODUCT_NAMESPACE = "product."
SOFTWARE_STATE_UNKNOWN = "SOFTWARE_STATE_UNKNOWN" SOFTWARE_STATE_UNKNOWN = "SOFTWARE_STATE_UNKNOWN"
SOFTWARE_STATE_INSTALLING = "SOFTWARE_STATE_INSTALLING" SOFTWARE_STATE_INSTALLING = "SOFTWARE_STATE_INSTALLING"
SOFTWARE_STATE_INSTALLED = "SOFTWARE_STATE_INSTALLED" SOFTWARE_STATE_INSTALLED = "SOFTWARE_STATE_INSTALLED"
...@@ -83,6 +83,10 @@ class SlapOSMasterCommunicator(object): ...@@ -83,6 +83,10 @@ class SlapOSMasterCommunicator(object):
self.url = url self.url = url
#########################################################
# Wrapper functions to support network retries
#########################################################
@retryOnNetworkFailure @retryOnNetworkFailure
def _supply(self, state="available"): def _supply(self, state="available"):
if self.computer_guid is None: if self.computer_guid is None:
...@@ -113,126 +117,35 @@ class SlapOSMasterCommunicator(object): ...@@ -113,126 +117,35 @@ class SlapOSMasterCommunicator(object):
state=state, state=state,
**self.request_kw) **self.request_kw)
@retryOnNetworkFailure
def isInstanceRequested(self, instance_title): def isInstanceRequested(self, instance_title):
hateoas = getattr(self.slap, '_hateoas_navigator', None) return len(self.hateoas_navigator._getHostingSubscriptionList(
return instance_title in hateoas.getHostingSubscriptionDict() title=instance_title))
@retryOnNetworkFailure @retryOnNetworkFailure
def _hateoas_getComputer(self, reference): def getComputer(self, reference):
root_document = self.hateoas_navigator.getRootDocument() return self.hateoas_navigator.getComputer(reference)
search_url = root_document["_links"]['raw_search']['href']
getter_link = expand(search_url, {
"query": "reference:%s AND portal_type:Computer" % reference,
"select_list": ["relative_url"],
"limit": 1})
result = self.hateoas_navigator.GET(getter_link)
content_list = json.loads(result)['_embedded']['contents']
if len(content_list) == 0:
raise Exception('No Computer found.')
computer_relative_url = content_list[0]["relative_url"]
getter_url = self.hateoas_navigator.getDocumentAndHateoas(
computer_relative_url)
return json.loads(self.hateoas_navigator.GET(getter_url))
@retryOnNetworkFailure @retryOnNetworkFailure
def getSoftwareInstallationList(self, computer_guid=None): def getSoftwareInstallationList(self, computer_guid=None):
# XXX Move me to slap.py API return self.hateoas_navigator.getSoftwareInstallationList(computer_guid=computer_guid)
computer = self._hateoas_getComputer(computer_guid) if computer_guid else self._hateoas_getComputer(self.computer_guid)
# Not a list ?
action = computer['_links']['action_object_slap']
if action.get('title') == 'getHateoasSoftwareInstallationList':
getter_link = action['href']
else:
raise Exception('No Link found found.')
result = self.hateoas_navigator.GET(getter_link)
return json.loads(result)['_links']['content']
@retryOnNetworkFailure
def getSoftwareInstallationNews(self, computer_guid=None):
getter_link = None
for si in self.getSoftwareInstallationList(computer_guid):
if si["title"] == self.url:
getter_link = si["href"]
break
# We could not find the document, so it is probably too soon.
if getter_link is None:
return ""
result = self.hateoas_navigator.GET(getter_link)
action_object_slap_list = json.loads(result)['_links']['action_object_slap']
for action in action_object_slap_list:
if action.get('title') == 'getHateoasNews':
getter_link = action['href']
break
else:
raise Exception('getHateoasNews not found.')
result = self.hateoas_navigator.GET(getter_link)
if len(json.loads(result)['news']) > 0:
return json.loads(result)['news'][0]["text"]
return ""
@retryOnNetworkFailure @retryOnNetworkFailure
def getInstanceUrlList(self): def getInstanceUrlList(self):
hosting_subscription_dict = self.hateoas_navigator._hateoas_getHostingSubscriptionDict() return self.hateoas_navigator.getHostingSubscriptionInstanceList(
# Don't store hosting subscription url. It changes from time to time. self.title)
hosting_subscription_url = None
for hs in hosting_subscription_dict:
if hs['title'] == self.name:
hosting_subscription_url = hs['href']
break
if hosting_subscription_url is None:
return None
return self.hateoas_navigator.getHateoasInstanceList(
hosting_subscription_url)
@retryOnNetworkFailure
def getNewsFromInstance(self, url):
result = self.hateoas_navigator.GET(url)
result = json.loads(result)
if result['_links'].get('action_object_slap', None) is None:
return None
object_link = self.hateoas_navigator.hateoasGetLinkFromLinks(
result['_links']['action_object_slap'], 'getHateoasNews')
result = self.hateoas_navigator.GET(object_link)
return json.loads(result)['news']
@retryOnNetworkFailure @retryOnNetworkFailure
def getInformationFromInstance(self, url): def getInformationFromInstance(self, url):
result = self.hateoas_navigator.GET(url) return self.hateoas_navigator.jio_get(url)
result = json.loads(result)
if result['_links'].get('action_object_slap', None) is None:
print(result['links'])
return None
object_link = self.hateoas_navigator.hateoasGetLinkFromLinks(
result['_links']['action_object_slap'], 'getHateoasInformation')
result = self.hateoas_navigator.GET(object_link)
return json.loads(result)
@retryOnNetworkFailure
def _getSoftwareState(self, computer_guid=None): def _getSoftwareState(self, computer_guid=None):
if self.computer_guid is None: if self.computer_guid is None:
return SOFTWARE_STATE_INSTALLED return SOFTWARE_STATE_INSTALLED
message = self.getSoftwareInstallationNews(computer_guid) message = self.hateoas_navigator.getSoftwareInstallationNews(
computer_guid=computer_guid, self.url)
logger.info(message) logger.info(message)
if message.startswith("#error no data found"): if message.startswith("#error no data found"):
return SOFTWARE_STATE_UNKNOWN return SOFTWARE_STATE_UNKNOWN
...@@ -270,19 +183,18 @@ class SlapOSMasterCommunicator(object): ...@@ -270,19 +183,18 @@ class SlapOSMasterCommunicator(object):
message_list = [] message_list = []
try: try:
for instance in self.getInstanceUrlList(): for instance in self.getInstanceUrlList():
news = self.getNewsFromInstance(instance["href"]) news = instance['SoftwareInstance_getNewsDict']
information = self.getInformationFromInstance(instance["href"])
state = INSTANCE_STATE_UNKNOWN state = INSTANCE_STATE_UNKNOWN
monitor_information_dict = {} monitor_information_dict = {}
info_created_at = "-1" info_created_at = "-1"
is_slave = information['slave'] is_slave = instance['portal_type'] == "Slave Instance"
if is_slave: if is_slave:
if (information["connection_dict"]) > 0: if len(instance['getConnectionXmlAsDict']) > 0:
state = INSTANCE_STATE_STARTED state = INSTANCE_STATE_STARTED
else: else:
# not slave # not slave
instance_state = news[0] instance_state = news
if instance_state.get('created_at', '-1') != "-1": if instance_state.get('created_at', '-1') != "-1":
# the following does NOT take TZ into account # the following does NOT take TZ into account
created_at = datetime.datetime.strptime(instance_state['created_at'], created_at = datetime.datetime.strptime(instance_state['created_at'],
...@@ -306,7 +218,7 @@ class SlapOSMasterCommunicator(object): ...@@ -306,7 +218,7 @@ class SlapOSMasterCommunicator(object):
if state == INSTANCE_STATE_STARTED_WITH_ERROR: if state == INSTANCE_STATE_STARTED_WITH_ERROR:
# search for monitor url # search for monitor url
monitor_v6_url = information["connection_dict"].get("monitor_v6_url") monitor_v6_url = instance['getConnectionXmlAsDict'].get("monitor_v6_url")
try: try:
monitor_information_dict = self.getRSSEntryFromMonitoring(monitor_v6_url) monitor_information_dict = self.getRSSEntryFromMonitoring(monitor_v6_url)
except Exception: except Exception:
...@@ -314,11 +226,13 @@ class SlapOSMasterCommunicator(object): ...@@ -314,11 +226,13 @@ class SlapOSMasterCommunicator(object):
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())
monitor_information_dict = {"message": "Unable to download"} monitor_information_dict = {"message": "Unable to download"}
instance["connection_dict"] = instance["getConnectionXmlAsDict"]
instance["parameter_dict"] = xml2dict(instance["text_content"]))
message_list.append({ message_list.append({
'title': instance["title"], 'title': instance["title"],
'slave': is_slave, 'slave': is_slave,
'news': news[0], 'news': news,
'information': information, 'information': instance,
'monitor': monitor_information_dict, 'monitor': monitor_information_dict,
'state': state 'state': state
}) })
...@@ -456,8 +370,7 @@ class SlapOSTester(SlapOSMasterCommunicator): ...@@ -456,8 +370,7 @@ class SlapOSTester(SlapOSMasterCommunicator):
for instance in self.getInstanceUrlList(): for instance in self.getInstanceUrlList():
if instance["title"] == "Monitor Frontend apache-frontend-1": if instance["title"] == "Monitor Frontend apache-frontend-1":
try: try:
information = self.getInformationFromInstance(instance["href"]) frontend_master_ipv6 = xml2dict(instance['text_content'])['url']
frontend_master_ipv6 = information['parameter_dict']['url']
except Exception as e: except Exception as e:
pass pass
start_time = time.time() start_time = time.time()
...@@ -471,18 +384,17 @@ class SlapOSTester(SlapOSMasterCommunicator): ...@@ -471,18 +384,17 @@ class SlapOSTester(SlapOSMasterCommunicator):
def getInstanceUrlDict(self): def getInstanceUrlDict(self):
frontend_url_list = [] frontend_url_list = []
for instance in self.getInstanceUrlList(): for instance in self.getInstanceUrlList():
information = self.getInformationFromInstance(instance["href"])
if "frontend-" in instance["title"]: if "frontend-" in instance["title"]:
try: try:
frontend = [instance["title"].replace("frontend-", ""), frontend = [instance["title"].replace("frontend-", ""),
information["connection_dict"]["secure_access"]] instance["getConnectionXmlAsDict"]["secure_access"]]
frontend_url_list.append(frontend) frontend_url_list.append(frontend)
except Exception as e: except Exception as e:
logger.info("Frontend url not generated yet for instance: " + instance["title"]) logger.info("Frontend url not generated yet for instance: " + instance["title"])
pass pass
if instance["title"] == self.name: if instance["title"] == self.name:
try: try:
connection_json = json.loads(information["connection_dict"]["_"]) connection_json = json.loads(instance["getConnectionXmlAsDict"]["_"])
user = connection_json["inituser-login"] user = connection_json["inituser-login"]
password = connection_json["inituser-password"] password = connection_json["inituser-password"]
except Exception as e: except Exception as e:
...@@ -491,8 +403,9 @@ class SlapOSTester(SlapOSMasterCommunicator): ...@@ -491,8 +403,9 @@ class SlapOSTester(SlapOSMasterCommunicator):
def destroyInstance(self, instance_title): def destroyInstance(self, instance_title):
self.name = instance_title self.name = instance_title
if self.getInstanceUrlList(): instance_url_list = self.InstanceUrlList()
for instance in self.getInstanceUrlList(): if instance_url_list:
for instance in instance_url_list:
if instance["title"] != instance_title: if instance["title"] != instance_title:
self._request(INSTANCE_STATE_DESTROYED, instance["title"]) self._request(INSTANCE_STATE_DESTROYED, instance["title"])
else: else:
......
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