refactor local installer 27/37727/9
authordongwenjuan <dong.wenjuan@zte.com.cn>
Mon, 17 Jul 2017 00:54:22 +0000 (08:54 +0800)
committerdongwenjuan <dong.wenjuan@zte.com.cn>
Tue, 1 Aug 2017 03:13:58 +0000 (11:13 +0800)
JIRA: DOCTOR-100

Change-Id: I1e2c53f7a716156e35386d42c0df32a228a78fab
Signed-off-by: dongwenjuan <dong.wenjuan@zte.com.cn>
tests/config.py
tests/installer/__init__.py [new file with mode: 0644]
tests/installer/base.py [new file with mode: 0644]
tests/installer/local.py [new file with mode: 0644]
tests/logger.py
tests/main.py
tests/utils.py [new file with mode: 0644]

index 88910f6..f33ab5d 100644 (file)
@@ -14,6 +14,7 @@ import alarm
 import consumer\r
 import image\r
 import instance\r
+import installer\r
 import network\r
 import inspector\r
 import monitor\r
@@ -23,6 +24,7 @@ import user
 \r
 def list_opts():\r
     return [\r
+        ('installer', installer.OPTS),\r
         ('monitor', monitor.OPTS),\r
         ('inspector', inspector.OPTS),\r
         ('consumer', consumer.OPTS),\r
diff --git a/tests/installer/__init__.py b/tests/installer/__init__.py
new file mode 100644 (file)
index 0000000..491543c
--- /dev/null
@@ -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 (file)
index 0000000..83467f5
--- /dev/null
@@ -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 (file)
index 0000000..e156ac1
--- /dev/null
@@ -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
index 72043ab..021389d 100644 (file)
@@ -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
-
index 6547835..b59cd7a 100644 (file)
@@ -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 (file)
index 0000000..c5d6c1c
--- /dev/null
@@ -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))
+