blob: ade905e24f74c37da9404c64815ca8b7633d1255 [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
14"""VPP util library"""
15import logging
16import re
17import subprocess
18import platform
19
20from collections import Counter
21
22# VPP_VERSION = '1707'
John DeNiscoa7da67f2018-01-26 14:55:33 -050023# VPP_VERSION = '1710'
jdeniscob9875092018-11-06 16:10:04 -050024VPP_VERSION = '1804'
John DeNisco68b0ee32017-09-27 16:35:23 -040025
26
27class VPPUtil(object):
28 """General class for any VPP related methods/functions."""
29
30 @staticmethod
31 def exec_command(cmd, timeout=None):
32 """Execute a command on the local node.
33
34 :param cmd: Command to run locally.
35 :param timeout: Timeout value
36 :type cmd: str
37 :type timeout: int
38 :return return_code, stdout, stderr
39 :rtype: tuple(int, str, str)
40 """
41
42 logging.info(" Local Command: {}".format(cmd))
43 out = ''
44 err = ''
45 prc = subprocess.Popen(cmd, shell=True, bufsize=1,
46 stdin=subprocess.PIPE,
47 stdout=subprocess.PIPE,
48 stderr=subprocess.PIPE)
49
50 with prc.stdout:
51 for line in iter(prc.stdout.readline, b''):
52 logging.info(" {}".format(line.strip('\n')))
53 out += line
54
55 with prc.stderr:
56 for line in iter(prc.stderr.readline, b''):
57 logging.warn(" {}".format(line.strip('\n')))
58 err += line
59
60 ret = prc.wait()
61
62 return ret, out, err
63
64 def _autoconfig_backup_file(self, filename):
65 """
66 Create a backup file.
67
68 :param filename: The file to backup
69 :type filename: str
70 """
71
72 # Does a copy of the file exist, if not create one
73 ofile = filename + '.orig'
74 (ret, stdout, stderr) = self.exec_command('ls {}'.format(ofile))
75 if ret != 0:
76 logging.debug(stderr)
77 if stdout.strip('\n') != ofile:
78 cmd = 'sudo cp {} {}'.format(filename, ofile)
79 (ret, stdout, stderr) = self.exec_command(cmd)
80 if ret != 0:
81 logging.debug(stderr)
82
83 def _install_vpp_pkg_ubuntu(self, node, pkg):
84 """
85 Install the VPP packages
86
87 :param node: Node dictionary
88 :param pkg: The vpp packages
89 :type node: dict
90 :type pkg: string
91 """
92
93 cmd = 'apt-get -y install {}'.format(pkg)
94 (ret, stdout, stderr) = self.exec_command(cmd)
95 if ret != 0:
96 raise RuntimeError('{} failed on node {} {} {}'.format(
97 cmd, node['host'], stdout, stderr))
98
99 def _install_vpp_pkg_centos(self, node, pkg):
100 """
101 Install the VPP packages
102
103 :param node: Node dictionary
104 :param pkg: The vpp packages
105 :type node: dict
106 :type pkg: string
107 """
108
109 cmd = 'yum -y install {}'.format(pkg)
110 (ret, stdout, stderr) = self.exec_command(cmd)
111 if ret != 0:
112 raise RuntimeError('{} failed on node {} {} {}'.format(
113 cmd, node['host'], stdout, stderr))
114
115 def _install_vpp_ubuntu(self, node, fdio_release=VPP_VERSION,
116 ubuntu_version='xenial'):
117 """
118 Install the VPP packages
119
120 :param node: Node dictionary with cpuinfo.
121 :param fdio_release: VPP release number
122 :param ubuntu_version: Ubuntu Version
123 :type node: dict
124 :type fdio_release: string
125 :type ubuntu_version: string
126 """
127
128 # Modify the sources list
129 sfile = '/etc/apt/sources.list.d/99fd.io.list'
130
131 # Backup the sources list
132 self._autoconfig_backup_file(sfile)
133
134 # Remove the current file
135 cmd = 'rm {}'.format(sfile)
136 (ret, stdout, stderr) = self.exec_command(cmd)
137 if ret != 0:
138 logging.debug('{} failed on node {} {}'.format(
139 cmd,
140 node['host'],
141 stderr))
142
143 reps = 'deb [trusted=yes] https://nexus.fd.io/content/'
John DeNiscoc6b2a202017-11-01 12:37:47 -0400144 # When using a stable branch
John DeNiscoa7da67f2018-01-26 14:55:33 -0500145 # reps += 'repositories/fd.io.stable.{}.ubuntu.{}.main/ ./\n'.format(fdio_release, ubuntu_version)
146 # When using release
147 reps += 'repositories/fd.io.ubuntu.{}.main/ ./\n'.format(ubuntu_version)
John DeNisco4dc83972018-03-30 10:50:19 -0400148 # When using master
149 # reps += 'repositories/fd.io.master.ubuntu.{}.main/ ./\n'.format(ubuntu_version)
John DeNisco68b0ee32017-09-27 16:35:23 -0400150
151 cmd = 'echo "{0}" | sudo tee {1}'.format(reps, sfile)
152 (ret, stdout, stderr) = self.exec_command(cmd)
153 if ret != 0:
154 raise RuntimeError('{} failed on node {} {}'.format(
155 cmd,
156 node['host'],
157 stderr))
158
159 # Install the package
160 cmd = 'apt-get -y update'
161 (ret, stdout, stderr) = self.exec_command(cmd)
162 if ret != 0:
163 raise RuntimeError('{} apt-get update failed on node {} {}'.format(
164 cmd,
165 node['host'],
166 stderr))
167
168 self._install_vpp_pkg_ubuntu(node, 'vpp-lib')
169 self._install_vpp_pkg_ubuntu(node, 'vpp')
170 self._install_vpp_pkg_ubuntu(node, 'vpp-plugins')
171 self._install_vpp_pkg_ubuntu(node, 'vpp-dpdk-dkms')
172 self._install_vpp_pkg_ubuntu(node, 'vpp-dpdk-dev')
173 self._install_vpp_pkg_ubuntu(node, 'vpp-api-python')
174 self._install_vpp_pkg_ubuntu(node, 'vpp-api-java')
175 self._install_vpp_pkg_ubuntu(node, 'vpp-api-lua')
176 self._install_vpp_pkg_ubuntu(node, 'vpp-dev')
177 self._install_vpp_pkg_ubuntu(node, 'vpp-dbg')
jdeniscob9875092018-11-06 16:10:04 -0500178 self._install_vpp_pkg_ubuntu(node, 'vpp-nsh-plugin')
179 self._install_vpp_pkg_ubuntu(node, 'vpp-nsh-plugin-dbg')
180 self._install_vpp_pkg_ubuntu(node, 'vpp-nsh-plugin-dev')
John DeNisco68b0ee32017-09-27 16:35:23 -0400181
182 def _install_vpp_centos(self, node, fdio_release=VPP_VERSION,
183 centos_version='centos7'):
184 """
185 Install the VPP packages
186
187 :param node: Node dictionary with cpuinfo.
188 :param fdio_release: VPP release number
189 :param centos_version: Ubuntu Version
190 :type node: dict
191 :type fdio_release: string
192 :type centos_version: string
193 """
194
195 # Modify the sources list
196 sfile = '/etc/yum.repos.d/fdio-release.repo'
197
198 # Backup the sources list
199 self._autoconfig_backup_file(sfile)
200
201 # Remove the current file
202 cmd = 'rm {}'.format(sfile)
203 (ret, stdout, stderr) = self.exec_command(cmd)
204 if ret != 0:
205 logging.debug('{} failed on node {} {}'.format(
206 cmd,
207 node['host'],
208 stderr))
209
John DeNisco4dc83972018-03-30 10:50:19 -0400210 # Latest
211 # reps = '[fdio-master]\n'
212 # reps += 'name=fd.io master branch latest merge\n'
213 # reps += 'baseurl=https://nexus.fd.io/content/repositories/fd.io.master.{}/\n'.format(centos_version)
214 # reps = '[fdio-stable-{}]\n'.format(fdio_release)
215 # reps += 'name=fd.io stable/{} branch latest merge\n'.format(fdio_release)
John DeNiscoc6b2a202017-11-01 12:37:47 -0400216 # When using stable
217 # reps += 'baseurl=https://nexus.fd.io/content/repositories/fd.io.stable.{}.{}/\n'.\
218 # format(fdio_release, centos_version)
John DeNiscoa7da67f2018-01-26 14:55:33 -0500219 # When using release
John DeNisco4dc83972018-03-30 10:50:19 -0400220 reps = '[fdio-release]\n'
221 reps += 'name=fd.io release branch latest merge\n'
John DeNiscoa7da67f2018-01-26 14:55:33 -0500222 reps += 'baseurl=https://nexus.fd.io/content/repositories/fd.io.{}/\n'.format(centos_version)
John DeNisco68b0ee32017-09-27 16:35:23 -0400223 reps += 'enabled=1\n'
224 reps += 'gpgcheck=0'
225
226 cmd = 'echo "{0}" | sudo tee {1}'.format(reps, sfile)
227 (ret, stdout, stderr) = self.exec_command(cmd)
228 if ret != 0:
229 raise RuntimeError('{} failed on node {} {}'.format(
230 cmd,
231 node['host'],
232 stderr))
233
234 # Install the packages
235
236 self._install_vpp_pkg_centos(node, 'vpp-lib')
237 self._install_vpp_pkg_centos(node, 'vpp')
238 self._install_vpp_pkg_centos(node, 'vpp-plugins')
John DeNisco68b0ee32017-09-27 16:35:23 -0400239 self._install_vpp_pkg_centos(node, 'vpp-api-python')
240 self._install_vpp_pkg_centos(node, 'vpp-api-java')
241 self._install_vpp_pkg_centos(node, 'vpp-api-lua')
242 self._install_vpp_pkg_centos(node, 'vpp-devel')
jdeniscob9875092018-11-06 16:10:04 -0500243 self._install_vpp_pkg_centos(node, 'vpp-debuginfo')
244 self._install_vpp_pkg_centos(node, 'vpp-nsh-plugin')
245 self._install_vpp_pkg_centos(node, 'vpp-nsh-plugin-devel')
246 self._install_vpp_pkg_centos(node, 'vpp-selinux-policy')
John DeNisco68b0ee32017-09-27 16:35:23 -0400247
248 def install_vpp(self, node):
249 """
250 Install the VPP packages
251
252 :param node: Node dictionary with cpuinfo.
253 :type node: dict
254 """
255 distro = self.get_linux_distro()
John DeNisco4dc83972018-03-30 10:50:19 -0400256 logging.info(" {}".format(distro[0]))
John DeNisco68b0ee32017-09-27 16:35:23 -0400257 if distro[0] == 'Ubuntu':
John DeNisco4dc83972018-03-30 10:50:19 -0400258 logging.info("Install Ubuntu")
John DeNisco68b0ee32017-09-27 16:35:23 -0400259 self._install_vpp_ubuntu(node)
260 elif distro[0] == 'CentOS Linux':
261 logging.info("Install CentOS")
262 self._install_vpp_centos(node)
263 else:
John DeNisco4dc83972018-03-30 10:50:19 -0400264 logging.info("Install CentOS (default)")
265 self._install_vpp_centos(node)
266 return
John DeNisco68b0ee32017-09-27 16:35:23 -0400267
268 def _uninstall_vpp_pkg_ubuntu(self, node, pkg):
269 """
270 Uninstall the VPP packages
271
272 :param node: Node dictionary
273 :param pkg: The vpp packages
274 :type node: dict
275 :type pkg: string
276 """
277 cmd = 'dpkg --purge {}'.format(pkg)
278 (ret, stdout, stderr) = self.exec_command(cmd)
279 if ret != 0:
280 raise RuntimeError('{} failed on node {} {} {}'.format(
281 cmd, node['host'], stdout, stderr))
282
283 def _uninstall_vpp_pkg_centos(self, node, pkg):
284 """
285 Uninstall the VPP packages
286
287 :param node: Node dictionary
288 :param pkg: The vpp packages
289 :type node: dict
290 :type pkg: string
291 """
292 cmd = 'yum -y remove {}'.format(pkg)
293 (ret, stdout, stderr) = self.exec_command(cmd)
294 if ret != 0:
295 raise RuntimeError('{} failed on node {} {} {}'.format(
296 cmd, node['host'], stdout, stderr))
297
298 def _uninstall_vpp_ubuntu(self, node):
299 """
300 Uninstall the VPP packages
301
302 :param node: Node dictionary with cpuinfo.
303 :type node: dict
304 """
305 pkgs = self.get_installed_vpp_pkgs()
306
307 if len(pkgs) > 0:
308 if 'version' in pkgs[0]:
309 logging.info("Uninstall Ubuntu Packages")
jdeniscob9875092018-11-06 16:10:04 -0500310 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-nsh-plugin-dev')
311 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-nsh-plugin-dbg')
312 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-nsh-plugin')
John DeNisco68b0ee32017-09-27 16:35:23 -0400313 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-api-python')
314 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-api-java')
315 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-api-lua')
316 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-plugins')
317 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-dpdk-dev')
318 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-dpdk-dkms')
319 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-dev')
320 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-dbg')
321 self._uninstall_vpp_pkg_ubuntu(node, 'vpp')
322 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-lib')
323 else:
324 logging.info("Uninstall locally installed Ubuntu Packages")
325 for pkg in pkgs:
326 self._uninstall_vpp_pkg_ubuntu(node, pkg['name'])
327 else:
328 logging.error("There are no Ubuntu packages installed")
329
330 def _uninstall_vpp_centos(self, node):
331 """
332 Uninstall the VPP packages
333
334 :param node: Node dictionary with cpuinfo.
335 :type node: dict
336 """
337
338 pkgs = self.get_installed_vpp_pkgs()
339
340 if len(pkgs) > 0:
341 if 'version' in pkgs[0]:
342 logging.info("Uninstall CentOS Packages")
jdeniscob9875092018-11-06 16:10:04 -0500343 self._uninstall_vpp_pkg_centos(node, 'vpp-selinux-policy')
344 self._uninstall_vpp_pkg_centos(node, 'vpp-nsh-plugin-devel')
345 self._uninstall_vpp_pkg_centos(node, 'vpp-nsh-plugin')
346 self._uninstall_vpp_pkg_centos(node, 'vpp-debuginfo')
John DeNisco68b0ee32017-09-27 16:35:23 -0400347 self._uninstall_vpp_pkg_centos(node, 'vpp-api-python')
348 self._uninstall_vpp_pkg_centos(node, 'vpp-api-java')
349 self._uninstall_vpp_pkg_centos(node, 'vpp-api-lua')
350 self._uninstall_vpp_pkg_centos(node, 'vpp-plugins')
John DeNisco68b0ee32017-09-27 16:35:23 -0400351 self._uninstall_vpp_pkg_centos(node, 'vpp-devel')
352 self._uninstall_vpp_pkg_centos(node, 'vpp')
353 self._uninstall_vpp_pkg_centos(node, 'vpp-lib')
354 else:
355 logging.info("Uninstall locally installed CentOS Packages")
356 for pkg in pkgs:
357 self._uninstall_vpp_pkg_centos(node, pkg['name'])
358 else:
359 logging.error("There are no CentOS packages installed")
360
361 def uninstall_vpp(self, node):
362 """
363 Uninstall the VPP packages
364
365 :param node: Node dictionary with cpuinfo.
366 :type node: dict
367 """
John DeNiscoc6b2a202017-11-01 12:37:47 -0400368
369 # First stop VPP
370 self.stop(node)
371
John DeNisco68b0ee32017-09-27 16:35:23 -0400372 distro = self.get_linux_distro()
373 if distro[0] == 'Ubuntu':
John DeNisco4dc83972018-03-30 10:50:19 -0400374 logging.info("Uninstall Ubuntu")
John DeNisco68b0ee32017-09-27 16:35:23 -0400375 self._uninstall_vpp_ubuntu(node)
376 elif distro[0] == 'CentOS Linux':
377 logging.info("Uninstall CentOS")
378 self._uninstall_vpp_centos(node)
379 else:
John DeNisco4dc83972018-03-30 10:50:19 -0400380 logging.info("Uninstall CentOS (Default)")
381 self._uninstall_vpp_centos(node)
John DeNisco68b0ee32017-09-27 16:35:23 -0400382 return
383
384 def show_vpp_settings(self, *additional_cmds):
385 """
386 Print default VPP settings. In case others are needed, can be
387 accepted as next parameters (each setting one parameter), preferably
388 in form of a string.
389
390 :param additional_cmds: Additional commands that the vpp should print
391 settings for.
392 :type additional_cmds: tuple
393 """
394 def_setting_tb_displayed = {
395 'IPv6 FIB': 'ip6 fib',
396 'IPv4 FIB': 'ip fib',
397 'Interface IP': 'int addr',
398 'Interfaces': 'int',
399 'ARP': 'ip arp',
400 'Errors': 'err'
401 }
402
403 if additional_cmds:
404 for cmd in additional_cmds:
405 def_setting_tb_displayed['Custom Setting: {}'.format(cmd)] \
406 = cmd
407
408 for _, value in def_setting_tb_displayed.items():
409 self.exec_command('vppctl sh {}'.format(value))
410
411 @staticmethod
John DeNiscoc6b2a202017-11-01 12:37:47 -0400412 def get_vms(node):
413 """
414 Get a list of VMs that are connected to VPP interfaces
415
416 :param node: VPP node.
417 :type node: dict
418 :returns: Dictionary containing a list of VMs and the interfaces that are connected to VPP
419 :rtype: dictionary
420 """
421
422 vmdict = {}
423
424 print "Need to implement get vms"
425
426 return vmdict
427
428 @staticmethod
John DeNiscoa3db0782017-10-17 11:07:22 -0400429 def get_int_ip(node):
430 """
431 Get the VPP interfaces and IP addresses
432
433 :param node: VPP node.
434 :type node: dict
435 :returns: Dictionary containing VPP interfaces and IP addresses
436 :rtype: dictionary
437 """
438 interfaces = {}
439 cmd = 'vppctl show int addr'
440 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
441 if ret != 0:
442 return interfaces
443
444 lines = stdout.split('\n')
445 if len(lines[0]) is not 0:
446 if lines[0].split(' ')[0] == 'FileNotFoundError':
447 return interfaces
448
John DeNiscoc6b2a202017-11-01 12:37:47 -0400449 name = ''
John DeNiscoa3db0782017-10-17 11:07:22 -0400450 for line in lines:
451 if len(line) is 0:
452 continue
453
454 # If the first character is not whitespace
455 # create a new interface
456 if len(re.findall(r'\s', line[0])) is 0:
457 spl = line.split()
458 name = spl[0]
459 if name == 'local0':
460 continue
461 interfaces[name] = {}
462 interfaces[name]['state'] = spl[1].lstrip('(').rstrip('):\r')
463 else:
464 interfaces[name]['address'] = line.lstrip(' ').rstrip('\r')
465
466 return interfaces
467
468 @staticmethod
John DeNisco68b0ee32017-09-27 16:35:23 -0400469 def get_hardware(node):
470 """
471 Get the VPP hardware information and return it in a
472 dictionary
473
474 :param node: VPP node.
475 :type node: dict
John DeNiscoa3db0782017-10-17 11:07:22 -0400476 :returns: Dictionary containing VPP hardware information
John DeNisco68b0ee32017-09-27 16:35:23 -0400477 :rtype: dictionary
478 """
479
480 interfaces = {}
481 cmd = 'vppctl show hard'
482 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
483 if ret != 0:
484 return interfaces
485
486 lines = stdout.split('\n')
487 if len(lines[0]) is not 0:
488 if lines[0].split(' ')[0] == 'FileNotFoundError':
489 return interfaces
490
491 for line in lines:
492 if len(line) is 0:
493 continue
494
495 # If the first character is not whitespace
496 # create a new interface
497 if len(re.findall(r'\s', line[0])) is 0:
498 spl = line.split()
499 name = spl[0]
500 interfaces[name] = {}
501 interfaces[name]['index'] = spl[1]
502 interfaces[name]['state'] = spl[2]
503
504 # Ethernet address
505 rfall = re.findall(r'Ethernet address', line)
506 if rfall:
507 spl = line.split()
508 interfaces[name]['mac'] = spl[2]
509
510 # Carrier
511 rfall = re.findall(r'carrier', line)
512 if rfall:
513 spl = line.split('carrier ')
514 interfaces[name]['carrier'] = spl[1]
515
516 # Socket
517 rfall = re.findall(r'cpu socket', line)
518 if rfall:
519 spl = line.split('cpu socket ')
520 interfaces[name]['cpu socket'] = spl[1]
521
522 # Queues and Descriptors
523 rfall = re.findall(r'rx queues', line)
524 if rfall:
525 spl = line.split(',')
526 interfaces[name]['rx queues'] = spl[0].lstrip(' ').split(' ')[2]
527 interfaces[name]['rx descs'] = spl[1].split(' ')[3]
528 interfaces[name]['tx queues'] = spl[2].split(' ')[3]
529 interfaces[name]['tx descs'] = spl[3].split(' ')[3]
530
531 return interfaces
532
533 def _get_installed_vpp_pkgs_ubuntu(self):
534 """
535 Get the VPP hardware information and return it in a
536 dictionary
537
538 :returns: List of the packages installed
539 :rtype: list
540 """
541
542 pkgs = []
543 cmd = 'dpkg -l | grep vpp'
544 (ret, stdout, stderr) = self.exec_command(cmd)
545 if ret != 0:
546 return pkgs
547
548 lines = stdout.split('\n')
549 for line in lines:
550 items = line.split()
551 if len(items) < 2:
552 continue
553 pkg = {'name': items[1], 'version': items[2]}
554 pkgs.append(pkg)
555
556 return pkgs
557
558 def _get_installed_vpp_pkgs_centos(self):
559 """
560 Get the VPP hardware information and return it in a
561 dictionary
562
563 :returns: List of the packages installed
564 :rtype: list
565 """
566
567 pkgs = []
568 cmd = 'rpm -qa | grep vpp'
569 (ret, stdout, stderr) = self.exec_command(cmd)
570 if ret != 0:
571 return pkgs
572
573 lines = stdout.split('\n')
574 for line in lines:
575 if len(line) == 0:
576 continue
577
578 items = line.split()
579 if len(items) < 2:
580 pkg = {'name': items[0]}
581 else:
582 pkg = {'name': items[1], 'version': items[2]}
583
584 pkgs.append(pkg)
585
586 return pkgs
587
588 def get_installed_vpp_pkgs(self):
589 """
590 Get the VPP hardware information and return it in a
591 dictionary
592
593 :returns: List of the packages installed
594 :rtype: list
595 """
596
597 distro = self.get_linux_distro()
598 if distro[0] == 'Ubuntu':
599 pkgs = self._get_installed_vpp_pkgs_ubuntu()
600 elif distro[0] == 'CentOS Linux':
601 pkgs = self._get_installed_vpp_pkgs_centos()
602 else:
John DeNisco4dc83972018-03-30 10:50:19 -0400603 pkgs = self._get_installed_vpp_pkgs_centos()
John DeNisco68b0ee32017-09-27 16:35:23 -0400604 return []
605
606 return pkgs
607
608 @staticmethod
609 def get_interfaces_numa_node(node, *iface_keys):
610 """Get numa node on which are located most of the interfaces.
611
612 Return numa node with highest count of interfaces provided as arguments.
613 Return 0 if the interface does not have numa_node information available.
614 If all interfaces have unknown location (-1), then return 0.
615 If most of interfaces have unknown location (-1), but there are
616 some interfaces with known location, then return the second most
617 location of the provided interfaces.
618
619 :param node: Node from DICT__nodes.
620 :param iface_keys: Interface keys for lookup.
621 :type node: dict
622 :type iface_keys: strings
623 """
624 numa_list = []
625 for if_key in iface_keys:
626 try:
627 numa_list.append(node['interfaces'][if_key].get('numa_node'))
628 except KeyError:
629 pass
630
631 numa_cnt_mc = Counter(numa_list).most_common()
632 numa_cnt_mc_len = len(numa_cnt_mc)
633 if numa_cnt_mc_len > 0 and numa_cnt_mc[0][0] != -1:
634 return numa_cnt_mc[0][0]
635 elif numa_cnt_mc_len > 1 and numa_cnt_mc[0][0] == -1:
636 return numa_cnt_mc[1][0]
637
638 return 0
639
640 @staticmethod
John DeNiscoc6b2a202017-11-01 12:37:47 -0400641 def restart(node):
642 """
643
644 Starts vpp for a given node
645
646 :param node: VPP node.
647 :type node: dict
648 """
649
650 cmd = 'service vpp restart'
651 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
652 if ret != 0:
653 raise RuntimeError('{} failed on node {} {} {}'.
654 format(cmd, node['host'],
655 stdout, stderr))
656
657 @staticmethod
John DeNisco68b0ee32017-09-27 16:35:23 -0400658 def start(node):
659 """
660
661 Starts vpp for a given node
662
663 :param node: VPP node.
664 :type node: dict
665 """
666
667 cmd = 'service vpp start'
668 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
669 if ret != 0:
670 raise RuntimeError('{} failed on node {} {} {}'.
671 format(cmd, node['host'],
672 stdout, stderr))
673
674 @staticmethod
675 def stop(node):
676 """
677
678 Stops vpp for a given node
679
680 :param node: VPP node.
681 :type node: dict
682 """
683
684 cmd = 'service vpp stop'
685 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
686 if ret != 0:
687 raise RuntimeError('{} failed on node {} {} {}'.
688 format(cmd, node['host'],
689 stdout, stderr))
690
John DeNiscoa7da67f2018-01-26 14:55:33 -0500691 # noinspection RegExpRedundantEscape
John DeNisco68b0ee32017-09-27 16:35:23 -0400692 @staticmethod
693 def status(node):
694 """
695
696 Gets VPP status
697
698 :param: node
699 :type node: dict
700 :returns: status, errors
701 :rtype: tuple(str, list)
702 """
703 errors = []
704 vutil = VPPUtil()
705 pkgs = vutil.get_installed_vpp_pkgs()
706 if len(pkgs) == 0:
707 return "Not Installed", errors
708
709 cmd = 'service vpp status'
710 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
711
712 # Get the active status
713 state = re.findall(r'Active:[\w (\)]+', stdout)[0].split(' ')
714 if len(state) > 2:
715 statestr = "{} {}".format(state[1], state[2])
716 else:
717 statestr = "Invalid"
718
719 # For now we won't look for DPDK errors
720 # lines = stdout.split('\n')
721 # for line in lines:
722 # if 'EAL' in line or \
723 # 'FAILURE' in line or \
724 # 'failed' in line or \
725 # 'Failed' in line:
726 # errors.append(line.lstrip(' '))
727
728 return statestr, errors
729
730 @staticmethod
731 def get_linux_distro():
732 """
733 Get the linux distribution and check if it is supported
734
735 :returns: linux distro, None if the distro is not supported
736 :rtype: list
737 """
738
739 distro = platform.linux_distribution()
740 if distro[0] == 'Ubuntu' or \
741 distro[0] == 'CentOS Linux' or \
John DeNisco4dc83972018-03-30 10:50:19 -0400742 distro[:7] == 'Red Hat':
John DeNisco68b0ee32017-09-27 16:35:23 -0400743 return distro
744 else:
745 raise RuntimeError('Linux Distribution {} is not supported'.format(distro[0]))
746
747 @staticmethod
748 def version():
749 """
750
751 Gets VPP Version information
752
753 :returns: version
754 :rtype: dict
755 """
756
757 version = {}
758 cmd = 'vppctl show version verbose'
759 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
760 if ret != 0:
761 return version
762
763 lines = stdout.split('\n')
764 if len(lines[0]) is not 0:
765 if lines[0].split(' ')[0] == 'FileNotFoundError':
766 return version
767
768 for line in lines:
769 if len(line) is 0:
770 continue
771 dct = line.split(':')
772 version[dct[0]] = dct[1].lstrip(' ')
773
774 return version
John DeNiscoc6b2a202017-11-01 12:37:47 -0400775
776 @staticmethod
777 def show_bridge(node):
778 """
779 Shows the current bridge configuration
780
781 :param node: VPP node.
782 :type node: dict
John DeNisco9fa5cf42018-02-06 15:23:05 -0500783 :returns: A list of interfaces
John DeNiscoc6b2a202017-11-01 12:37:47 -0400784 """
785
John DeNisco9fa5cf42018-02-06 15:23:05 -0500786 ifaces = []
John DeNiscoc6b2a202017-11-01 12:37:47 -0400787 cmd = 'vppctl show bridge'
788 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
789 if ret != 0:
790 raise RuntimeError('{} failed on node {} {} {}'.
791 format(cmd, node['host'],
792 stdout, stderr))
793 lines = stdout.split('\r\n')
794 bridges = []
795 for line in lines:
796 if line == 'no bridge-domains in use':
797 print line
John DeNisco9fa5cf42018-02-06 15:23:05 -0500798 return ifaces
John DeNiscoc6b2a202017-11-01 12:37:47 -0400799 if len(line) == 0:
800 continue
801
802 lspl = line.lstrip(' ').split()
803 if lspl[0] != 'BD-ID':
804 bridges.append(lspl[0])
805
806 for bridge in bridges:
807 cmd = 'vppctl show bridge {} detail'.format(bridge)
808 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
809 if ret != 0:
810 raise RuntimeError('{} failed on node {} {} {}'.
811 format(cmd, node['host'],
812 stdout, stderr))
John DeNisco9fa5cf42018-02-06 15:23:05 -0500813
814 lines = stdout.split('\r\n')
815 for line in lines:
816 iface = re.findall(r'[a-zA-z]+\d+/\d+/\d+', line)
817 if len(iface):
818 ifcidx ={'name': iface[0], 'index': line.split()[1] }
819 ifaces.append(ifcidx)
820
821 print stdout
John DeNisco4dc83972018-03-30 10:50:19 -0400822 return ifaces