From 9549a92ad62fbbad00e355b707809e6409b9e085 Mon Sep 17 00:00:00 2001 From: dongwenjuan Date: Mon, 17 Jul 2017 08:54:22 +0800 Subject: refactor local installer JIRA: DOCTOR-100 Change-Id: I1e2c53f7a716156e35386d42c0df32a228a78fab Signed-off-by: dongwenjuan --- tests/config.py | 2 + tests/installer/__init__.py | 37 +++++++++++++++++ tests/installer/base.py | 32 +++++++++++++++ tests/installer/local.py | 97 +++++++++++++++++++++++++++++++++++++++++++++ tests/logger.py | 3 +- tests/main.py | 4 ++ tests/utils.py | 33 +++++++++++++++ 7 files changed, 206 insertions(+), 2 deletions(-) create mode 100644 tests/installer/__init__.py create mode 100644 tests/installer/base.py create mode 100644 tests/installer/local.py create mode 100644 tests/utils.py (limited to 'tests') diff --git a/tests/config.py b/tests/config.py index 88910f6d..f33ab5d2 100644 --- a/tests/config.py +++ b/tests/config.py @@ -14,6 +14,7 @@ import alarm import consumer import image import instance +import installer import network import inspector import monitor @@ -23,6 +24,7 @@ import user def list_opts(): return [ + ('installer', installer.OPTS), ('monitor', monitor.OPTS), ('inspector', inspector.OPTS), ('consumer', consumer.OPTS), diff --git a/tests/installer/__init__.py b/tests/installer/__init__.py new file mode 100644 index 00000000..491543c8 --- /dev/null +++ b/tests/installer/__init__.py @@ -0,0 +1,37 @@ +############################################################################## +# 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 + +from oslo_config import cfg +from oslo_utils import importutils + +OPTS = [ + cfg.StrOpt('type', + default=os.environ.get('INSTALLER_TYPE', 'local'), + choices=['local'], + help='the type of installer', + required=True), + cfg.StrOpt('ip', + default=os.environ.get('INSTALLER_IP', '127.0.0.1'), + help='the ip of installer'), + cfg.StrOpt('username', + default='root', + help='the user name for login installer server', + required=True), +] + + +_installer_name_class_mapping = { + 'local': 'installer.local.LocalInstaller' +} + + +def get_installer(conf, log): + installer_class = _installer_name_class_mapping[conf.installer.type] + return importutils.import_object(installer_class, conf, log) \ No newline at end of file diff --git a/tests/installer/base.py b/tests/installer/base.py new file mode 100644 index 00000000..83467f55 --- /dev/null +++ b/tests/installer/base.py @@ -0,0 +1,32 @@ +############################################################################## +# 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 abc +import six + +@six.add_metaclass(abc.ABCMeta) +class BaseInstaller(object): + def __init__(self, conf, log): + self.conf = conf + self.log = log + + @abc.abstractproperty + def computer_user_name(self): + """user name for login to computer node""" + + @abc.abstractmethod + def get_ssh_key_from_installer(self): + pass + + @abc.abstractmethod + def setup(self): + pass + + @abc.abstractmethod + def cleanup(self): + pass diff --git a/tests/installer/local.py b/tests/installer/local.py new file mode 100644 index 00000000..e156ac1a --- /dev/null +++ b/tests/installer/local.py @@ -0,0 +1,97 @@ +############################################################################## +# 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 + +from installer.base import BaseInstaller +from utils import load_json_file +from utils import write_json_file + + +class LocalInstaller(BaseInstaller): + computer_user_name = 'root' + + nova_policy_file = '/etc/nova/policy.json' + nova_policy_file_backup = '%s%s' % (nova_policy_file, '.bak') + + def __init__(self, conf, log): + super(LocalInstaller, self).__init__(conf, log) + self.policy_modified = False + self.add_policy_file = False + + def setup(self): + self.get_ssh_key_from_installer() + self.set_apply_patches() + + def cleanup(self): + self.restore_apply_patches() + + def get_ssh_key_from_installer(self): + self.log.info('Assuming SSH keys already exchanged with computer for local installer type') + return + + def set_apply_patches(self): + self._set_nova_policy() + + def restore_apply_patches(self): + self._restore_nova_policy() + + def _set_nova_policy(self): + host_status_policy = 'os_compute_api:servers:show:host_status' + host_status_rule = 'rule:admin_or_owner' + policy_data = { + 'context_is_admin': 'role:admin', + 'owner': 'user_id:%(user_id)s', + 'admin_or_owner': 'rule:context_is_admin or rule:owner', + host_status_policy: host_status_rule + } + + if os.path.isfile(self.nova_policy_file): + data = load_json_file(self.nova_policy_file) + if host_status_policy in data: + rule_origion = data[host_status_policy] + if host_status_rule == rule_origion: + self.log.info('Do not need to modify nova policy.') + self.policy_modified = False + else: + # update the host_status_policy + data[host_status_policy] = host_status_rule + self.policy_modified = True + else: + # add the host_status_policy, if the admin_or_owner is not + # defined, add it also + for policy, rule in policy_data.items(): + if policy not in data: + data[policy] = rule + self.policy_modified = True + if self.policy_modified: + self.log.info('Nova policy is Modified.') + shutil.copyfile(self.nova_policy_file, + self.nova_policy_file_backup) + else: + # file does not exit, create a new one and add the policy + self.log.info('Nova policy file not exist. Creating a new one') + data = policy_data + self.add_policy_file = True + + if self.policy_modified or self.add_policy_file: + write_json_file(self.nova_policy_file, data) + os.system('screen -S stack -p n-api -X stuff "^C^M^[[A^M"') + + def _restore_nova_policy(self): + if self.policy_modified: + shutil.copyfile(self.nova_policy_file_backup, self.nova_policy_file) + os.remove(self.nova_policy_file_backup) + elif self.add_policy_file: + os.remove(self.nova_policy_file) + + if self.add_policy_file or self.policy_modified: + os.system('screen -S stack -p n-api -X stuff "^C^M^[[A^M"') + self.add_policy_file = False + self.policy_modified = False diff --git a/tests/logger.py b/tests/logger.py index 72043ab3..021389d9 100644 --- a/tests/logger.py +++ b/tests/logger.py @@ -21,6 +21,7 @@ class Logger(object): CI_DEBUG = os.getenv('CI_DEBUG') + logging.basicConfig(filemode='w') self.logger = logging.getLogger(logger_name) self.logger.propagate = 0 self.logger.setLevel(logging.DEBUG) @@ -41,7 +42,5 @@ class Logger(object): file_handler.setLevel(logging.DEBUG) self.logger.addHandler(file_handler) - def getLogger(self): return self.logger - diff --git a/tests/main.py b/tests/main.py index 6547835e..b59cd7a3 100644 --- a/tests/main.py +++ b/tests/main.py @@ -16,6 +16,7 @@ from consumer import get_consumer from image import Image from instance import Instance from inspector import get_inspector +from installer import get_installer import logger as doctor_log from user import User from network import Network @@ -39,9 +40,11 @@ class DoctorTest(object): self.inspector.get_inspector_url(), LOG) self.consumer = get_consumer(self.conf, LOG) + self.installer = get_installer(self.conf, LOG) def setup(self): # prepare the cloud env + self.installer.setup() # preparing VM image... self.image.create() @@ -89,6 +92,7 @@ class DoctorTest(object): self.inspector.stop() self.monitor.stop() self.consumer.stop() + self.installer.cleanup() def main(): diff --git a/tests/utils.py b/tests/utils.py new file mode 100644 index 00000000..c5d6c1c3 --- /dev/null +++ b/tests/utils.py @@ -0,0 +1,33 @@ +############################################################################## +# 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 json +import os + + +def load_json_file(full_path): + """Loads JSON from file + :param target_filename: + :return: + """ + if not os.path.isfile(full_path): + raise Exception('File(%s) does not exist' % full_path) + + with open(full_path, 'r') as file: + return json.load(file) + + +def write_json_file(full_path, data): + """write JSON from file + :param target_filename: + :return: + """ + + with open(full_path, 'w+') as file: + file.write(json.dumps(data)) + -- cgit 1.2.3-korg