From 3f71d8c07d2f1539a8d56752773c47556d91ef4d Mon Sep 17 00:00:00 2001 From: helenyao Date: Fri, 24 Mar 2017 11:32:19 +0800 Subject: Compass Adapter to get deployment information result of example.py for Compass(ODL enabled) can be refered here https://pastebin.com/k3UW9bUJ Change-Id: I56352d71152078a44d706d97c67fb8d69b20ad2d Signed-off-by: helenyao --- modules/opnfv/deployment/compass/__init__.py | 0 modules/opnfv/deployment/compass/adapter.py | 185 +++++++++++++++++++++++++++ modules/opnfv/deployment/example.py | 14 ++ modules/opnfv/deployment/factory.py | 6 + modules/opnfv/deployment/manager.py | 9 +- 5 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 modules/opnfv/deployment/compass/__init__.py create mode 100644 modules/opnfv/deployment/compass/adapter.py (limited to 'modules/opnfv/deployment') diff --git a/modules/opnfv/deployment/compass/__init__.py b/modules/opnfv/deployment/compass/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/modules/opnfv/deployment/compass/adapter.py b/modules/opnfv/deployment/compass/adapter.py new file mode 100644 index 000000000..856c7fc38 --- /dev/null +++ b/modules/opnfv/deployment/compass/adapter.py @@ -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 diff --git a/modules/opnfv/deployment/example.py b/modules/opnfv/deployment/example.py index 3999a11c6..52d9b5630 100644 --- a/modules/opnfv/deployment/example.py +++ b/modules/opnfv/deployment/example.py @@ -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) diff --git a/modules/opnfv/deployment/factory.py b/modules/opnfv/deployment/factory.py index 1ccee4e80..b8e5c8ef4 100644 --- a/modules/opnfv/deployment/factory.py +++ b/modules/opnfv/deployment/factory.py @@ -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.") diff --git a/modules/opnfv/deployment/manager.py b/modules/opnfv/deployment/manager.py index df735f157..694df7755 100644 --- a/modules/opnfv/deployment/manager.py +++ b/modules/opnfv/deployment/manager.py @@ -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) -- cgit 1.2.3-korg