Compass Adapter to get deployment information 53/31653/7
authorhelenyao <yaohelan@huawei.com>
Fri, 24 Mar 2017 03:32:19 +0000 (11:32 +0800)
committerhelenyao <yaohelan@huawei.com>
Fri, 31 Mar 2017 09:01:36 +0000 (17:01 +0800)
result of example.py for Compass(ODL enabled) can be refered here
https://pastebin.com/k3UW9bUJ

Change-Id: I56352d71152078a44d706d97c67fb8d69b20ad2d
Signed-off-by: helenyao <yaohelan@huawei.com>
modules/opnfv/deployment/compass/__init__.py [new file with mode: 0644]
modules/opnfv/deployment/compass/adapter.py [new file with mode: 0644]
modules/opnfv/deployment/example.py
modules/opnfv/deployment/factory.py
modules/opnfv/deployment/manager.py

diff --git a/modules/opnfv/deployment/compass/__init__.py b/modules/opnfv/deployment/compass/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/modules/opnfv/deployment/compass/adapter.py b/modules/opnfv/deployment/compass/adapter.py
new file mode 100644 (file)
index 0000000..856c7fc
--- /dev/null
@@ -0,0 +1,185 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2017 HUAWEI TECHNOLOGIES CO.,LTD 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 netaddr
+import re
+
+from opnfv.deployment import manager
+from opnfv.utils import opnfv_logger as logger
+from opnfv.utils import ssh_utils
+
+logger = logger.Logger(__name__).getLogger()
+
+
+class CompassAdapter(manager.DeploymentHandler):
+
+    def __init__(self, installer_ip, installer_user, installer_pwd):
+        super(CompassAdapter, self).__init__(installer='compass',
+                                             installer_ip=installer_ip,
+                                             installer_user=installer_user,
+                                             installer_pwd=installer_pwd,
+                                             pkey_file=None)
+
+    def get_nodes(self, options=None):
+        nodes = []
+        self.deployment_status = None
+        self.nodes_dict = self._get_deployment_nodes()
+        self.deployment_status = self.get_deployment_status()
+
+        for k, v in self.nodes_dict.iteritems():
+            node = manager.Node(v['id'], v['ip'],
+                                k, v['status'],
+                                v['roles'], v['ssh_client'], v['mac'])
+            nodes.append(node)
+
+        self.get_nodes_called = True
+        return nodes
+
+    def get_openstack_version(self):
+        version = None
+        cmd = 'source /opt/admin-openrc.sh;nova-manage version 2>/dev/null'
+        version = next(node.run_cmd(cmd) for node in self.nodes
+                       if node.is_controller())
+        return version
+
+    def get_sdn_version(self):
+        for node in self.nodes:
+            if node.is_odl():
+                sdn_info = self._get_sdn_info(node, manager.Role.ODL)
+                break
+            elif node.is_onos():
+                sdn_info = self._get_sdn_info(node, manager.Role.ONOS)
+                break
+            else:
+                sdn_info = None
+        return sdn_info
+
+    def _get_sdn_info(self, node, sdn_type):
+        if sdn_type == manager.Role.ODL:
+            sdn_key = 'distribution-karaf'
+        elif sdn_type == manager.Role.ONOS:
+            sdn_key = 'onos-'
+        else:
+            raise KeyError('SDN %s is not supported', sdn_type)
+
+        cmd = "find /opt -name '{0}*'".format(sdn_key)
+        sdn_info = node.run_cmd(cmd)
+        sdn_version = 'None'
+        if sdn_info:
+            # /opt/distribution-karaf-0.5.2-Boron-SR2.tar.gz
+            match_sdn = re.findall(r".*(0\.\d\.\d).*", sdn_info)
+            if (match_sdn and len(match_sdn) >= 1):
+                sdn_version = match_sdn[0]
+                sdn_version = '{0} {1}'.format(sdn_type, sdn_version)
+        return sdn_version
+
+    def get_deployment_status(self):
+        if self.deployment_status is not None:
+            logger.debug('Skip - Node status has been retrieved once')
+            return self.deployment_status
+
+        for k, v in self.nodes_dict.iteritems():
+            if manager.Role.CONTROLLER in v['roles']:
+                cmd = 'source /opt/admin-openrc.sh; nova hypervisor-list;'
+                '''
+                +----+---------------------+-------+---------+
+
+                | ID | Hypervisor hostname | State | Status  |
+
+                +----+---------------------+-------+---------+
+
+                | 3  | host4               | up    | enabled |
+
+                | 6  | host5               | up    | enabled |
+
+                +----+---------------------+-------+---------+
+                '''
+                _, stdout, stderr = (v['ssh_client'].exec_command(cmd))
+                error = stderr.readlines()
+                if len(error) > 0:
+                    logger.error("error %s" % ''.join(error))
+                    status = manager.NodeStatus.STATUS_ERROR
+                    v['status'] = status
+                    continue
+
+                lines = stdout.readlines()
+                for i in range(3, len(lines) - 1):
+                    fields = lines[i].strip().encode().rsplit(' | ')
+                    hostname = fields[1].strip().encode().lower()
+                    state = fields[2].strip().encode().lower()
+                    if 'up' == state:
+                        status = manager.NodeStatus.STATUS_OK
+                    else:
+                        status = manager.NodeStatus.STATUS_ERROR
+                    self.nodes_dict[hostname]['status'] = status
+                    v['status'] = manager.NodeStatus.STATUS_OK
+
+        failed_nodes = [k for k, v in self.nodes_dict.iteritems()
+                        if v['status'] != manager.NodeStatus.STATUS_OK]
+
+        if failed_nodes and len(failed_nodes) > 0:
+            return 'Hosts {0} failed'.format(','.join(failed_nodes))
+
+        return 'active'
+
+    def _get_deployment_nodes(self):
+        sql_query = ('select host.host_id, host.roles, '
+                     'network.ip_int, machine.mac from clusterhost as host, '
+                     'host_network as network, machine as machine '
+                     'where host.host_id=network.host_id '
+                     'and host.id=machine.id;')
+        cmd = 'mysql -uroot -Dcompass -e "{0}"'.format(sql_query)
+        logger.debug('mysql command: %s', cmd)
+        output = self.installer_node.run_cmd(cmd)
+        '''
+        host_id roles   ip_int  mac
+        1 ["controller", "ha", "odl", "ceph-adm", "ceph-mon"]
+        167837746 00:00:e3:ee:a8:63
+        2 ["controller", "ha", "odl", "ceph-mon"]
+        167837747 00:00:31:1d:16:7a
+        3 ["controller", "ha", "odl", "ceph-mon"]
+        167837748 00:00:0c:bf:eb:01
+        4 ["compute", "ceph-osd"] 167837749 00:00:d8:22:6f:59
+        5 ["compute", "ceph-osd"] 167837750 00:00:75:d5:6b:9e
+        '''
+        lines = output.encode().rsplit('\n')
+        nodes_dict = {}
+        if (not lines or len(lines) < 2):
+            logger.error('No nodes are found in the deployment.')
+            return nodes_dict
+
+        proxy = {'ip': self.installer_ip,
+                 'username': self.installer_user,
+                 'password': self.installer_pwd}
+        for i in range(1, len(lines)):
+            fields = lines[i].strip().encode().rsplit('\t')
+            host_id = fields[0].strip().encode()
+            name = 'host{0}'.format(host_id)
+            node_roles = fields[1].strip().encode().lower()
+            node_roles = [manager.Role.ODL if x == 'odl'
+                          else x for x in node_roles]
+            roles = [x for x in [manager.Role.CONTROLLER,
+                                 manager.Role.COMPUTE,
+                                 manager.Role.ODL,
+                                 manager.Role.ONOS] if x in node_roles]
+            ip = fields[2].strip().encode()
+            ip = str(netaddr.IPAddress(ip))
+            mac = fields[3].strip().encode()
+
+            nodes_dict[name] = {}
+            nodes_dict[name]['id'] = host_id
+            nodes_dict[name]['roles'] = roles
+            nodes_dict[name]['ip'] = ip
+            nodes_dict[name]['mac'] = mac
+            ssh_client = ssh_utils.get_ssh_client(hostname=ip,
+                                                  username='root',
+                                                  proxy=proxy)
+            nodes_dict[name]['ssh_client'] = ssh_client
+            nodes_dict[name]['status'] = manager.NodeStatus.STATUS_UNKNOWN
+        return nodes_dict
index 3999a11..52d9b56 100644 (file)
@@ -34,3 +34,17 @@ print("List of nodes in cluster 4:")
 nodes = handler.get_nodes({'cluster': '4'})
 for node in nodes:
     print(node)
