blob: d6354858828bf7e2c54495b98ea975cf1be926cc [file] [log] [blame]
John DeNisco68b0ee32017-09-27 16:35:23 -04001# Copyright (c) 2016 Cisco and/or its affiliates.
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at:
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -080014from __future__ import print_function
15
John DeNisco68b0ee32017-09-27 16:35:23 -040016"""VPP util library"""
17import logging
18import re
19import subprocess
20import platform
jdenisco24010fb2018-11-13 12:40:12 -050021import requests
John DeNisco68b0ee32017-09-27 16:35:23 -040022
23from collections import Counter
24
jdenisco2cefb062019-02-19 16:25:05 -050025ubuntu_pkgs = {'release': ['vpp', 'vpp-plugins', 'vpp-api-java', 'vpp-api-lua', 'vpp-api-python',
26 'vpp-dbg', 'vpp-dev'],
27 'master': ['vpp', 'vpp-plugin-core', 'vpp-ext-deps', 'vpp-api-python',
28 'vpp-dbg', 'vpp-dev', 'vpp-plugin-dpdk']}
29
30centos_pkgs = {'release': ['vpp', 'vpp-plugins', 'vpp-api-java', 'vpp-api-lua',
31 'vpp-api-python', 'vpp-debuginfo', 'vpp-devel', 'libvpp0'],
32 'master': ['vpp', 'vpp-plugins', 'vpp-ext-deps', 'vpp-api-java', 'vpp-api-lua',
33 'vpp-api-python', 'vpp-debuginfo', 'vpp-devel', 'libvpp0']}
34
John DeNisco68b0ee32017-09-27 16:35:23 -040035
36class VPPUtil(object):
37 """General class for any VPP related methods/functions."""
38
39 @staticmethod
40 def exec_command(cmd, timeout=None):
41 """Execute a command on the local node.
42
43 :param cmd: Command to run locally.
44 :param timeout: Timeout value
45 :type cmd: str
46 :type timeout: int
47 :return return_code, stdout, stderr
48 :rtype: tuple(int, str, str)
49 """
50
51 logging.info(" Local Command: {}".format(cmd))
52 out = ''
53 err = ''
54 prc = subprocess.Popen(cmd, shell=True, bufsize=1,
55 stdin=subprocess.PIPE,
56 stdout=subprocess.PIPE,
57 stderr=subprocess.PIPE)
58
59 with prc.stdout:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -080060 lines = prc.stdout.readlines()
61 for line in lines:
62 if type(line) != str:
63 line = line.decode()
John DeNisco68b0ee32017-09-27 16:35:23 -040064 logging.info(" {}".format(line.strip('\n')))
65 out += line
66
67 with prc.stderr:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -080068 lines = prc.stderr.readlines()
69 for line in lines:
70 if type(line) != str:
71 line = line.decode()
jdenisco2cefb062019-02-19 16:25:05 -050072 logging.warning(" {}".format(line.strip('\n')))
John DeNisco68b0ee32017-09-27 16:35:23 -040073 err += line
74
75 ret = prc.wait()
76
77 return ret, out, err
78
79 def _autoconfig_backup_file(self, filename):
80 """
81 Create a backup file.
82
83 :param filename: The file to backup
84 :type filename: str
85 """
86
87 # Does a copy of the file exist, if not create one
88 ofile = filename + '.orig'
89 (ret, stdout, stderr) = self.exec_command('ls {}'.format(ofile))
90 if ret != 0:
91 logging.debug(stderr)
92 if stdout.strip('\n') != ofile:
93 cmd = 'sudo cp {} {}'.format(filename, ofile)
94 (ret, stdout, stderr) = self.exec_command(cmd)
95 if ret != 0:
96 logging.debug(stderr)
97
jdeniscob0b9dad2018-12-18 15:29:45 -050098 def _install_vpp_ubuntu(self, node, branch, ubuntu_version='xenial'):
John DeNisco68b0ee32017-09-27 16:35:23 -040099 """
100 Install the VPP packages
101
102 :param node: Node dictionary with cpuinfo.
jdeniscob0b9dad2018-12-18 15:29:45 -0500103 :param branch: VPP branch
John DeNisco68b0ee32017-09-27 16:35:23 -0400104 :param ubuntu_version: Ubuntu Version
105 :type node: dict
jdeniscob0b9dad2018-12-18 15:29:45 -0500106 :type branch: string
John DeNisco68b0ee32017-09-27 16:35:23 -0400107 :type ubuntu_version: string
108 """
109
110 # Modify the sources list
111 sfile = '/etc/apt/sources.list.d/99fd.io.list'
112
113 # Backup the sources list
114 self._autoconfig_backup_file(sfile)
115
jdenisco24010fb2018-11-13 12:40:12 -0500116 reps = 'deb [trusted=yes] https://packagecloud.io/fdio/'
jdenisco2cefb062019-02-19 16:25:05 -0500117 reps += '{}/ubuntu {} main\n'.format(branch, ubuntu_version)
John DeNisco68b0ee32017-09-27 16:35:23 -0400118
jdenisco24010fb2018-11-13 12:40:12 -0500119 with open(sfile, 'w') as sfd:
120 sfd.write(reps)
121 sfd.close()
122
123 # Add the key
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800124
125 key = requests.get(
126 'https://packagecloud.io/fdio/{}/gpgkey'.format(branch))
127 cmd = 'echo "{}" | apt-key add -'.format(key.content.decode(key.encoding))
John DeNisco68b0ee32017-09-27 16:35:23 -0400128 (ret, stdout, stderr) = self.exec_command(cmd)
129 if ret != 0:
130 raise RuntimeError('{} failed on node {} {}'.format(
131 cmd,
132 node['host'],
133 stderr))
134
135 # Install the package
136 cmd = 'apt-get -y update'
137 (ret, stdout, stderr) = self.exec_command(cmd)
138 if ret != 0:
139 raise RuntimeError('{} apt-get update failed on node {} {}'.format(
140 cmd,
141 node['host'],
142 stderr))
143
jdenisco2cefb062019-02-19 16:25:05 -0500144 # Get the package list
145 pkgstr = ''
146 for ps in ubuntu_pkgs[branch]:
147 pkgstr += ps + ' '
148
149 cmd = 'apt-get -y install {}'.format(pkgstr)
150 (ret, stdout, stderr) = self.exec_command(cmd)
151 if ret != 0:
152 raise RuntimeError('{} failed on node {} {} {}'.format(
153 cmd, node['host'], stdout, stderr))
John DeNisco68b0ee32017-09-27 16:35:23 -0400154
jdeniscob0b9dad2018-12-18 15:29:45 -0500155 def _install_vpp_centos(self, node, branch):
John DeNisco68b0ee32017-09-27 16:35:23 -0400156 """
157 Install the VPP packages
158
159 :param node: Node dictionary with cpuinfo.
jdeniscob0b9dad2018-12-18 15:29:45 -0500160 :param branch: The branch name release or master
John DeNisco68b0ee32017-09-27 16:35:23 -0400161 :type node: dict
jdeniscob0b9dad2018-12-18 15:29:45 -0500162 :type branch: string
John DeNisco68b0ee32017-09-27 16:35:23 -0400163 """
164
jdenisco24010fb2018-11-13 12:40:12 -0500165 # Be sure the correct system packages are installed
166 cmd = 'yum -y update'
167 (ret, stdout, stderr) = self.exec_command(cmd)
168 if ret != 0:
169 logging.debug('{} failed on node {} {}'.format(
170 cmd,
171 node['host'],
172 stderr))
173
174 cmd = 'yum -y install pygpgme yum-utils'
175 (ret, stdout, stderr) = self.exec_command(cmd)
176 if ret != 0:
177 logging.debug('{} failed on node {} {}'.format(
178 cmd,
179 node['host'],
180 stderr))
181
John DeNisco68b0ee32017-09-27 16:35:23 -0400182 # Modify the sources list
183 sfile = '/etc/yum.repos.d/fdio-release.repo'
184
185 # Backup the sources list
186 self._autoconfig_backup_file(sfile)
187
188 # Remove the current file
189 cmd = 'rm {}'.format(sfile)
190 (ret, stdout, stderr) = self.exec_command(cmd)
191 if ret != 0:
192 logging.debug('{} failed on node {} {}'.format(
193 cmd,
194 node['host'],
195 stderr))
196
jdenisco24010fb2018-11-13 12:40:12 -0500197 # Get the file contents
jdenisco24010fb2018-11-13 12:40:12 -0500198
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800199 reps = '\n'.join([
200 '[fdio_{}]'.format(branch),
201 'name=fdio_{}'.format(branch),
202 'baseurl=https://packagecloud.io/fdio/{}/el/7/$basearch'.format(
203 branch),
204 'repo_gpgcheck=1',
205 'gpgcheck=0',
206 'enabled=1',
207 'gpgkey=https://packagecloud.io/fdio/{}/gpgkey'.format(branch),
208 'sslverify=1',
209 'sslcacert=/etc/pki/tls/certs/ca-bundle.crt',
210 'metadata_expire=300\n',
211 '[fdio_{}-source]'.format(branch),
212 'name=fdio_release-{}'.format(branch),
213 'baseurl=https://packagecloud.io/fdio/{}/el/7/SRPMS'.format(
214 branch),
215 'repo_gpgcheck=1',
216 'gpgcheck=0',
217 'enabled=1',
218 'gpgkey=https://packagecloud.io/fdio/{}/gpgkey'.format(branch),
219 'sslverify =1',
220 'sslcacert=/etc/pki/tls/certs/ca-bundle.crt',
221 'metadata_expire=300\n'
222 ])
jdenisco24010fb2018-11-13 12:40:12 -0500223 with open(sfile, 'w') as sfd:
224 sfd.write(reps)
225 sfd.close()
226
227 # Update the fdio repo
228 cmd = 'yum clean all'
John DeNisco68b0ee32017-09-27 16:35:23 -0400229 (ret, stdout, stderr) = self.exec_command(cmd)
230 if ret != 0:
jdenisco24010fb2018-11-13 12:40:12 -0500231 logging.debug('{} failed on node {} {}'.format(
232 cmd,
233 node['host'],
234 stderr))
235
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800236 cmd = "yum -q makecache -y --disablerepo='*' " \
237 "--enablerepo='fdio_{}'".format(branch)
jdenisco24010fb2018-11-13 12:40:12 -0500238 (ret, stdout, stderr) = self.exec_command(cmd)
239 if ret != 0:
240 logging.debug('{} failed on node {} {}'.format(
John DeNisco68b0ee32017-09-27 16:35:23 -0400241 cmd,
242 node['host'],
243 stderr))
244
jdenisco2cefb062019-02-19 16:25:05 -0500245 # Get the package list
246 pkgstr = ''
247 for ps in centos_pkgs[branch]:
248 pkgstr += ps + ' '
249
250 cmd = 'yum -y install {}'.format(pkgstr)
251 (ret, stdout, stderr) = self.exec_command(cmd)
252 if ret != 0:
253 raise RuntimeError('{} failed on node {} {} {}'.format(
254 cmd, node['host'], stdout, stderr))
John DeNisco68b0ee32017-09-27 16:35:23 -0400255
jdeniscob0b9dad2018-12-18 15:29:45 -0500256 def install_vpp(self, node, branch):
John DeNisco68b0ee32017-09-27 16:35:23 -0400257 """
258 Install the VPP packages
259
260 :param node: Node dictionary with cpuinfo.
jdeniscob0b9dad2018-12-18 15:29:45 -0500261 :param branch: The branch name
John DeNisco68b0ee32017-09-27 16:35:23 -0400262 :type node: dict
jdeniscob0b9dad2018-12-18 15:29:45 -0500263 :type branch: string
264
John DeNisco68b0ee32017-09-27 16:35:23 -0400265 """
266 distro = self.get_linux_distro()
John DeNisco4dc83972018-03-30 10:50:19 -0400267 logging.info(" {}".format(distro[0]))
John DeNisco68b0ee32017-09-27 16:35:23 -0400268 if distro[0] == 'Ubuntu':
John DeNisco4dc83972018-03-30 10:50:19 -0400269 logging.info("Install Ubuntu")
jdeniscob0b9dad2018-12-18 15:29:45 -0500270 self._install_vpp_ubuntu(node, branch, ubuntu_version=distro[2])
John DeNisco68b0ee32017-09-27 16:35:23 -0400271 elif distro[0] == 'CentOS Linux':
272 logging.info("Install CentOS")
jdeniscob0b9dad2018-12-18 15:29:45 -0500273 self._install_vpp_centos(node, branch)
John DeNisco68b0ee32017-09-27 16:35:23 -0400274 else:
John DeNisco4dc83972018-03-30 10:50:19 -0400275 logging.info("Install CentOS (default)")
jdeniscob0b9dad2018-12-18 15:29:45 -0500276 self._install_vpp_centos(node, branch)
John DeNisco4dc83972018-03-30 10:50:19 -0400277 return
John DeNisco68b0ee32017-09-27 16:35:23 -0400278
John DeNisco68b0ee32017-09-27 16:35:23 -0400279 def _uninstall_vpp_ubuntu(self, node):
280 """
281 Uninstall the VPP packages
282
283 :param node: Node dictionary with cpuinfo.
284 :type node: dict
285 """
John DeNisco68b0ee32017-09-27 16:35:23 -0400286
jdenisco2cefb062019-02-19 16:25:05 -0500287 # get the package list
288 pkgstr = ''
289 pkgs = self.get_installed_vpp_pkgs()
290 for pkg in pkgs:
291 pkgname = pkg['name']
292 pkgstr += pkgname + ' '
293
294 cmd = 'dpkg --purge {}'.format(pkgstr)
295 (ret, stdout, stderr) = self.exec_command(cmd)
296 if ret != 0:
297 raise RuntimeError('{} failed on node {} {} {}'.format(
298 cmd, node['host'], stdout, stderr))
John DeNisco68b0ee32017-09-27 16:35:23 -0400299
300 def _uninstall_vpp_centos(self, node):
301 """
302 Uninstall the VPP packages
303
304 :param node: Node dictionary with cpuinfo.
305 :type node: dict
jdenisco2cefb062019-02-19 16:25:05 -0500306 """
John DeNisco68b0ee32017-09-27 16:35:23 -0400307
jdenisco2cefb062019-02-19 16:25:05 -0500308 pkgstr = ''
John DeNisco68b0ee32017-09-27 16:35:23 -0400309 pkgs = self.get_installed_vpp_pkgs()
jdenisco2cefb062019-02-19 16:25:05 -0500310 for pkg in pkgs:
311 pkgname = pkg['name']
312 pkgstr += pkgname + ' '
John DeNisco68b0ee32017-09-27 16:35:23 -0400313
jdenisco2cefb062019-02-19 16:25:05 -0500314 logging.info("Uninstalling {}".format(pkgstr))
315 cmd = 'yum -y remove {}'.format(pkgstr)
316 (ret, stdout, stderr) = self.exec_command(cmd)
317 if ret != 0:
318 raise RuntimeError('{} failed on node {} {} {}'.format(
319 cmd, node['host'], stdout, stderr))
John DeNisco68b0ee32017-09-27 16:35:23 -0400320
321 def uninstall_vpp(self, node):
322 """
323 Uninstall the VPP packages
324
325 :param node: Node dictionary with cpuinfo.
326 :type node: dict
327 """
John DeNiscoc6b2a202017-11-01 12:37:47 -0400328
329 # First stop VPP
330 self.stop(node)
John DeNisco68b0ee32017-09-27 16:35:23 -0400331 distro = self.get_linux_distro()
332 if distro[0] == 'Ubuntu':
John DeNisco4dc83972018-03-30 10:50:19 -0400333 logging.info("Uninstall Ubuntu")
John DeNisco68b0ee32017-09-27 16:35:23 -0400334 self._uninstall_vpp_ubuntu(node)
335 elif distro[0] == 'CentOS Linux':
336 logging.info("Uninstall CentOS")
337 self._uninstall_vpp_centos(node)
338 else:
John DeNisco4dc83972018-03-30 10:50:19 -0400339 logging.info("Uninstall CentOS (Default)")
340 self._uninstall_vpp_centos(node)
John DeNisco68b0ee32017-09-27 16:35:23 -0400341 return
342
343 def show_vpp_settings(self, *additional_cmds):
344 """
345 Print default VPP settings. In case others are needed, can be
346 accepted as next parameters (each setting one parameter), preferably
347 in form of a string.
348
349 :param additional_cmds: Additional commands that the vpp should print
350 settings for.
351 :type additional_cmds: tuple
352 """
353 def_setting_tb_displayed = {
354 'IPv6 FIB': 'ip6 fib',
355 'IPv4 FIB': 'ip fib',
356 'Interface IP': 'int addr',
357 'Interfaces': 'int',
358 'ARP': 'ip arp',
359 'Errors': 'err'
360 }
361
362 if additional_cmds:
363 for cmd in additional_cmds:
364 def_setting_tb_displayed['Custom Setting: {}'.format(cmd)] \
365 = cmd
366
367 for _, value in def_setting_tb_displayed.items():
368 self.exec_command('vppctl sh {}'.format(value))
369
370 @staticmethod
John DeNiscoc6b2a202017-11-01 12:37:47 -0400371 def get_vms(node):
372 """
373 Get a list of VMs that are connected to VPP interfaces
374
375 :param node: VPP node.
376 :type node: dict
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800377 :returns: Dictionary containing a list of VMs and the interfaces
378 that are connected to VPP
John DeNiscoc6b2a202017-11-01 12:37:47 -0400379 :rtype: dictionary
380 """
381
382 vmdict = {}
383
jdenisco2cefb062019-02-19 16:25:05 -0500384 print("Need to implement get vms")
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800385
John DeNiscoc6b2a202017-11-01 12:37:47 -0400386 return vmdict
387
388 @staticmethod
John DeNiscoa3db0782017-10-17 11:07:22 -0400389 def get_int_ip(node):
390 """
391 Get the VPP interfaces and IP addresses
392
393 :param node: VPP node.
394 :type node: dict
395 :returns: Dictionary containing VPP interfaces and IP addresses
396 :rtype: dictionary
397 """
398 interfaces = {}
399 cmd = 'vppctl show int addr'
400 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
401 if ret != 0:
402 return interfaces
403
404 lines = stdout.split('\n')
405 if len(lines[0]) is not 0:
406 if lines[0].split(' ')[0] == 'FileNotFoundError':
407 return interfaces
408
John DeNiscoc6b2a202017-11-01 12:37:47 -0400409 name = ''
John DeNiscoa3db0782017-10-17 11:07:22 -0400410 for line in lines:
411 if len(line) is 0:
412 continue
413
414 # If the first character is not whitespace
415 # create a new interface
416 if len(re.findall(r'\s', line[0])) is 0:
417 spl = line.split()
418 name = spl[0]
419 if name == 'local0':
420 continue
421 interfaces[name] = {}
422 interfaces[name]['state'] = spl[1].lstrip('(').rstrip('):\r')
423 else:
424 interfaces[name]['address'] = line.lstrip(' ').rstrip('\r')
425
426 return interfaces
427
428 @staticmethod
John DeNisco68b0ee32017-09-27 16:35:23 -0400429 def get_hardware(node):
430 """
431 Get the VPP hardware information and return it in a
432 dictionary
433
434 :param node: VPP node.
435 :type node: dict
John DeNiscoa3db0782017-10-17 11:07:22 -0400436 :returns: Dictionary containing VPP hardware information
John DeNisco68b0ee32017-09-27 16:35:23 -0400437 :rtype: dictionary
438 """
439
440 interfaces = {}
441 cmd = 'vppctl show hard'
442 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
443 if ret != 0:
444 return interfaces
445
446 lines = stdout.split('\n')
447 if len(lines[0]) is not 0:
448 if lines[0].split(' ')[0] == 'FileNotFoundError':
449 return interfaces
450
451 for line in lines:
452 if len(line) is 0:
453 continue
454
455 # If the first character is not whitespace
456 # create a new interface
457 if len(re.findall(r'\s', line[0])) is 0:
458 spl = line.split()
459 name = spl[0]
460 interfaces[name] = {}
461 interfaces[name]['index'] = spl[1]
462 interfaces[name]['state'] = spl[2]
463
464 # Ethernet address
465 rfall = re.findall(r'Ethernet address', line)
466 if rfall:
467 spl = line.split()
468 interfaces[name]['mac'] = spl[2]
469
470 # Carrier
471 rfall = re.findall(r'carrier', line)
472 if rfall:
473 spl = line.split('carrier ')
474 interfaces[name]['carrier'] = spl[1]
475
476 # Socket
jdenisco2cefb062019-02-19 16:25:05 -0500477 spl = ''
jdenisco7c37a672018-11-20 11:25:17 -0500478 rfall = re.findall(r'numa \d+', line)
John DeNisco68b0ee32017-09-27 16:35:23 -0400479 if rfall:
jdenisco7c37a672018-11-20 11:25:17 -0500480 spl = rfall[0].split()
481 interfaces[name]['numa'] = rfall[0].split()[1]
John DeNisco68b0ee32017-09-27 16:35:23 -0400482
483 # Queues and Descriptors
jdenisco7c37a672018-11-20 11:25:17 -0500484 rfall = re.findall(r'rx\: queues \d+', line)
John DeNisco68b0ee32017-09-27 16:35:23 -0400485 if rfall:
jdenisco7c37a672018-11-20 11:25:17 -0500486 interfaces[name]['rx queues'] = rfall[0].split()[2]
487 rdesc = re.findall(r'desc \d+', line)
488 if rdesc:
489 interfaces[name]['rx descs'] = rdesc[0].split()[1]
490
491 rfall = re.findall(r'tx\: queues \d+', line)
492 if rfall:
493 interfaces[name]['tx queues'] = rfall[0].split()[2]
494 rdesc = re.findall(r'desc \d+', line)
495 if rdesc:
496 interfaces[name]['tx descs'] = rdesc[0].split()[1]
John DeNisco68b0ee32017-09-27 16:35:23 -0400497
498 return interfaces
499
jdenisco2cefb062019-02-19 16:25:05 -0500500 def _get_installed_vpp_pkgs_ubuntu(self):
John DeNisco68b0ee32017-09-27 16:35:23 -0400501 """
502 Get the VPP hardware information and return it in a
503 dictionary
504
505 :returns: List of the packages installed
506 :rtype: list
507 """
508
509 pkgs = []
510 cmd = 'dpkg -l | grep vpp'
511 (ret, stdout, stderr) = self.exec_command(cmd)
512 if ret != 0:
513 return pkgs
514
515 lines = stdout.split('\n')
516 for line in lines:
517 items = line.split()
518 if len(items) < 2:
519 continue
520 pkg = {'name': items[1], 'version': items[2]}
521 pkgs.append(pkg)
522
523 return pkgs
524
525 def _get_installed_vpp_pkgs_centos(self):
526 """
527 Get the VPP hardware information and return it in a
528 dictionary
529
530 :returns: List of the packages installed
531 :rtype: list
532 """
533
534 pkgs = []
535 cmd = 'rpm -qa | grep vpp'
536 (ret, stdout, stderr) = self.exec_command(cmd)
537 if ret != 0:
538 return pkgs
539
540 lines = stdout.split('\n')
541 for line in lines:
542 if len(line) == 0:
543 continue
544
545 items = line.split()
546 if len(items) < 2:
547 pkg = {'name': items[0]}
548 else:
549 pkg = {'name': items[1], 'version': items[2]}
550
551 pkgs.append(pkg)
552
553 return pkgs
554
555 def get_installed_vpp_pkgs(self):
556 """
557 Get the VPP hardware information and return it in a
558 dictionary
559
560 :returns: List of the packages installed
561 :rtype: list
562 """
563
564 distro = self.get_linux_distro()
565 if distro[0] == 'Ubuntu':
jdenisco2cefb062019-02-19 16:25:05 -0500566 pkgs = self._get_installed_vpp_pkgs_ubuntu()
John DeNisco68b0ee32017-09-27 16:35:23 -0400567 elif distro[0] == 'CentOS Linux':
568 pkgs = self._get_installed_vpp_pkgs_centos()
569 else:
John DeNisco4dc83972018-03-30 10:50:19 -0400570 pkgs = self._get_installed_vpp_pkgs_centos()
John DeNisco68b0ee32017-09-27 16:35:23 -0400571 return []
572
573 return pkgs
574
575 @staticmethod
576 def get_interfaces_numa_node(node, *iface_keys):
577 """Get numa node on which are located most of the interfaces.
578
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800579 Return numa node with highest count of interfaces provided as
580 arguments.
581 Return 0 if the interface does not have numa_node information
582 available.
John DeNisco68b0ee32017-09-27 16:35:23 -0400583 If all interfaces have unknown location (-1), then return 0.
584 If most of interfaces have unknown location (-1), but there are
585 some interfaces with known location, then return the second most
586 location of the provided interfaces.
587
588 :param node: Node from DICT__nodes.
589 :param iface_keys: Interface keys for lookup.
590 :type node: dict
591 :type iface_keys: strings
592 """
593 numa_list = []
594 for if_key in iface_keys:
595 try:
596 numa_list.append(node['interfaces'][if_key].get('numa_node'))
597 except KeyError:
598 pass
599
600 numa_cnt_mc = Counter(numa_list).most_common()
601 numa_cnt_mc_len = len(numa_cnt_mc)
602 if numa_cnt_mc_len > 0 and numa_cnt_mc[0][0] != -1:
603 return numa_cnt_mc[0][0]
604 elif numa_cnt_mc_len > 1 and numa_cnt_mc[0][0] == -1:
605 return numa_cnt_mc[1][0]
606
607 return 0
608
609 @staticmethod
John DeNiscoc6b2a202017-11-01 12:37:47 -0400610 def restart(node):
611 """
612
613 Starts vpp for a given node
614
615 :param node: VPP node.
616 :type node: dict
617 """
618
619 cmd = 'service vpp restart'
620 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
621 if ret != 0:
622 raise RuntimeError('{} failed on node {} {} {}'.
623 format(cmd, node['host'],
624 stdout, stderr))
625
626 @staticmethod
John DeNisco68b0ee32017-09-27 16:35:23 -0400627 def start(node):
628 """
629
630 Starts vpp for a given node
631
632 :param node: VPP node.
633 :type node: dict
634 """
635
636 cmd = 'service vpp start'
637 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
638 if ret != 0:
639 raise RuntimeError('{} failed on node {} {} {}'.
640 format(cmd, node['host'],
641 stdout, stderr))
642
643 @staticmethod
644 def stop(node):
645 """
646
647 Stops vpp for a given node
648
649 :param node: VPP node.
650 :type node: dict
651 """
652
653 cmd = 'service vpp stop'
654 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
655 if ret != 0:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800656 logging.debug('{} failed on node {} {} {}'.
657 format(cmd, node['host'],
658 stdout, stderr))
John DeNisco68b0ee32017-09-27 16:35:23 -0400659
John DeNiscoa7da67f2018-01-26 14:55:33 -0500660 # noinspection RegExpRedundantEscape
John DeNisco68b0ee32017-09-27 16:35:23 -0400661 @staticmethod
662 def status(node):
663 """
664
665 Gets VPP status
666
667 :param: node
668 :type node: dict
669 :returns: status, errors
670 :rtype: tuple(str, list)
671 """
672 errors = []
673 vutil = VPPUtil()
674 pkgs = vutil.get_installed_vpp_pkgs()
675 if len(pkgs) == 0:
676 return "Not Installed", errors
677
678 cmd = 'service vpp status'
679 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
680
681 # Get the active status
682 state = re.findall(r'Active:[\w (\)]+', stdout)[0].split(' ')
683 if len(state) > 2:
684 statestr = "{} {}".format(state[1], state[2])
685 else:
686 statestr = "Invalid"
687
688 # For now we won't look for DPDK errors
689 # lines = stdout.split('\n')
690 # for line in lines:
691 # if 'EAL' in line or \
692 # 'FAILURE' in line or \
693 # 'failed' in line or \
694 # 'Failed' in line:
695 # errors.append(line.lstrip(' '))
696
697 return statestr, errors
698
699 @staticmethod
700 def get_linux_distro():
701 """
702 Get the linux distribution and check if it is supported
703
704 :returns: linux distro, None if the distro is not supported
705 :rtype: list
706 """
707
708 distro = platform.linux_distribution()
709 if distro[0] == 'Ubuntu' or \
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800710 distro[0] == 'CentOS Linux' or \
711 distro[:7] == 'Red Hat':
John DeNisco68b0ee32017-09-27 16:35:23 -0400712 return distro
713 else:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800714 raise RuntimeError(
715 'Linux Distribution {} is not supported'.format(distro[0]))
John DeNisco68b0ee32017-09-27 16:35:23 -0400716
717 @staticmethod
718 def version():
719 """
720
721 Gets VPP Version information
722
723 :returns: version
724 :rtype: dict
725 """
726
727 version = {}
728 cmd = 'vppctl show version verbose'
729 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
730 if ret != 0:
731 return version
732
733 lines = stdout.split('\n')
734 if len(lines[0]) is not 0:
735 if lines[0].split(' ')[0] == 'FileNotFoundError':
736 return version
737
738 for line in lines:
739 if len(line) is 0:
740 continue
741 dct = line.split(':')
742 version[dct[0]] = dct[1].lstrip(' ')
743
744 return version
John DeNiscoc6b2a202017-11-01 12:37:47 -0400745
746 @staticmethod
747 def show_bridge(node):
748 """
749 Shows the current bridge configuration
750
751 :param node: VPP node.
752 :type node: dict
John DeNisco9fa5cf42018-02-06 15:23:05 -0500753 :returns: A list of interfaces
John DeNiscoc6b2a202017-11-01 12:37:47 -0400754 """
755
John DeNisco9fa5cf42018-02-06 15:23:05 -0500756 ifaces = []
John DeNiscoc6b2a202017-11-01 12:37:47 -0400757 cmd = 'vppctl show bridge'
758 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
759 if ret != 0:
760 raise RuntimeError('{} failed on node {} {} {}'.
761 format(cmd, node['host'],
762 stdout, stderr))
763 lines = stdout.split('\r\n')
764 bridges = []
765 for line in lines:
766 if line == 'no bridge-domains in use':
jdenisco2cefb062019-02-19 16:25:05 -0500767 print(line)
John DeNisco9fa5cf42018-02-06 15:23:05 -0500768 return ifaces
John DeNiscoc6b2a202017-11-01 12:37:47 -0400769 if len(line) == 0:
770 continue
771
772 lspl = line.lstrip(' ').split()
773 if lspl[0] != 'BD-ID':
774 bridges.append(lspl[0])
775
776 for bridge in bridges:
777 cmd = 'vppctl show bridge {} detail'.format(bridge)
778 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
779 if ret != 0:
780 raise RuntimeError('{} failed on node {} {} {}'.
781 format(cmd, node['host'],
782 stdout, stderr))
John DeNisco9fa5cf42018-02-06 15:23:05 -0500783
784 lines = stdout.split('\r\n')
785 for line in lines:
786 iface = re.findall(r'[a-zA-z]+\d+/\d+/\d+', line)
787 if len(iface):
jdeniscob0b9dad2018-12-18 15:29:45 -0500788 ifcidx = {'name': iface[0], 'index': line.split()[1]}
John DeNisco9fa5cf42018-02-06 15:23:05 -0500789 ifaces.append(ifcidx)
790
jdenisco2cefb062019-02-19 16:25:05 -0500791 print(stdout)
John DeNisco4dc83972018-03-30 10:50:19 -0400792 return ifaces