From 162fc8e0aa6d460ca17c8fcdb673c8c9aeabbc30 Mon Sep 17 00:00:00 2001 From: Roque <roqueporchetto@gmail.com> Date: Thu, 22 Feb 2018 17:00:55 +0100 Subject: [PATCH] tesnode: slapos master communicator handles frontend request - communicator considers requests of master frontend and instance destruction. - communicator retrieves frontend related information from instances. - minor refactoring and code cleanup. --- .../util/testnode/SlapOSMasterCommunicator.py | 104 +++++++++++++----- 1 file changed, 77 insertions(+), 27 deletions(-) diff --git a/erp5/util/testnode/SlapOSMasterCommunicator.py b/erp5/util/testnode/SlapOSMasterCommunicator.py index b5ad1a32aa..f1e0a3ef60 100644 --- a/erp5/util/testnode/SlapOSMasterCommunicator.py +++ b/erp5/util/testnode/SlapOSMasterCommunicator.py @@ -2,7 +2,7 @@ import datetime import json import traceback import time -#import feedparser +import requests from functools import wraps from uritemplate import expand @@ -12,8 +12,8 @@ from requests.exceptions import HTTPError from ..taskdistribution import SAFE_RPC_EXCEPTION_LIST from . import logger -# max time to instance changing state: 2 hour -MAX_INSTANCE_TIME = 60*60*2 +# max time to instance changing state: 3 hour +MAX_INSTANCE_TIME = 60*60*3 SOFTWARE_PRODUCT_NAMESPACE = "product." @@ -89,19 +89,24 @@ class SlapOSMasterCommunicator(object): return self.slap_supply.supply(self.url, self.computer_guid) @retryOnNetworkFailure - def _request(self, state, instance_title=None, request_kw=None): + def _request(self, state, instance_title=None, request_kw=None, shared=False, software_type="RootSoftwareInstance"): if instance_title is not None: self.name = instance_title if request_kw is not None: - if isinstance(request_kw, basestring): + if isinstance(request_kw, basestring) or \ + isinstance(request_kw, unicode): self.request_kw = json.loads(request_kw) else: self.request_kw = request_kw + if self.request_kw is None: + self.request_kw = {} logger.info('Request %s@%s: %s', self.url, self.name, state) self.latest_state = state return self.slap_order.request( software_release=self.url, + software_type="RootSoftwareInstance", partition_reference=self.name, + shared=shared, state=state, **self.request_kw) @@ -134,9 +139,9 @@ class SlapOSMasterCommunicator(object): @retryOnNetworkFailure - def getSoftwareInstallationList(self): - # XXX Move me to slap.py API - computer = self._hateoas_getComputer(self.computer_guid) + def getSoftwareInstallationList(self, computer_guid=None): + # XXX Move me to slap.py API + 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'] @@ -151,9 +156,9 @@ class SlapOSMasterCommunicator(object): @retryOnNetworkFailure - def getSoftwareInstallationNews(self): + def getSoftwareInstallationNews(self, computer_guid=None): getter_link = None - for si in self.getSoftwareInstallationList(): + for si in self.getSoftwareInstallationList(computer_guid): if si["title"] == self.url: getter_link = si["href"] break @@ -219,11 +224,12 @@ class SlapOSMasterCommunicator(object): result = self.hateoas_navigator.GET(object_link) return json.loads(result) - def _getSoftwareState(self): + def _getSoftwareState(self, computer_guid=None): if self.computer_guid is None: return SOFTWARE_STATE_INSTALLED - message = self.getSoftwareInstallationNews() + message = self.getSoftwareInstallationNews(computer_guid) + logger.info(message) if message.startswith("#error no data found"): return SOFTWARE_STATE_UNKNOWN @@ -288,6 +294,9 @@ class SlapOSMasterCommunicator(object): if instance_state['text'].startswith('#access Instance correctly stopped'): state = INSTANCE_STATE_STOPPED + if instance_state['text'].startswith('#destroy'): + state = INSTANCE_STATE_DESTROYED + if instance_state['text'].startswith('#error'): state = INSTANCE_STATE_STARTED_WITH_ERROR @@ -297,8 +306,8 @@ class SlapOSMasterCommunicator(object): try: monitor_information_dict = self.getRSSEntryFromMonitoring(monitor_v6_url) except Exception: - logger.exception('Unable to download promises for: %s', - instance["title"]) + logger.exception('Unable to download promises for: %s', instance["title"]) + logger.error(traceback.format_exc()) monitor_information_dict = {"message": "Unable to download"} message_list.append({ @@ -357,8 +366,7 @@ class SlapOSMasterCommunicator(object): if (time.time()-start_time) > max_time: error_message = "Instance '%s' not '%s' after %s seconds" %(instance_title, state, str(time.time()-start_time)) return {'error_message' : error_message} - logger.info("Instance correctly '%s' after %s seconds.", - state, time.time() - start_time) + logger.info("Instance correctly '%s' after %s seconds.", state, time.time() - start_time) return {'error_message' : None} class SlapOSTester(SlapOSMasterCommunicator): @@ -400,22 +408,20 @@ class SlapOSTester(SlapOSMasterCommunicator): self.computer_guid = computer_guid self._supply() - def requestInstanceStart(self, instance_title=None, request_kw=None): - self._request(INSTANCE_STATE_STARTED, instance_title, request_kw) + def requestInstanceStart(self, instance_title=None, request_kw=None, shared=False, software_type="RootSoftwareInstance"): + self.instance = self._request(INSTANCE_STATE_STARTED, instance_title, request_kw, shared, software_type) - def requestInstanceStop(self, instance_title=None, request_kw=None): - self._request(INSTANCE_STATE_STOPPED, instance_title, request_kw) + def requestInstanceStop(self, instance_title=None, request_kw=None, shared=False): + self._request(INSTANCE_STATE_STOPPED, instance_title, request_kw, shared) - def requestInstanceDestroy(self, instance_title=None, request_kw=None): - self._request(INSTANCE_STATE_DESTROYED, instance_title, request_kw) + def requestInstanceDestroy(self, instance_title=None, request_kw=None, shared=False): + self._request(INSTANCE_STATE_DESTROYED, instance_title, request_kw, shared) def waitInstanceStarted(self, instance_title): error_message = self._waitInstance(instance_title, INSTANCE_STATE_STARTED)["error_message"] if error_message is not None: logger.error(error_message) - logger.error("Do you use instance state propagation in your project?") - logger.error("Instance '%s' will be stopped and test aborted.", - instance_title) + logger.error("Instance '%s' will be stopped and test aborted.", instance_title) self.requestInstanceStop() time.sleep(60) raise ValueError(error_message) @@ -424,16 +430,60 @@ class SlapOSTester(SlapOSMasterCommunicator): error_message = self._waitInstance(instance_title, INSTANCE_STATE_STOPPED)["error_message"] if error_message is not None: logger.error(error_message) - logger.error("Do you use instance state propagation in your project?") raise ValueError(error_message) def waitInstanceDestroyed(self, instance_title): error_message = self._waitInstance(instance_title, INSTANCE_STATE_DESTROYED)["error_message"] if error_message is not None: logger.error(error_message) - logger.error("Do you use instance state propagation in your project?") raise ValueError(error_message) + def getMasterFrontendDict(self): + frontend_master_ipv6 = None + instance_guid = None + for instance in self.getInstanceUrlList(): + if instance["title"] == "Monitor Frontend apache-frontend-1": + try: + information = self.getInformationFromInstance(instance["href"]) + frontend_master_ipv6 = information['parameter_dict']['url'] + except Exception as e: + pass + return {'instance_guid' : self.instance.getInstanceGuid(), 'frontend_master_ipv6' : frontend_master_ipv6} + + def getInstanceUrlDict(self): + frontend_url_list = [] + zope_address_list = [] + for instance in self.getInstanceUrlList(): + information = self.getInformationFromInstance(instance["href"]) + if "frontend-" in instance["title"]: + try: + # TODO: this should get "secure_access" value (https). Until having a + # valid certificate, the "site_url" (http) will be used. + frontend = [instance["title"].replace("frontend-", ""), + information["connection_dict"]["site_url"]] + frontend_url_list.append(frontend) + except Exception as e: + logger.info("Frontend url not generated yet for instance: " + instance["title"]) + pass + if instance["title"] == self.name: + try: + connection_json = json.loads(information["connection_dict"]["_"]) + user = connection_json["inituser-login"] + password = connection_json["inituser-password"] + except Exception as e: + raise ValueError("user and password not found in connection parameters. Error while instantiating?") + if "zope-" in instance["title"]: + try: + connection_dict = information["connection_dict"]["_"] + address = json.loads(connection_dict)["zope-address-list"][0][0] + zope = [instance["title"].replace("zope-", ""), address] + zope_address_list.append(zope) + except Exception as e: + logger.info("zope address not found in connection parameters. Error while instantiating?") + pass + return {'zope-address-list' : zope_address_list, 'user' : user, + 'password' : password, 'frontend-url-list' : frontend_url_list } + class SoftwareReleaseTester(SlapOSTester): deadline = None -- 2.30.9