Create Apex Adapter 31/24531/14
authorjose.lausuch <jose.lausuch@ericsson.com>
Thu, 17 Nov 2016 22:03:44 +0000 (23:03 +0100)
committerJose Lausuch <jose.lausuch@ericsson.com>
Mon, 30 Jan 2017 08:56:48 +0000 (08:56 +0000)
JIRA: RELENG-152

This implementation will help collect information from
the deployment. For example:
- overcloudrc file
- files from the undercloud
- files from the overcloud nodes (i.e. logs)

Change-Id: I293837695a4b82e57b9fac6027fe8197d68b1f14
Signed-off-by: jose.lausuch <jose.lausuch@ericsson.com>
modules/opnfv/installer_adapters/InstallerHandler.py
modules/opnfv/installer_adapters/apex/ApexAdapter.py
modules/opnfv/installer_adapters/apex/example.py [new file with mode: 0644]
modules/opnfv/utils/SSHUtils.py

index dc5bdb9..6c43a46 100644 (file)
@@ -1,5 +1,5 @@
 ##############################################################################
-# Copyright (c) 2015 Ericsson AB and others.
+# Copyright (c) 2017 Ericsson AB and others.
 # Author: Jose Lausuch (jose.lausuch@ericsson.com)
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Apache License, Version 2.0
@@ -23,18 +23,22 @@ class InstallerHandler:
                  installer,
                  installer_ip,
                  installer_user,
-                 installer_pwd=None):
+                 installer_pwd=None,
+                 private_key_file=None):
         self.installer = installer.lower()
         self.installer_ip = installer_ip
         self.installer_user = installer_user
         self.installer_pwd = installer_pwd
+        self.private_key_file = private_key_file
 
         if self.installer == INSTALLERS[0]:
             self.InstallerAdapter = FuelAdapter(self.installer_ip,
                                                 self.installer_user,
                                                 self.installer_pwd)
         elif self.installer == INSTALLERS[1]:
-            self.InstallerAdapter = ApexAdapter(self.installer_ip)
+            self.InstallerAdapter = ApexAdapter(installer_ip=self.installer_ip,
+                                                user=self.installer_user,
+                                                pkey_file=self.private_key_file)
         elif self.installer == INSTALLERS[2]:
             self.InstallerAdapter = CompassAdapter(self.installer_ip)
         elif self.installer == INSTALLERS[3]:
index 17a27b1..29637d7 100644 (file)
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
 
+import os
+import re
+
+import opnfv.utils.SSHUtils as ssh_utils
+import opnfv.utils.OPNFVLogger as logger
+
 
 class ApexAdapter:
 
-    def __init__(self, installer_ip):
+    def __init__(self, installer_ip, pkey_file, user="stack"):
         self.installer_ip = installer_ip
+        self.installer_user = user
+        self.pkey_file = pkey_file
+        self.installer_connection = ssh_utils.get_ssh_client(
+            self.installer_ip,
+            self.installer_user,
+            pkey_file=self.pkey_file)
+        self.logger = logger.Logger("ApexHandler").getLogger()
 
-    def get_deployment_info(self):
-        pass
+    def runcmd_apex_installer(self, cmd):
+        _, stdout, stderr = (self.installer_connection.exec_command(cmd))
+        error = stderr.readlines()
+        if len(error) > 0:
+            self.logger.error("error %s" % ''.join(error))
+            return error
+        output = ''.join(stdout.readlines())
+        return output
 
     def get_nodes(self):
-        pass
+        nodes = []
+        output = self.runcmd_apex_installer(
+            "source /home/stack/stackrc;nova list")
+        lines = output.rsplit('\n')
+        if len(lines) < 4:
+            self.logger.info("No nodes found in the deployment.")
+            return None
+
+        for line in lines:
+            if 'controller' in line:
+                roles = "controller"
+            elif 'compute' in line:
+                roles = "compute"
+            else:
+                continue
+            if 'Daylight' in line:
+                roles = + ", OpenDaylight"
+            fields = line.split('|')
+            dict = {"id": re.sub('[!| ]', '', fields[1]),
+                    "roles": roles,
+                    "name": re.sub('[!| ]', '', fields[2]),
+                    "status": re.sub('[!| ]', '', fields[3]),
+                    "ip": re.sub('[!| ctlplane=]', '', fields[6])}
+            nodes.append(dict)
+
+        return nodes
+
+    def get_deployment_info(self):
+        str = "Deployment details:\n"
+        str += "\tINSTALLER:   Apex\n"
+        str += ("\tSCENARIO:    %s\n" %
+                os.getenv('DEPLOY_SCENARIO', 'Unknown'))
+        sdn = "None"
+
+        nodes = self.get_nodes()
+        if nodes is None:
+            self.logger.info("No nodes found in the deployment.")
+            return
+        num_nodes = len(nodes)
+        num_controllers = 0
+        num_computes = 0
+        for node in nodes:
+            if 'controller' in node['roles']:
+                num_controllers += 1
+            if 'compute' in node['roles']:
+                num_computes += 1
+            if 'Daylight' in node['name']:
+                sdn = 'OpenDaylight'
+
+        ha = str(num_controllers >= 3)
+
+        str += "\tHA:          %s\n" % ha
+        str += "\tNUM.NODES:   %s\n" % num_nodes
+        str += "\tCONTROLLERS: %s\n" % num_controllers
+        str += "\tCOMPUTES:    %s\n" % num_computes
+        str += "\tSDN CONTR.:  %s\n\n" % sdn
+
+        str += "\tNODES:\n"
+        for node in nodes:
+            str += ("\t  ID:     %s\n" % node['id'])
+            str += ("\t  Name:   %s\n" % node['name'])
+            str += ("\t  Roles:  %s\n" % node['roles'])
+            str += ("\t  Status: %s\n" % node['status'])
+            str += ("\t  IP:     %s\n\n" % node['ip'])
+
+        return str
+
+    def get_controller_ips(self, options=None):
+        nodes = self.get_nodes()
+        controllers = []
+        for node in nodes:
+            if "controller" in node["roles"]:
+                controllers.append(node['ip'])
+        return controllers
+
+    def get_compute_ips(self, options=None):
+        nodes = self.get_nodes()
+        computes = []
+        for node in nodes:
+            if "compute" in node["roles"]:
+                computes.append(node['ip'])
+        return computes
 
