Matteo Scandolo | 48d3d2d | 2017-08-08 13:05:27 -0700 | [diff] [blame] | 1 | |
| 2 | # Copyright 2017-present Open Networking Foundation |
| 3 | # |
| 4 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | # you may not use this file except in compliance with the License. |
| 6 | # You may obtain a copy of the License at |
| 7 | # |
| 8 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | # |
| 10 | # Unless required by applicable law or agreed to in writing, software |
| 11 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | # See the License for the specific language governing permissions and |
| 14 | # limitations under the License. |
| 15 | |
| 16 | |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 17 | import os |
| 18 | import shutil |
| 19 | import re |
| 20 | from novaclient import client as nova_client |
| 21 | from SSHTestAgent import SSHTestAgent |
| 22 | from CordTestUtils import * |
A R Karthick | 933f5b5 | 2017-03-27 15:27:16 -0700 | [diff] [blame] | 23 | from CordTestUtils import log_test as log |
| 24 | |
| 25 | log.setLevel('INFO') |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 26 | |
| 27 | class VSGAccess(object): |
| 28 | |
| 29 | vcpe_map = {} |
| 30 | interface_map = {} |
| 31 | ip_addr_pattern = re.compile('[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}$') |
| 32 | |
| 33 | @classmethod |
| 34 | def setUp(cls): |
| 35 | try: |
| 36 | shutil.copy('/etc/resolv.conf', '/etc/resolv.conf.orig') |
| 37 | except: |
| 38 | pass |
| 39 | |
| 40 | @classmethod |
| 41 | def tearDown(cls): |
| 42 | try: |
| 43 | shutil.copy('/etc/resolv.conf.orig', '/etc/resolv.conf') |
| 44 | except: |
| 45 | pass |
| 46 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 47 | ''' |
| 48 | @method: get_nova_credentials_v2 |
| 49 | @Description: Get nova credentials |
| 50 | @params: |
| 51 | returns credential from env |
| 52 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 53 | @classmethod |
| 54 | def get_nova_credentials_v2(cls): |
| 55 | credential = {} |
| 56 | credential['username'] = os.environ['OS_USERNAME'] |
| 57 | credential['api_key'] = os.environ['OS_PASSWORD'] |
| 58 | credential['auth_url'] = os.environ['OS_AUTH_URL'] |
| 59 | credential['project_id'] = os.environ['OS_TENANT_NAME'] |
| 60 | return credential |
| 61 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 62 | ''' |
| 63 | @method: get_compute_nodes |
| 64 | @Description: Get the list of compute nodes |
| 65 | @params: |
| 66 | returns node list |
| 67 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 68 | @classmethod |
| 69 | def get_compute_nodes(cls): |
| 70 | credentials = cls.get_nova_credentials_v2() |
| 71 | nvclient = nova_client.Client('2', **credentials) |
| 72 | return nvclient.hypervisors.list() |
| 73 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 74 | ''' |
| 75 | @method: get_vsgs |
| 76 | @Description: Get list of vsg's running in compute node |
| 77 | @params: status of vsg |
| 78 | returns vsg wrappers |
| 79 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 80 | @classmethod |
| 81 | def get_vsgs(cls, active = True): |
| 82 | credentials = cls.get_nova_credentials_v2() |
| 83 | nvclient = nova_client.Client('2', **credentials) |
| 84 | vsgs = nvclient.servers.list(search_opts = {'all_tenants': 1}) |
| 85 | if active is True: |
| 86 | vsgs = filter(lambda vsg: vsg.status == 'ACTIVE', vsgs) |
| 87 | vsg_wrappers = [] |
| 88 | for vsg in vsgs: |
| 89 | vsg_wrappers.append(VSGWrapper(vsg)) |
| 90 | return vsg_wrappers |
| 91 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 92 | ''' |
| 93 | @method: open_mgmt |
| 94 | @Description: Bringing up Interface for access to management |
| 95 | @params: intf = "Interface to open" |
| 96 | returns Gateway |
| 97 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 98 | @classmethod |
| 99 | def open_mgmt(cls, intf = 'eth0'): |
| 100 | if intf in cls.interface_map: |
| 101 | gw = cls.interface_map[intf]['gw'] |
| 102 | ip = cls.interface_map[intf]['ip'] |
| 103 | if gw != '0.0.0.0': |
| 104 | current_gw, _ = get_default_gw() |
| 105 | cmds = [ 'route del default gw {}'.format(current_gw), |
| 106 | 'ifconfig {} {} up'.format(intf, ip), |
| 107 | 'route add default gw {}'.format(gw) ] |
| 108 | for cmd in cmds: |
| 109 | os.system(cmd) |
| 110 | shutil.copy('/etc/resolv.conf', '/etc/resolv.conf.lastdhcp') |
| 111 | shutil.copy('/etc/resolv.conf.orig', '/etc/resolv.conf') |
| 112 | return current_gw |
| 113 | return None |
| 114 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 115 | ''' |
| 116 | @method: close_mgmt |
| 117 | @Description: Bringing up gateway deleting default |
| 118 | @params: intf = "Interface to open" |
| 119 | dict2 = retrieved data from GET method |
| 120 | returns: NA |
| 121 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 122 | @classmethod |
| 123 | def close_mgmt(cls, restore_gw, intf = 'eth0'): |
| 124 | if restore_gw: |
| 125 | cmds = [ 'route del default gw 0.0.0.0', |
| 126 | 'route add default gw {}'.format(restore_gw), |
| 127 | 'cp /etc/resolv.conf.lastdhcp /etc/resolv.conf', |
| 128 | 'rm -f /etc/resolv.conf.lastdhcp' |
| 129 | ] |
| 130 | for cmd in cmds: |
| 131 | os.system(cmd) |
| 132 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 133 | ''' |
| 134 | @method: health_check |
| 135 | @Description: Check if vsgs are reachable |
| 136 | @params: |
| 137 | returns True |
| 138 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 139 | @classmethod |
| 140 | def health_check(cls): |
| 141 | '''Returns 0 if all active vsgs are reachable through the compute node''' |
| 142 | vsgs = cls.get_vsgs() |
| 143 | vsg_status = [] |
| 144 | for vsg in vsgs: |
| 145 | vsg_status.append(vsg.get_health()) |
| 146 | unreachable = filter(lambda st: st == False, vsg_status) |
| 147 | return len(unreachable) == 0 |
| 148 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 149 | ''' |
| 150 | @method: get_vcpe_vsg |
| 151 | @Description: Getting vsg vm instance info from given vcpe |
| 152 | @params: vcpe = "vcpe name" |
| 153 | returns vsg |
| 154 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 155 | @classmethod |
| 156 | def get_vcpe_vsg(cls, vcpe): |
| 157 | '''Find the vsg hosting the vcpe service''' |
| 158 | if vcpe in cls.vcpe_map: |
| 159 | return cls.vcpe_map[vcpe]['vsg'] |
| 160 | vsgs = cls.get_vsgs() |
| 161 | for vsg in vsgs: |
| 162 | cmd = 'sudo docker exec {} ls 2>/dev/null'.format(vcpe) |
| 163 | st, _ = vsg.run_cmd(cmd, timeout = 30) |
| 164 | if st == True: |
| 165 | return vsg |
| 166 | return None |
| 167 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 168 | ''' |
| 169 | @method: save_vcpe_config |
| 170 | @Description: Saving vcpe config with lan & wan side info |
| 171 | @params: vsg |
| 172 | vcpe |
| 173 | returns True |
| 174 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 175 | @classmethod |
| 176 | def save_vcpe_config(cls, vsg, vcpe): |
| 177 | if vcpe not in cls.vcpe_map: |
| 178 | cmd_gw = "sudo docker exec %s ip route show | grep default | head -1 | awk '{print $3}'" %(vcpe) |
| 179 | vsg_ip = vsg.ip |
| 180 | if vsg_ip is None: |
| 181 | return False |
| 182 | st, output = vsg.run_cmd(cmd_gw, timeout = 30) |
| 183 | if st == False or not output: |
| 184 | return False |
| 185 | gw = output |
| 186 | cmd_wan = "sudo docker exec %s ip addr show eth0 |grep inet |head -1 | tr -s ' ' | awk '{print $2}' | awk '{print $1}'" %(vcpe) |
| 187 | cmd_lan = "sudo docker exec %s ip addr show eth1 |grep inet |head -1 | tr -s ' ' | awk '{print $2}' | awk '{print $1}'" %(vcpe) |
| 188 | st, output = vsg.run_cmd(cmd_wan, timeout = 30) |
| 189 | ip_wan = '0.0.0.0/24' |
| 190 | ip_lan = '0.0.0.0/24' |
| 191 | if st and output: |
| 192 | if cls.ip_addr_pattern.match(output): |
| 193 | ip_wan = output |
| 194 | |
| 195 | st, output = vsg.run_cmd(cmd_lan, timeout = 30) |
| 196 | if st and output: |
| 197 | if cls.ip_addr_pattern.match(output): |
| 198 | ip_lan = output |
| 199 | |
| 200 | cls.vcpe_map[vcpe] = { 'vsg': vsg, 'gw': gw, 'wan': ip_wan, 'lan': ip_lan } |
| 201 | |
| 202 | return True |
| 203 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 204 | ''' |
| 205 | @method: restore_vcpe_config |
| 206 | @Description: Restoring saved config for lan & wan |
| 207 | @params: vcpe |
| 208 | gw |
| 209 | wan |
| 210 | lan |
| 211 | returns True/False |
| 212 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 213 | @classmethod |
| 214 | def restore_vcpe_config(cls, vcpe, gw = True, wan = False, lan = False): |
| 215 | if vcpe in cls.vcpe_map: |
| 216 | vsg = cls.vcpe_map[vcpe]['vsg'] |
| 217 | cmds = [] |
| 218 | if gw is True: |
| 219 | #restore default gw |
| 220 | gw = cls.vcpe_map[vcpe]['gw'] |
| 221 | cmds.append('sudo docker exec {} ip link set eth0 up'.format(vcpe)) |
| 222 | cmds.append('sudo docker exec {} route add default gw {} dev eth0'.format(vcpe, gw)) |
| 223 | if wan is True: |
| 224 | ip_wan = cls.vcpe_map[vcpe]['wan'] |
| 225 | cmds.append('sudo docker exec {} ip addr set {} dev eth0'.format(vcpe, ip_wan)) |
| 226 | if lan is True: |
| 227 | ip_lan = cls.vcpe_map[vcpe]['lan'] |
| 228 | cmds.append('sudo docker exec {} ip addr set {} dev eth1'.format(vcpe, ip_lan)) |
| 229 | ret_status = True |
| 230 | for cmd in cmds: |
| 231 | st, _ = vsg.run_cmd(cmd, timeout = 30) |
| 232 | if st == False: |
| 233 | ret_status = False |
| 234 | return ret_status |
| 235 | return False |
| 236 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 237 | ''' |
| 238 | @method: get_vcpe_gw |
| 239 | @Description: Get gw of vcpe from created map |
| 240 | @params: vcpe |
| 241 | returns gw |
| 242 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 243 | @classmethod |
| 244 | def get_vcpe_gw(cls, vcpe): |
| 245 | if vcpe in cls.vcpe_map: |
| 246 | return cls.vcpe_map[vcpe]['gw'] |
| 247 | return None |
| 248 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 249 | ''' |
| 250 | @method: get_vcpe_wan |
| 251 | @Description: |
| 252 | @params: |
| 253 | return wan side of vcpe |
| 254 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 255 | @classmethod |
| 256 | def get_vcpe_wan(cls, vcpe): |
| 257 | if vcpe in cls.vcpe_map: |
| 258 | return cls.vcpe_map[vcpe]['wan'] |
| 259 | return None |
| 260 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 261 | ''' |
| 262 | @method: get_vcpe_lan |
| 263 | @Description: |
| 264 | @params: |
| 265 | returns True if contents of dict1 exists in dict2 |
| 266 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 267 | @classmethod |
| 268 | def get_vcpe_lan(cls, vcpe): |
| 269 | if vcpe in cls.vcpe_map: |
| 270 | return cls.vcpe_map[vcpe]['lan'] |
| 271 | return None |
| 272 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 273 | ''' |
| 274 | @method: vcpe_wan_up |
| 275 | @Description: |
| 276 | @params: |
| 277 | returns status |
| 278 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 279 | @classmethod |
| 280 | def vcpe_wan_up(cls, vcpe): |
| 281 | return cls.restore_vcpe_config(vcpe) |
| 282 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 283 | ''' |
| 284 | @method: vcpe_lan_up |
| 285 | @Description: |
| 286 | @params: |
| 287 | returns status |
| 288 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 289 | @classmethod |
| 290 | def vcpe_lan_up(cls, vcpe, vsg = None): |
| 291 | if vsg is None: |
| 292 | vsg = cls.get_vcpe_vsg(vcpe) |
| 293 | if vsg is None: |
| 294 | return False |
| 295 | cmd = 'sudo docker exec {} ip link set eth1 up'.format(vcpe) |
| 296 | st, _ = vsg.run_cmd(cmd, timeout = 30) |
| 297 | return st |
| 298 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 299 | ''' |
| 300 | @method: vcpe_port_down |
| 301 | @Description: |
| 302 | @params: |
| 303 | returns status |
| 304 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 305 | #we cannot access compute node if the vcpe port gets dhcp as default would be through fabric |
| 306 | @classmethod |
| 307 | def vcpe_port_down(cls, vcpe, port, vsg = None): |
| 308 | if vsg is None: |
| 309 | vsg = cls.get_vcpe_vsg(vcpe) |
| 310 | if vsg is None: |
| 311 | return False |
| 312 | if not cls.save_vcpe_config(vsg, vcpe): |
| 313 | return False |
| 314 | cmd = 'sudo docker exec {} ip link set {} down'.format(vcpe, port) |
| 315 | st, _ = vsg.run_cmd(cmd, timeout = 30) |
| 316 | if st is False: |
| 317 | cls.restore_vcpe_config(vcpe) |
| 318 | return False |
| 319 | return st |
| 320 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 321 | ''' |
| 322 | @method: vcpe_wan_down |
| 323 | @Description: |
| 324 | @params: |
| 325 | returns status |
| 326 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 327 | @classmethod |
| 328 | def vcpe_wan_down(cls, vcpe, vsg = None): |
| 329 | return cls.vcpe_port_down(vcpe, 'eth0', vsg = vsg) |
| 330 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 331 | ''' |
| 332 | @method: vcpe_lan_down |
| 333 | @Description: |
| 334 | @params: |
| 335 | returns status |
| 336 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 337 | @classmethod |
| 338 | def vcpe_lan_down(cls, vcpe, vsg = None): |
| 339 | return cls.vcpe_port_down(vcpe, 'eth1', vsg = vsg) |
| 340 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 341 | ''' |
| 342 | @method: save_interface_config |
| 343 | @Description: |
| 344 | @params: |
| 345 | returns NA |
| 346 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 347 | @classmethod |
| 348 | def save_interface_config(cls, intf): |
| 349 | if intf not in cls.interface_map: |
| 350 | ip = get_ip(intf) |
| 351 | if ip is None: |
| 352 | ip = '0.0.0.0' |
| 353 | default_gw, default_gw_device = get_default_gw() |
| 354 | if default_gw_device != intf: |
| 355 | default_gw = '0.0.0.0' |
| 356 | cls.interface_map[intf] = { 'ip' : ip, 'gw': default_gw } |
| 357 | #bounce the interface to remove default gw |
| 358 | cmds = ['ifconfig {} 0 down'.format(intf), |
| 359 | 'ifconfig {} 0 up'.format(intf) |
| 360 | ] |
| 361 | for cmd in cmds: |
| 362 | os.system(cmd) |
| 363 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 364 | ''' |
| 365 | @method: restore_interface_config |
| 366 | @Description: |
| 367 | @params: |
| 368 | returns NA |
| 369 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 370 | #open up access to compute node |
| 371 | @classmethod |
| 372 | def restore_interface_config(cls, intf, vcpe = None): |
| 373 | if intf in cls.interface_map: |
| 374 | ip = cls.interface_map[intf]['ip'] |
| 375 | gw = cls.interface_map[intf]['gw'] |
| 376 | del cls.interface_map[intf] |
| 377 | cmds = [] |
| 378 | if vcpe is not None: |
| 379 | shutil.copy('/etc/resolv.conf.orig', '/etc/resolv.conf') |
| 380 | #bounce the vcpes to clear default gw |
| 381 | cmds.append('ifconfig {} 0 down'.format(vcpe)) |
| 382 | cmds.append('ifconfig {} 0 up'.format(vcpe)) |
| 383 | cmds.append('ifconfig {} {} up'.format(intf, ip)) |
| 384 | if gw and gw != '0.0.0.0': |
| 385 | cmds.append('route add default gw {} dev {}'.format(gw, intf)) |
| 386 | for cmd in cmds: |
| 387 | os.system(cmd) |
| 388 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 389 | ''' |
| 390 | @method: vcpe_get_dhcp |
| 391 | @Description: Get DHCP from vcpe dhcp interface. |
| 392 | @params: |
| 393 | returns vcpe ip |
| 394 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 395 | @classmethod |
| 396 | def vcpe_get_dhcp(cls, vcpe, mgmt = 'eth0'): |
| 397 | '''Get DHCP from vcpe dhcp interface.''' |
| 398 | '''We have to also save the management interface config for restoration''' |
| 399 | cls.save_interface_config(mgmt) |
| 400 | getstatusoutput('pkill -9 dhclient') |
| 401 | st, output = getstatusoutput('dhclient -q {}'.format(vcpe)) |
| 402 | getstatusoutput('pkill -9 dhclient') |
| 403 | vcpe_ip = get_ip(vcpe) |
| 404 | if vcpe_ip is None: |
| 405 | cls.restore_interface_config(mgmt) |
| 406 | return None |
| 407 | if output: |
| 408 | #workaround for docker container apparmor that prevents moving dhclient resolv.conf |
| 409 | start = output.find('/etc/resolv.conf') |
| 410 | if start >= 0: |
| 411 | end = output.find("'", start) |
| 412 | dns_file = output[start:end] |
| 413 | if os.access(dns_file, os.F_OK): |
| 414 | shutil.copy(dns_file, '/etc/resolv.conf') |
| 415 | |
| 416 | default_gw, default_gw_device = get_default_gw() |
| 417 | if default_gw and default_gw_device == vcpe: |
| 418 | return vcpe_ip |
| 419 | cls.restore_interface_config(mgmt, vcpe = vcpe) |
| 420 | return None |
| 421 | |
| 422 | class VSGWrapper(object): |
| 423 | |
| 424 | def __init__(self, vsg): |
| 425 | self.vsg = vsg |
| 426 | self.name = self.vsg.name |
| 427 | self.compute_node = self.get_compute_node() |
| 428 | self.ip = self.get_ip() |
| 429 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 430 | ''' |
| 431 | @method: get_compute_node |
| 432 | @Description: |
| 433 | @params: |
| 434 | returns compute node name |
| 435 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 436 | def get_compute_node(self): |
| 437 | return self.vsg._info['OS-EXT-SRV-ATTR:hypervisor_hostname'] |
| 438 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 439 | ''' |
| 440 | @method: get_ip |
| 441 | @Description: |
| 442 | @params: |
| 443 | returns ip of network |
| 444 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 445 | def get_ip(self): |
| 446 | if 'management' in self.vsg.networks: |
| 447 | ips = self.vsg.networks['management'] |
| 448 | if len(ips) > 0: |
| 449 | return ips[0] |
| 450 | return None |
| 451 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 452 | ''' |
| 453 | @method: run_cmd_compute |
| 454 | @Description: |
| 455 | @params: |
| 456 | returns Status & output |
| 457 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 458 | def run_cmd_compute(self, cmd, timeout = 5): |
| 459 | ssh_agent = SSHTestAgent(self.compute_node) |
| 460 | st, output = ssh_agent.run_cmd(cmd, timeout = timeout) |
| 461 | if st == True and output: |
| 462 | output = output.strip() |
| 463 | else: |
| 464 | output = None |
| 465 | |
| 466 | return st, output |
| 467 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 468 | ''' |
| 469 | @method: run_cmd |
| 470 | @Description: |
| 471 | @params: |
| 472 | returns status & output |
| 473 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 474 | def run_cmd(self, cmd, timeout = 5, mgmt = 'eth0'): |
| 475 | last_gw = VSGAccess.open_mgmt(mgmt) |
| 476 | ssh_agent = SSHTestAgent(self.compute_node) |
| 477 | ssh_cmd = 'ssh {} {}'.format(self.ip, cmd) |
| 478 | st, output = ssh_agent.run_cmd(ssh_cmd, timeout = timeout) |
| 479 | if st == True and output: |
| 480 | output = output.strip() |
| 481 | else: |
| 482 | output = None |
| 483 | VSGAccess.close_mgmt(last_gw, mgmt) |
| 484 | return st, output |
| 485 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 486 | ''' |
| 487 | @method: get_health |
| 488 | @Description: |
| 489 | @params: |
| 490 | returns Status |
| 491 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 492 | def get_health(self): |
| 493 | if self.ip is None: |
A R Karthick | 850795b | 2017-03-27 14:07:03 -0700 | [diff] [blame] | 494 | return True |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 495 | cmd = 'ping -c 1 {}'.format(self.ip) |
A R Karthick | 933f5b5 | 2017-03-27 15:27:16 -0700 | [diff] [blame] | 496 | log.info('Pinging VSG %s at IP %s' %(self.name, self.ip)) |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 497 | st, _ = self.run_cmd_compute(cmd) |
A R Karthick | 36968e2 | 2017-11-07 10:45:03 -0800 | [diff] [blame] | 498 | log.info('VSG %s at IP %s is %s through compute node %s' %(self.name, self.ip, 'reachable' if st == True else 'unreachable', self.compute_node)) |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 499 | return st |
| 500 | |
Chetan Gaonker | 79b3553 | 2017-03-31 18:58:36 +0000 | [diff] [blame] | 501 | ''' |
| 502 | @method: check_access |
| 503 | @Description: validates access |
| 504 | @params: |
| 505 | returns Status |
| 506 | ''' |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 507 | def check_access(self): |
| 508 | if self.ip is None: |
A R Karthick | 933f5b5 | 2017-03-27 15:27:16 -0700 | [diff] [blame] | 509 | return True |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 510 | ssh_agent = SSHTestAgent(self.compute_node) |
| 511 | st, _ = ssh_agent.run_cmd('ls', timeout=10) |
| 512 | if st == False: |
A R Karthick | 933f5b5 | 2017-03-27 15:27:16 -0700 | [diff] [blame] | 513 | log.error('Compute node at %s is not accessible' %(self.compute_node)) |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 514 | return st |
A R Karthick | 933f5b5 | 2017-03-27 15:27:16 -0700 | [diff] [blame] | 515 | log.info('Checking if VSG at %s is accessible from compute node %s' %(self.ip, self.compute_node)) |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 516 | st, _ = ssh_agent.run_cmd('ssh {} ls'.format(self.ip), timeout=30) |
A R Karthick | 933f5b5 | 2017-03-27 15:27:16 -0700 | [diff] [blame] | 517 | if st == True: |
| 518 | log.info('OK') |
A R Karthick | d0fdf3b | 2017-03-21 16:54:22 -0700 | [diff] [blame] | 519 | return st |