From b54cbc5dd2d32fcb27238680b4657ed384d021c5 Mon Sep 17 00:00:00 2001 From: Tomi Juvonen Date: Wed, 17 Jan 2018 10:20:44 +0200 Subject: Add setup and cleanup for maintenance test JIRA: DOCTOR-106 Change-Id: Idb95e1391e8f9094f68e2c7bc79fd2d7e01af9de Signed-off-by: Tomi Juvonen --- doctor_tests/installer/apex.py | 81 ++++++++++-- doctor_tests/installer/base.py | 38 ++++-- .../installer/common/restore_ceilometer.py | 27 ---- .../installer/common/restore_compute_config.py | 25 ++++ doctor_tests/installer/common/restore_config.py | 55 ++++++++ doctor_tests/installer/common/set_ceilometer.py | 45 ------- .../installer/common/set_compute_config.py | 48 +++++++ doctor_tests/installer/common/set_config.py | 139 +++++++++++++++++++++ 8 files changed, 360 insertions(+), 98 deletions(-) delete mode 100644 doctor_tests/installer/common/restore_ceilometer.py create mode 100644 doctor_tests/installer/common/restore_compute_config.py create mode 100644 doctor_tests/installer/common/restore_config.py delete mode 100644 doctor_tests/installer/common/set_ceilometer.py create mode 100644 doctor_tests/installer/common/set_compute_config.py create mode 100644 doctor_tests/installer/common/set_config.py (limited to 'doctor_tests/installer') diff --git a/doctor_tests/installer/apex.py b/doctor_tests/installer/apex.py index c851b2ac..121767fc 100644 --- a/doctor_tests/installer/apex.py +++ b/doctor_tests/installer/apex.py @@ -6,14 +6,19 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## +import re +import time + from doctor_tests.common.utils import SSHClient from doctor_tests.installer.base import BaseInstaller class ApexInstaller(BaseInstaller): node_user_name = 'heat-admin' - cm_set_script = 'set_ceilometer.py' - cm_restore_script = 'restore_ceilometer.py' + cm_set_script = 'set_config.py' + cm_set_compute_script = 'set_compute_config.py' + cm_restore_script = 'restore_config.py' + cm_restore_compute_script = 'restore_compute_config.py' def __init__(self, conf, log): super(ApexInstaller, self).__init__(conf, log) @@ -23,13 +28,15 @@ class ApexInstaller(BaseInstaller): look_for_keys=True) self.key_file = None self.controllers = list() + self.computes = list() self.controller_clients = list() + self.compute_clients = list() def setup(self): self.log.info('Setup Apex installer start......') self.key_file = self.get_ssh_key_from_installer() - self.controllers = self.get_controller_ips() + self._get_and_set_ips() self.create_flavor() self.set_apply_patches() self.setup_stunnel() @@ -43,16 +50,20 @@ class ApexInstaller(BaseInstaller): key_path = '/home/stack/.ssh/id_rsa' return self._get_ssh_key(self.client, key_path) - def get_controller_ips(self): - self.log.info('Get controller ips from Apex installer......') - - command = "source stackrc; " \ - "nova list | grep ' overcloud-controller-[0-9] ' " \ - "| sed -e 's/^.*ctlplane=//' |awk '{print $1}'" - controllers = self._run_cmd_remote(self.client, command) - self.log.info('Get controller_ips:%s from Apex installer' - % controllers) - return controllers + def _get_and_set_ips(self): + self.log.info('Get controller and compute ips from Apex installer' + '......') + + command = "source stackrc; nova list | grep ' overcloud-'" + raw_ips_list = self._run_cmd_remote(self.client, command) + for line in raw_ips_list: + ip = line.split('ctlplane=', 1)[1].split(" ", 1)[0] + if 'overcloud-controller-' in line: + self.controllers.append(ip) + elif 'overcloud-novacompute-' in line: + self.computes.append(ip) + self.log.info('controller_ips:%s' % self.controllers) + self.log.info('compute_ips:%s' % self.computes) def get_host_ip_from_hostname(self, hostname): self.log.info('Get host ip by hostname=%s from Apex installer......' @@ -63,12 +74,31 @@ class ApexInstaller(BaseInstaller): host_ips = self._run_cmd_remote(self.client, command) return host_ips[0] + def get_transport_url(self): + client = SSHClient(self.controllers[0], self.node_user_name, + key_filename=self.key_file) + + command = 'sudo grep "^transport_url" /etc/nova/nova.conf' + ret, url = client.ssh(command) + if ret: + raise Exception('Exec command to get host ip from controller(%s)' + 'in Apex installer failed, ret=%s, output=%s' + % (self.controllers[0], ret, url)) + # need to use ip instead of hostname + ret = (re.sub("@.*:", "@%s:" % self.controllers[0], + url[0].split("=", 1)[1])) + self.log.debug('get_transport_url %s' % ret) + return ret + def set_apply_patches(self): self.log.info('Set apply patches start......') restart_cm_cmd = 'sudo systemctl restart ' \ 'openstack-ceilometer-notification.service' + if self.conf.test_case != 'fault_management': + restart_cm_cmd += ' openstack-nova-scheduler.service' + for node_ip in self.controllers: client = SSHClient(node_ip, self.node_user_name, key_filename=self.key_file) @@ -77,13 +107,38 @@ class ApexInstaller(BaseInstaller): restart_cm_cmd, self.cm_set_script) + if self.conf.test_case != 'fault_management': + restart_cm_cmd = 'sudo systemctl restart ' \ + 'openstack-nova-compute.service' + for node_ip in self.computes: + client = SSHClient(node_ip, self.node_user_name, + key_filename=self.key_file) + self.compute_clients.append(client) + self._run_apply_patches(client, + restart_cm_cmd, + self.cm_set_compute_script) + + if self.conf.test_case != 'fault_management': + time.sleep(10) + def restore_apply_patches(self): self.log.info('restore apply patches start......') restart_cm_cmd = 'sudo systemctl restart ' \ 'openstack-ceilometer-notification.service' + if self.conf.test_case != 'fault_management': + restart_cm_cmd += ' openstack-nova-scheduler.service' + for client in self.controller_clients: self._run_apply_patches(client, restart_cm_cmd, self.cm_restore_script) + + if self.conf.test_case != 'fault_management': + restart_cm_cmd = 'sudo systemctl restart ' \ + 'openstack-nova-compute.service' + for client in self.compute_clients: + self._run_apply_patches(client, + restart_cm_cmd, + self.cm_restore_compute_script) diff --git a/doctor_tests/installer/base.py b/doctor_tests/installer/base.py index f37b7f1a..4eed3f29 100644 --- a/doctor_tests/installer/base.py +++ b/doctor_tests/installer/base.py @@ -58,21 +58,33 @@ class BaseInstaller(object): def setup_stunnel(self): self.log.info('Setup ssh stunnel in %s installer......' % self.conf.installer.type) + tunnels = [self.conf.consumer.port] + if self.conf.test_case == 'maintenance': + tunnel_uptime = 1200 + tunnels += [self.conf.app_manager.port, self.conf.inspector.port] + elif self.conf.test_case == 'all': + tunnel_uptime = 1800 + tunnels += [self.conf.app_manager.port, self.conf.inspector.port] + else: + tunnel_uptime = 600 for node_ip in self.controllers: - cmd = ("ssh -o UserKnownHostsFile=/dev/null" - " -o StrictHostKeyChecking=no" - " -i %s %s@%s -R %s:localhost:%s" - " sleep 600 > ssh_tunnel.%s" - " 2>&1 < /dev/null " - % (self.key_file, - self.node_user_name, - node_ip, - self.conf.consumer.port, - self.conf.consumer.port, - node_ip)) - server = subprocess.Popen('exec ' + cmd, shell=True) - self.servers.append(server) + for port in tunnels: + self.log.info('tunnel for port %s' % port) + cmd = ("ssh -o UserKnownHostsFile=/dev/null" + " -o StrictHostKeyChecking=no" + " -i %s %s@%s -R %s:localhost:%s" + " sleep %s > ssh_tunnel.%s" + " 2>&1 < /dev/null " + % (self.key_file, + self.node_user_name, + node_ip, + port, + port, + tunnel_uptime, + node_ip)) + server = subprocess.Popen('exec ' + cmd, shell=True) + self.servers.append(server) def _get_ssh_key(self, client, key_path): self.log.info('Get SSH keys from %s installer......' diff --git a/doctor_tests/installer/common/restore_ceilometer.py b/doctor_tests/installer/common/restore_ceilometer.py deleted file mode 100644 index d25b9ede..00000000 --- a/doctor_tests/installer/common/restore_ceilometer.py +++ /dev/null @@ -1,27 +0,0 @@ -############################################################################## -# Copyright (c) 2017 ZTE Corporation and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## -import os -import shutil - -ep_file = '/etc/ceilometer/event_pipeline.yaml' -ep_file_bak = '/etc/ceilometer/event_pipeline.yaml.bak' - - -def restore_ep_config(): - - if not os.path.isfile(ep_file_bak): - print('Bak_file:%s does not exist.' % ep_file_bak) - else: - print('restore') - shutil.copyfile(ep_file_bak, ep_file) - os.remove(ep_file_bak) - return - - -restore_ep_config() diff --git a/doctor_tests/installer/common/restore_compute_config.py b/doctor_tests/installer/common/restore_compute_config.py new file mode 100644 index 00000000..0971d12b --- /dev/null +++ b/doctor_tests/installer/common/restore_compute_config.py @@ -0,0 +1,25 @@ +############################################################################## +# Copyright (c) 2018 Nokia Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +import os +import shutil + + +def restore_cpu_allocation_ratio(): + nova_file = '/etc/nova/nova.conf' + nova_file_bak = '/etc/nova/nova.bak' + + if not os.path.isfile(nova_file_bak): + print('Bak_file:%s does not exist.' % nova_file_bak) + else: + print('restore: %s' % nova_file) + shutil.copyfile(nova_file_bak, nova_file) + os.remove(nova_file_bak) + return + +restore_cpu_allocation_ratio() diff --git a/doctor_tests/installer/common/restore_config.py b/doctor_tests/installer/common/restore_config.py new file mode 100644 index 00000000..c1f919c1 --- /dev/null +++ b/doctor_tests/installer/common/restore_config.py @@ -0,0 +1,55 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +import os +import shutil + +ep_file = '/etc/ceilometer/event_pipeline.yaml' +ep_file_bak = '/etc/ceilometer/event_pipeline.yaml.bak' + + +def restore_ep_config(): + + if not os.path.isfile(ep_file_bak): + print('Bak_file:%s does not exist.' % ep_file_bak) + else: + print('restore') + shutil.copyfile(ep_file_bak, ep_file) + os.remove(ep_file_bak) + return + + +def restore_ed_config(): + + ed_file = '/etc/ceilometer/event_definitions.yaml' + ed_file_bak = '/etc/ceilometer/event_definitions.bak' + + if not os.path.isfile(ed_file_bak): + print("Bak_file doesn't exist: %s." % ed_file_bak) + else: + print('restore: %s' % ed_file) + shutil.copyfile(ed_file_bak, ed_file) + os.remove(ed_file_bak) + return + + +def restore_cpu_allocation_ratio(): + nova_file = '/etc/nova/nova.conf' + nova_file_bak = '/etc/nova/nova.bak' + + if not os.path.isfile(nova_file_bak): + print('Bak_file:%s does not exist.' % nova_file_bak) + else: + print('restore: %s' % nova_file) + shutil.copyfile(nova_file_bak, nova_file) + os.remove(nova_file_bak) + return + +restore_ep_config() +restore_ed_config() +restore_cpu_allocation_ratio() diff --git a/doctor_tests/installer/common/set_ceilometer.py b/doctor_tests/installer/common/set_ceilometer.py deleted file mode 100644 index 4050aaef..00000000 --- a/doctor_tests/installer/common/set_ceilometer.py +++ /dev/null @@ -1,45 +0,0 @@ -############################################################################## -# Copyright (c) 2017 ZTE Corporation and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## -import os -import shutil -import yaml - -ep_file = '/etc/ceilometer/event_pipeline.yaml' -ep_file_bak = '/etc/ceilometer/event_pipeline.yaml.bak' -event_notifier_topic = 'notifier://?topic=alarm.all' - - -def set_notifier_topic(): - config_modified = False - - if not os.path.isfile(ep_file): - raise Exception("File doesn't exist: %s." % ep_file) - - with open(ep_file, 'r') as file: - config = yaml.safe_load(file) - - sinks = config['sinks'] - for sink in sinks: - if sink['name'] == 'event_sink': - publishers = sink['publishers'] - if event_notifier_topic not in publishers: - print('Add event notifier in ceilometer') - publishers.append(event_notifier_topic) - config_modified = True - else: - print('NOTE: event notifier is configured' - 'in ceilometer as we needed') - - if config_modified: - shutil.copyfile(ep_file, ep_file_bak) - with open(ep_file, 'w+') as file: - file.write(yaml.safe_dump(config)) - - -set_notifier_topic() diff --git a/doctor_tests/installer/common/set_compute_config.py b/doctor_tests/installer/common/set_compute_config.py new file mode 100644 index 00000000..07db1e16 --- /dev/null +++ b/doctor_tests/installer/common/set_compute_config.py @@ -0,0 +1,48 @@ +############################################################################## +# Copyright (c) 2018 Nokia Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +import os +import shutil + + +def set_cpu_allocation_ratio(): + nova_file = '/etc/nova/nova.conf' + nova_file_bak = '/etc/nova/nova.bak' + + if not os.path.isfile(nova_file): + raise Exception("File doesn't exist: %s." % nova_file) + # TODO (tojuvone): Unfortunately ConfigParser did not produce working conf + fcheck = open(nova_file) + found_list = ([ca for ca in fcheck.readlines() if "cpu_allocation_ratio" + in ca]) + fcheck.close() + if found_list and len(found_list): + change = False + found = False + for car in found_list: + if car.startswith('#'): + continue + if car.startswith('cpu_allocation_ratio'): + found = True + if "1.0" not in car.split('=')[1]: + change = True + if not found or change: + # need to add or change + shutil.copyfile(nova_file, nova_file_bak) + fin = open(nova_file_bak) + fout = open(nova_file, "wt") + for line in fin: + if change and line.startswith("cpu_allocation_ratio"): + line = "cpu_allocation_ratio=1.0" + if not found and line.startswith("[DEFAULT]"): + line += "cpu_allocation_ratio=1.0\n" + fout.write(line) + fin.close() + fout.close() + +set_cpu_allocation_ratio() diff --git a/doctor_tests/installer/common/set_config.py b/doctor_tests/installer/common/set_config.py new file mode 100644 index 00000000..42465247 --- /dev/null +++ b/doctor_tests/installer/common/set_config.py @@ -0,0 +1,139 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +import os +import shutil +import yaml + +ep_file = '/etc/ceilometer/event_pipeline.yaml' +ep_file_bak = '/etc/ceilometer/event_pipeline.yaml.bak' +event_notifier_topic = 'notifier://?topic=alarm.all' + + +def set_notifier_topic(): + config_modified = False + + if not os.path.isfile(ep_file): + raise Exception("File doesn't exist: %s." % ep_file) + + with open(ep_file, 'r') as file: + config = yaml.safe_load(file) + + sinks = config['sinks'] + for sink in sinks: + if sink['name'] == 'event_sink': + publishers = sink['publishers'] + if event_notifier_topic not in publishers: + print('Add event notifier in ceilometer') + publishers.append(event_notifier_topic) + config_modified = True + else: + print('NOTE: event notifier is configured' + 'in ceilometer as we needed') + + if config_modified: + shutil.copyfile(ep_file, ep_file_bak) + with open(ep_file, 'w+') as file: + file.write(yaml.safe_dump(config)) + + +def set_maintenance_event_definitions(): + ed_file = '/etc/ceilometer/event_definitions.yaml' + ed_file_bak = '/etc/ceilometer/event_definitions.bak' + + if not os.path.isfile(ed_file): + raise Exception("File doesn't exist: %s." % ed_file) + + with open(ed_file, 'r') as file: + config = yaml.safe_load(file) + + et_list = [et['event_type'] for et in config] + + if 'maintenance.scheduled' in et_list: + add_mscheduled = False + print('NOTE: maintenance.scheduled allready configured') + else: + print('NOTE: add maintenance.scheduled to event_definitions.yaml') + add_mscheduled = True + mscheduled = { + 'event_type': 'maintenance.scheduled', + 'traits': { + 'allowed_actions': {'fields': 'payload.allowed_actions'}, + 'instance_ids': {'fields': 'payload.instance_ids'}, + 'reply_url': {'fields': 'payload.reply_url'}, + 'actions_at': {'fields': 'payload.actions_at', + 'type': 'datetime'}, + 'state': {'fields': 'payload.state'}, + 'session_id': {'fields': 'payload.session_id'}, + 'project_id': {'fields': 'payload.project_id'}, + 'metadata': {'fields': 'payload.metadata'} + } + } + config.append(mscheduled) + + if 'maintenance.host' in et_list: + add_mhost = False + print('NOTE: maintenance.host allready configured') + else: + print('NOTE: add maintenance.host to event_definitions.yaml') + add_mhost = True + mhost = { + 'event_type': 'maintenance.host', + 'traits': { + 'host': {'fields': 'payload.host'}, + 'project_id': {'fields': 'payload.project_id'}, + 'state': {'fields': 'payload.state'}, + 'session_id': {'fields': 'payload.session_id'} + } + } + config.append(mhost) + + if add_mscheduled or add_mhost: + shutil.copyfile(ed_file, ed_file_bak) + with open(ed_file, 'w+') as file: + file.write(yaml.safe_dump(config)) + + +def set_cpu_allocation_ratio(): + nova_file = '/etc/nova/nova.conf' + nova_file_bak = '/etc/nova/nova.bak' + + if not os.path.isfile(nova_file): + raise Exception("File doesn't exist: %s." % nova_file) + # TODO (tojuvone): Unfortunately ConfigParser did not produce working conf + fcheck = open(nova_file) + found_list = ([ca for ca in fcheck.readlines() if "cpu_allocation_ratio" + in ca]) + fcheck.close() + if found_list and len(found_list): + change = False + found = False + for car in found_list: + if car.startswith('#'): + continue + if car.startswith('cpu_allocation_ratio'): + found = True + if "1.0" not in car.split('=')[1]: + change = True + if not found or change: + # need to add or change + shutil.copyfile(nova_file, nova_file_bak) + fin = open(nova_file_bak) + fout = open(nova_file, "wt") + for line in fin: + if change and line.startswith("cpu_allocation_ratio"): + line = "cpu_allocation_ratio=1.0" + if not found and line.startswith("[DEFAULT]"): + line += "cpu_allocation_ratio=1.0\n" + fout.write(line) + fin.close() + fout.close() + +set_notifier_topic() +set_maintenance_event_definitions() +set_cpu_allocation_ratio() -- cgit 1.2.3-korg