aboutsummaryrefslogtreecommitdiffstats
path: root/opnfv/deployment/compass/adapter.py
blob: 38aa452274f60f46e023d69712f3c992a0e2b407 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/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 json
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_str = fields[1].strip().encode().lower()
            node_roles_list = json.loads(node_roles_str)
            node_roles = [manager.Role.ODL if x == 'odl'
                          else x for x in node_roles_list]
            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