From 4639f15e6db2f1480b41f6fbfd11d70312d4e421 Mon Sep 17 00:00:00 2001 From: Tomi Juvonen Date: Thu, 8 Mar 2018 07:13:36 +0200 Subject: Add maintenance test code -Add sample admin_tool -Add sample app_manager -Modify sample inspector JIRA: DOCTOR-106 Change-Id: I52cffecaa88452ce5e7cc6487534c88fcfd378ad Signed-off-by: Tomi Juvonen --- doctor_tests/scenario/maintenance.py | 103 ++++++++++++++++++++++++++++++++--- 1 file changed, 96 insertions(+), 7 deletions(-) (limited to 'doctor_tests/scenario') diff --git a/doctor_tests/scenario/maintenance.py b/doctor_tests/scenario/maintenance.py index bb0e943b..54244d79 100644 --- a/doctor_tests/scenario/maintenance.py +++ b/doctor_tests/scenario/maintenance.py @@ -6,9 +6,17 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## +import datetime +import json +import requests +import time + +from doctor_tests.admin_tool import get_admin_tool +from doctor_tests.app_manager import get_app_manager from doctor_tests.common.utils import get_doctor_test_root_dir from doctor_tests.identity_auth import get_identity_auth from doctor_tests.identity_auth import get_session +from doctor_tests.inspector import get_inspector from doctor_tests.os_clients import keystone_client from doctor_tests.os_clients import neutron_client from doctor_tests.os_clients import nova_client @@ -17,7 +25,7 @@ from doctor_tests.stack import Stack class Maintenance(object): - def __init__(self, conf, log): + def __init__(self, trasport_url, conf, log): self.conf = conf self.log = log self.keystone = keystone_client( @@ -26,6 +34,9 @@ class Maintenance(object): auth = get_identity_auth(project=self.conf.doctor_project) self.neutron = neutron_client(get_session(auth=auth)) self.stack = Stack(self.conf, self.log) + self.admin_tool = get_admin_tool(trasport_url, self.conf, self.log) + self.app_manager = get_app_manager(self.stack, self.conf, self.log) + self.inspector = get_inspector(self.conf, self.log) def get_external_network(self): ext_net = None @@ -35,7 +46,7 @@ class Maintenance(object): ext_net = network['name'] break if ext_net is None: - raise Exception("externl network not defined") + raise Exception("external network not defined") return ext_net def setup_maintenance(self, user): @@ -43,14 +54,15 @@ class Maintenance(object): # need to be free before test hvisors = self.nova.hypervisors.list(detailed=True) prev_vcpus = 0 - prev_hostname = "" + prev_hostname = '' self.log.info('checking hypervisors.......') for hvisor in hvisors: - vcpus = hvisor.__getattr__("vcpus") - vcpus_used = hvisor.__getattr__("vcpus_used") - hostname = hvisor.__getattr__("hypervisor_hostname") + vcpus = hvisor.__getattr__('vcpus') + vcpus_used = hvisor.__getattr__('vcpus_used') + hostname = hvisor.__getattr__('hypervisor_hostname') if vcpus < 2: - raise Exception('not enough vcpus on %s' % hostname) + raise Exception('not enough vcpus (%d) on %s' % + (vcpus, hostname)) if vcpus_used > 0: raise Exception('%d vcpus used on %s' % (vcpus_used, hostname)) @@ -98,6 +110,83 @@ class Maintenance(object): parameters=parameters, files=files) + self.admin_tool.start() + self.app_manager.start() + self.inspector.start() + + def start_maintenance(self): + self.log.info('start maintenance.......') + hvisors = self.nova.hypervisors.list(detailed=True) + maintenance_hosts = list() + for hvisor in hvisors: + hostname = hvisor.__getattr__('hypervisor_hostname') + maintenance_hosts.append(hostname) + + url = 'http://0.0.0.0:%s/maintenance' % self.conf.admin_tool.port + # let's start maintenance 20sec from now, so projects will have + # time to ACK to it before that + maintenance_at = (datetime.datetime.utcnow() + + datetime.timedelta(seconds=20) + ).strftime('%Y-%m-%d %H:%M:%S') + data = {'hosts': maintenance_hosts, + 'state': 'MAINTENANCE', + 'maintenance_at': maintenance_at, + 'metadata': {'openstack_version': 'Pike'}} + headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json'} + + ret = requests.post(url, data=json.dumps(data), headers=headers) + if ret.status_code != 200: + raise Exception(ret.text) + return ret.json()['session_id'] + + def remove_maintenance_session(self, session_id): + self.log.info('remove maintenance session %s.......' % session_id) + + url = 'http://0.0.0.0:%s/maintenance' % self.conf.admin_tool.port + + data = {'state': 'REMOVE_MAINTENANCE_SESSION', + 'session_id': session_id} + headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json'} + + ret = requests.post(url, data=json.dumps(data), headers=headers) + if ret.status_code != 200: + raise Exception(ret.text) + + def get_maintenance_state(self, session_id): + url = 'http://0.0.0.0:%s/maintenance' % self.conf.admin_tool.port + data = {'session_id': session_id} + headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json'} + ret = requests.get(url, data=json.dumps(data), headers=headers) + if ret.status_code != 200: + raise Exception(ret.text) + return ret.json()['state'] + + def wait_maintenance_complete(self, session_id): + retries = 60 + state = None + time.sleep(600) + while state != 'MAINTENANCE_COMPLETE' and retries > 0: + time.sleep(10) + state = self.get_maintenance_state(session_id) + retries = retries - 1 + if retries == 0 and state != 'MAINTENANCE_COMPLETE': + raise Exception('maintenance %s not completed within 20min, status' + ' %s' % (session_id, state)) + elif state == 'MAINTENANCE_COMPLETE': + self.log.info('maintenance %s %s' % (session_id, state)) + self.remove_maintenance_session(session_id) + elif state == 'MAINTENANCE_FAILED': + raise Exception('maintenance %s failed' % session_id) + def cleanup_maintenance(self): + self.admin_tool.stop() + self.app_manager.stop() + self.inspector.stop() self.log.info('stack delete start.......') self.stack.delete() -- cgit 1.2.3-korg