+
+
+print("########## COMPASS ##########")
+handler = factory.Factory.get_handler('compass',
+                                      '192.168.200.2',
+                                      'root',
+                                      installer_pwd='root')
+
+print(handler.get_deployment_status())
+print(handler.get_deployment_info())
+print('Details of each node:')
+nodes = handler.nodes
+for node in nodes:
+    print(node)
index 1ccee4e..b8e5c8e 100644 (file)
@@ -9,6 +9,7 @@
 
 
 from opnfv.deployment.apex import adapter as apex_adapter
+from opnfv.deployment.compass import adapter as compass_adapter
 from opnfv.deployment.fuel import adapter as fuel_adapter
 from opnfv.utils import opnfv_logger as logger
 
@@ -40,6 +41,11 @@ class Factory(object):
             return fuel_adapter.FuelAdapter(installer_ip=installer_ip,
                                             installer_user=installer_user,
                                             installer_pwd=installer_pwd)
+        elif installer.lower() == "compass":
+            return compass_adapter.CompassAdapter(
+                installer_ip=installer_ip,
+                installer_user=installer_user,
+                installer_pwd=installer_pwd)
         else:
             raise Exception("Installer adapter is not implemented for "
                             "the given installer.")
index df735f1..694df77 100644 (file)
@@ -108,6 +108,7 @@ class NodeStatus():
     STATUS_OFFLINE = 'offline'
     STATUS_ERROR = 'error'
     STATUS_UNUSED = 'unused'
+    STATUS_UNKNOWN = 'unknown'
 
 
 class Node(object):
@@ -229,6 +230,12 @@ class Node(object):
         '''
         return Role.ODL in self.roles
 
+    def is_onos(self):
+        '''
+        Returns if the node is an ONOS
+        '''
+        return Role.ONOS in self.roles
+
     def get_ovs_info(self):
         '''
         Returns the ovs version installed
@@ -383,4 +390,4 @@ class DeploymentHandler(object):
                           pod=os.getenv('NODE_NAME', 'Unknown'),
                           openstack_version=self.get_openstack_version(),
                           sdn_controller=self.get_sdn_version(),
-                          nodes=self.get_nodes())
+                          nodes=self.nodes)