-    def get_controller_ips(self):
-        pass
+    def get_file_from_installer(self, remote_path, local_path, options=None):
+        self.logger.debug("Fetching %s from Undercloud %s" %
+                          (remote_path, self.installer_ip))
+        get_file_result = ssh_utils.get_file(self.installer_connection,
+                                             remote_path,
+                                             local_path)
+        if get_file_result is None:
+            self.logger.error("SFTP failed to retrieve the file.")
+            return 1
+        self.logger.info("%s successfully copied from Undercloud to %s" %
+                         (remote_path, local_path))
 
-    def get_compute_ips(self):
-        pass
+    def get_file_from_controller(self,
+                                 remote_path,
+                                 local_path,
+                                 ip=None,
+                                 options=None):
+        if ip is None:
+            controllers = self.get_controller_ips()
+            ip = controllers[0]
 
-    def get_file_from_installer(self, origin, target, options=None):
-        pass
+        connection = ssh_utils.get_ssh_client(ip,
+                                              'heat-admin',
+                                              pkey_file=self.pkey_file)
 
-    def get_file_from_controller(self, origin, target, ip=None, options=None):
-        pass
+        get_file_result = ssh_utils.get_file(connection,
+                                             remote_path,
+                                             local_path)
+        if get_file_result is None:
+            self.logger.error("SFTP failed to retrieve the file.")
+            return 1
+        self.logger.info("%s successfully copied from %s to %s" %
+                         (remote_path, ip, local_path))
diff --git a/modules/opnfv/installer_adapters/apex/example.py b/modules/opnfv/installer_adapters/apex/example.py
new file mode 100644 (file)
index 0000000..c8c4737
--- /dev/null
@@ -0,0 +1,16 @@
+# This is an example of usage of this Tool
+# Author: Jose Lausuch (jose.lausuch@ericsson.com)
+
+import opnfv.installer_adapters.InstallerHandler as ins_handler
+
+apex_handler = ins_handler.InstallerHandler(installer='apex',
+                                            installer_ip='192.168.122.135',
+                                            installer_user='stack',
+                                            private_key_file='/root/.ssh/id_rsa')
+apex_handler.get_file_from_installer(
+    '/home/stack/overcloudrc', './overcloudrc')
+
+print("\n%s\n" % apex_handler.get_deployment_info())
+
+apex_handler.get_file_from_controller(
+    '/etc/resolv.conf', './resolv.conf')
index 16e34c3..e0a830c 100644 (file)
@@ -16,7 +16,11 @@ import os
 logger = OPNFVLogger.Logger('SSHUtils').getLogger()
 
 
-def get_ssh_client(hostname, username, password=None, proxy=None):
+def get_ssh_client(hostname,
+                   username,
+                   password=None,
+                   proxy=None,
+                   pkey_file=None):
     client = None
     try:
         if proxy is None:
@@ -26,14 +30,21 @@ def get_ssh_client(hostname, username, password=None, proxy=None):
             client.configure_jump_host(proxy['ip'],
                                        proxy['username'],
                                        proxy['password'])
-
         if client is None:
             raise Exception('Could not connect to client')
 
         client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
-        client.connect(hostname,
-                       username=username,
-                       password=password)
+        if pkey_file is not None:
+            key = paramiko.RSAKey.from_private_key_file(pkey_file)
+            client.load_system_host_keys()
+            client.connect(hostname,
+                           username=username,
+                           pkey=key)
+        else:
+            client.connect(hostname,
+                           username=username,
+                           password=password)
+
         return client
     except Exception, e:
         logger.error(e)
@@ -66,6 +77,7 @@ class ProxyHopClient(paramiko.SSHClient):
     '''
     Connect to a remote server using a proxy hop
     '''
+
     def __init__(self, *args, **kwargs):
         self.logger = OPNFVLogger.Logger("ProxyHopClient").getLogger()
         self.proxy_ssh = None