Merge "Support opera test in functest releng"
[releng.git] / modules / opnfv / deployment / compass / adapter.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2017 HUAWEI TECHNOLOGIES CO.,LTD and others.
4 #
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9
10 import json
11 import netaddr
12 import re
13
14 from opnfv.deployment import manager
15 from opnfv.utils import opnfv_logger as logger
16 from opnfv.utils import ssh_utils
17
18 logger = logger.Logger(__name__).getLogger()
19
20
21 class CompassAdapter(manager.DeploymentHandler):
22
23     def __init__(self, installer_ip, installer_user, installer_pwd):
24         super(CompassAdapter, self).__init__(installer='compass',
25                                              installer_ip=installer_ip,
26                                              installer_user=installer_user,
27                                              installer_pwd=installer_pwd,
28                                              pkey_file=None)
29
30     def get_nodes(self, options=None):
31         nodes = []
32         self.deployment_status = None
33         self.nodes_dict = self._get_deployment_nodes()
34         self.deployment_status = self.get_deployment_status()
35
36         for k, v in self.nodes_dict.iteritems():
37             node = manager.Node(v['id'], v['ip'],
38                                 k, v['status'],
39                                 v['roles'], v['ssh_client'], v['mac'])
40             nodes.append(node)
41
42         self.get_nodes_called = True
43         return nodes
44
45     def get_openstack_version(self):
46         version = None
47         cmd = 'source /opt/admin-openrc.sh;nova-manage version 2>/dev/null'
48         version = next(node.run_cmd(cmd) for node in self.nodes
49                        if node.is_controller())
50         return version
51
52     def get_sdn_version(self):
53         for node in self.nodes:
54             if node.is_odl():
55                 sdn_info = self._get_sdn_info(node, manager.Role.ODL)
56                 break
57             elif node.is_onos():
58                 sdn_info = self._get_sdn_info(node, manager.Role.ONOS)
59                 break
60             else:
61                 sdn_info = None
62         return sdn_info
63
64     def _get_sdn_info(self, node, sdn_type):
65         if sdn_type == manager.Role.ODL:
66             sdn_key = 'distribution-karaf'
67         elif sdn_type == manager.Role.ONOS:
68             sdn_key = 'onos-'
69         else:
70             raise KeyError('SDN %s is not supported', sdn_type)
71
72         cmd = "find /opt -name '{0}*'".format(sdn_key)
73         sdn_info = node.run_cmd(cmd)
74         sdn_version = 'None'
75         if sdn_info:
76             # /opt/distribution-karaf-0.5.2-Boron-SR2.tar.gz
77             match_sdn = re.findall(r".*(0\.\d\.\d).*", sdn_info)
78             if (match_sdn and len(match_sdn) >= 1):
79                 sdn_version = match_sdn[0]
80                 sdn_version = '{0} {1}'.format(sdn_type, sdn_version)
81         return sdn_version
82
83     def get_deployment_status(self):
84         if self.deployment_status is not None:
85             logger.debug('Skip - Node status has been retrieved once')
86             return self.deployment_status
87
88         for k, v in self.nodes_dict.iteritems():
89             if manager.Role.CONTROLLER in v['roles']:
90                 cmd = 'source /opt/admin-openrc.sh; nova hypervisor-list;'
91                 '''
92                 +----+---------------------+-------+---------+
93
94                 | ID | Hypervisor hostname | State | Status  |
95
96                 +----+---------------------+-------+---------+
97
98                 | 3  | host4               | up    | enabled |
99
100                 | 6  | host5               | up    | enabled |
101
102                 +----+---------------------+-------+---------+
103                 '''
104                 _, stdout, stderr = (v['ssh_client'].exec_command(cmd))
105                 error = stderr.readlines()
106                 if len(error) > 0:
107                     logger.error("error %s" % ''.join(error))
108                     status = manager.NodeStatus.STATUS_ERROR
109                     v['status'] = status
110                     continue
111
112                 lines = stdout.readlines()
113                 for i in range(3, len(lines) - 1):
114                     fields = lines[i].strip().encode().rsplit(' | ')
115                     hostname = fields[1].strip().encode().lower()
116                     state = fields[2].strip().encode().lower()
117                     if 'up' == state:
118                         status = manager.NodeStatus.STATUS_OK
119                     else:
120                         status = manager.NodeStatus.STATUS_ERROR
121                     self.nodes_dict[hostname]['status'] = status
122                     v['status'] = manager.NodeStatus.STATUS_OK
123
124         failed_nodes = [k for k, v in self.nodes_dict.iteritems()
125                         if v['status'] != manager.NodeStatus.STATUS_OK]
126
127         if failed_nodes and len(failed_nodes) > 0:
128             return 'Hosts {0} failed'.format(','.join(failed_nodes))
129
130         return 'active'
131
132     def _get_deployment_nodes(self):
133         sql_query = ('select host.host_id, host.roles, '
134                      'network.ip_int, machine.mac from clusterhost as host, '
135                      'host_network as network, machine as machine '
136                      'where host.host_id=network.host_id '
137                      'and host.id=machine.id;')
138         cmd = 'mysql -uroot -Dcompass -e "{0}"'.format(sql_query)
139         logger.debug('mysql command: %s', cmd)
140         output = self.installer_node.run_cmd(cmd)
141         '''
142         host_id roles   ip_int  mac
143         1 ["controller", "ha", "odl", "ceph-adm", "ceph-mon"]
144         167837746 00:00:e3:ee:a8:63
145         2 ["controller", "ha", "odl", "ceph-mon"]
146         167837747 00:00:31:1d:16:7a
147         3 ["controller", "ha", "odl", "ceph-mon"]
148         167837748 00:00:0c:bf:eb:01
149         4 ["compute", "ceph-osd"] 167837749 00:00:d8:22:6f:59
150         5 ["compute", "ceph-osd"] 167837750 00:00:75:d5:6b:9e
151         '''
152         lines = output.encode().rsplit('\n')
153         nodes_dict = {}
154         if (not lines or len(lines) < 2):
155             logger.error('No nodes are found in the deployment.')
156             return nodes_dict
157
158         proxy = {'ip': self.installer_ip,
159                  'username': self.installer_user,
160                  'password': self.installer_pwd}
161         for i in range(1, len(lines)):
162             fields = lines[i].strip().encode().rsplit('\t')
163             host_id = fields[0].strip().encode()
164             name = 'host{0}'.format(host_id)
165             node_roles_str = fields[1].strip().encode().lower()
166             node_roles_list = json.loads(node_roles_str)
167             node_roles = [manager.Role.ODL if x == 'odl'
168                           else x for x in node_roles_list]
169             roles = [x for x in [manager.Role.CONTROLLER,
170                                  manager.Role.COMPUTE,
171                                  manager.Role.ODL,
172                                  manager.Role.ONOS] if x in node_roles]
173             ip = fields[2].strip().encode()
174             ip = str(netaddr.IPAddress(ip))
175             mac = fields[3].strip().encode()
176
177             nodes_dict[name] = {}
178             nodes_dict[name]['id'] = host_id
179             nodes_dict[name]['roles'] = roles
180             nodes_dict[name]['ip'] = ip
181             nodes_dict[name]['mac'] = mac
182             ssh_client = ssh_utils.get_ssh_client(hostname=ip,
183                                                   username='root',
184                                                   proxy=proxy)
185             nodes_dict[name]['ssh_client'] = ssh_client
186             nodes_dict[name]['status'] = manager.NodeStatus.STATUS_UNKNOWN
187         return nodes_dict