blob: 6f13a437826396fa8cd00863cfa755b7ffdf95bb [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'
24VPP_VERSION = '1801'
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')
178
179 def _install_vpp_centos(self, node, fdio_release=VPP_VERSION,
180 centos_version='centos7'):
181 """
182 Install the VPP packages
183
184 :param node: Node dictionary with cpuinfo.
185 :param fdio_release: VPP release number
186 :param centos_version: Ubuntu Version
187 :type node: dict
188 :type fdio_release: string
189 :type centos_version: string
190 """
191
192 # Modify the sources list
193 sfile = '/etc/yum.repos.d/fdio-release.repo'
194
195 # Backup the sources list
196 self._autoconfig_backup_file(sfile)
197
198 # Remove the current file
199 cmd = 'rm {}'.format(sfile)
200 (ret, stdout, stderr) = self.exec_command(cmd)
201 if ret != 0:
202 logging.debug('{} failed on node {} {}'.format(
203 cmd,
204 node['host'],
205 stderr))
206
John DeNisco4dc83972018-03-30 10:50:19 -0400207 # Latest
208 # reps = '[fdio-master]\n'
209 # reps += 'name=fd.io master branch latest merge\n'
210 # reps += 'baseurl=https://nexus.fd.io/content/repositories/fd.io.master.{}/\n'.format(centos_version)
211 # reps = '[fdio-stable-{}]\n'.format(fdio_release)
212 # reps += 'name=fd.io stable/{} branch latest merge\n'.format(fdio_release)
John DeNiscoc6b2a202017-11-01 12:37:47 -0400213 # When using stable
214 # reps += 'baseurl=https://nexus.fd.io/content/repositories/fd.io.stable.{}.{}/\n'.\
215 # format(fdio_release, centos_version)
John DeNiscoa7da67f2018-01-26 14:55:33 -0500216 # When using release
John DeNisco4dc83972018-03-30 10:50:19 -0400217 reps = '[fdio-release]\n'
218 reps += 'name=fd.io release branch latest merge\n'
John DeNiscoa7da67f2018-01-26 14:55:33 -0500219 reps += 'baseurl=https://nexus.fd.io/content/repositories/fd.io.{}/\n'.format(centos_version)
John DeNisco68b0ee32017-09-27 16:35:23 -0400220 reps += 'enabled=1\n'
221 reps += 'gpgcheck=0'
222
223 cmd = 'echo "{0}" | sudo tee {1}'.format(reps, sfile)
224 (ret, stdout, stderr) = self.exec_command(cmd)
225 if ret != 0:
226 raise RuntimeError('{} failed on node {} {}'.format(
227 cmd,
228 node['host'],
229 stderr))
230
231 # Install the packages
232
233 self._install_vpp_pkg_centos(node, 'vpp-lib')
234 self._install_vpp_pkg_centos(node, 'vpp')
235 self._install_vpp_pkg_centos(node, 'vpp-plugins')
236 # jadfix Check with Ole
237 # self._install_vpp_pkg_centos(node, 'vpp-dpdk-devel')
238 self._install_vpp_pkg_centos(node, 'vpp-api-python')
239 self._install_vpp_pkg_centos(node, 'vpp-api-java')
240 self._install_vpp_pkg_centos(node, 'vpp-api-lua')
241 self._install_vpp_pkg_centos(node, 'vpp-devel')
242
243 def install_vpp(self, node):
244 """
245 Install the VPP packages
246
247 :param node: Node dictionary with cpuinfo.
248 :type node: dict
249 """
250 distro = self.get_linux_distro()
John DeNisco4dc83972018-03-30 10:50:19 -0400251 logging.info(" {}".format(distro[0]))
John DeNisco68b0ee32017-09-27 16:35:23 -0400252 if distro[0] == 'Ubuntu':
John DeNisco4dc83972018-03-30 10:50:19 -0400253 logging.info("Install Ubuntu")
John DeNisco68b0ee32017-09-27 16:35:23 -0400254 self._install_vpp_ubuntu(node)
255 elif distro[0] == 'CentOS Linux':
256 logging.info("Install CentOS")
257 self._install_vpp_centos(node)
258 else:
John DeNisco4dc83972018-03-30 10:50:19 -0400259 logging.info("Install CentOS (default)")
260 self._install_vpp_centos(node)
261 return
John DeNisco68b0ee32017-09-27 16:35:23 -0400262
263 def _uninstall_vpp_pkg_ubuntu(self, node, pkg):
264 """
265 Uninstall the VPP packages
266
267 :param node: Node dictionary
268 :param pkg: The vpp packages
269 :type node: dict
270 :type pkg: string
271 """
272 cmd = 'dpkg --purge {}'.format(pkg)
273 (ret, stdout, stderr) = self.exec_command(cmd)
274 if ret != 0:
275 raise RuntimeError('{} failed on node {} {} {}'.format(
276 cmd, node['host'], stdout, stderr))
277
278 def _uninstall_vpp_pkg_centos(self, node, pkg):
279 """
280 Uninstall the VPP packages
281
282 :param node: Node dictionary
283 :param pkg: The vpp packages
284 :type node: dict
285 :type pkg: string
286 """
287 cmd = 'yum -y remove {}'.format(pkg)
288 (ret, stdout, stderr) = self.exec_command(cmd)
289 if ret != 0:
290 raise RuntimeError('{} failed on node {} {} {}'.format(
291 cmd, node['host'], stdout, stderr))
292
293 def _uninstall_vpp_ubuntu(self, node):
294 """
295 Uninstall the VPP packages
296
297 :param node: Node dictionary with cpuinfo.
298 :type node: dict
299 """
300 pkgs = self.get_installed_vpp_pkgs()
301
302 if len(pkgs) > 0:
303 if 'version' in pkgs[0]:
304 logging.info("Uninstall Ubuntu Packages")
305 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-api-python')
306 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-api-java')
307 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-api-lua')
308 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-plugins')
309 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-dpdk-dev')
310 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-dpdk-dkms')
311 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-dev')
312 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-dbg')
313 self._uninstall_vpp_pkg_ubuntu(node, 'vpp')
314 self._uninstall_vpp_pkg_ubuntu(node, 'vpp-lib')
315 else:
316 logging.info("Uninstall locally installed Ubuntu Packages")
317 for pkg in pkgs:
318 self._uninstall_vpp_pkg_ubuntu(node, pkg['name'])
319 else:
320 logging.error("There are no Ubuntu packages installed")
321
322 def _uninstall_vpp_centos(self, node):
323 """
324 Uninstall the VPP packages
325
326 :param node: Node dictionary with cpuinfo.
327 :type node: dict
328 """
329
330 pkgs = self.get_installed_vpp_pkgs()
331
332 if len(pkgs) > 0:
333 if 'version' in pkgs[0]:
334 logging.info("Uninstall CentOS Packages")
335 self._uninstall_vpp_pkg_centos(node, 'vpp-api-python')
336 self._uninstall_vpp_pkg_centos(node, 'vpp-api-java')
337 self._uninstall_vpp_pkg_centos(node, 'vpp-api-lua')
338 self._uninstall_vpp_pkg_centos(node, 'vpp-plugins')
339 self._uninstall_vpp_pkg_centos(node, 'vpp-dpdk-devel')
340 self._uninstall_vpp_pkg_centos(node, 'vpp-devel')
341 self._uninstall_vpp_pkg_centos(node, 'vpp')
342 self._uninstall_vpp_pkg_centos(node, 'vpp-lib')
343 else:
344 logging.info("Uninstall locally installed CentOS Packages")
345 for pkg in pkgs:
346 self._uninstall_vpp_pkg_centos(node, pkg['name'])
347 else:
348 logging.error("There are no CentOS packages installed")
349
350 def uninstall_vpp(self, node):
351 """
352 Uninstall the VPP packages
353
354 :param node: Node dictionary with cpuinfo.
355 :type node: dict
356 """
John DeNiscoc6b2a202017-11-01 12:37:47 -0400357
358 # First stop VPP
359 self.stop(node)
360
John DeNisco68b0ee32017-09-27 16:35:23 -0400361 distro = self.get_linux_distro()
362 if distro[0] == 'Ubuntu':
John DeNisco4dc83972018-03-30 10:50:19 -0400363 logging.info("Uninstall Ubuntu")
John DeNisco68b0ee32017-09-27 16:35:23 -0400364 self._uninstall_vpp_ubuntu(node)
365 elif distro[0] == 'CentOS Linux':
366 logging.info("Uninstall CentOS")
367 self._uninstall_vpp_centos(node)
368 else:
John DeNisco4dc83972018-03-30 10:50:19 -0400369 logging.info("Uninstall CentOS (Default)")
370 self._uninstall_vpp_centos(node)
John DeNisco68b0ee32017-09-27 16:35:23 -0400371 return
372
373 def show_vpp_settings(self, *additional_cmds):
374 """
375 Print default VPP settings. In case others are needed, can be
376 accepted as next parameters (each setting one parameter), preferably
377 in form of a string.
378
379 :param additional_cmds: Additional commands that the vpp should print
380 settings for.
381 :type additional_cmds: tuple
382 """
383 def_setting_tb_displayed = {
384 'IPv6 FIB': 'ip6 fib',
385 'IPv4 FIB': 'ip fib',
386 'Interface IP': 'int addr',
387 'Interfaces': 'int',
388 'ARP': 'ip arp',
389 'Errors': 'err'
390 }
391
392 if additional_cmds:
393 for cmd in additional_cmds:
394 def_setting_tb_displayed['Custom Setting: {}'.format(cmd)] \
395 = cmd
396
397 for _, value in def_setting_tb_displayed.items():
398 self.exec_command('vppctl sh {}'.format(value))
399
400 @staticmethod
John DeNiscoc6b2a202017-11-01 12:37:47 -0400401 def get_vms(node):
402 """
403 Get a list of VMs that are connected to VPP interfaces
404
405 :param node: VPP node.
406 :type node: dict
407 :returns: Dictionary containing a list of VMs and the interfaces that are connected to VPP
408 :rtype: dictionary
409 """
410
411 vmdict = {}
412
413 print "Need to implement get vms"
414
415 return vmdict
416
417 @staticmethod
John DeNiscoa3db0782017-10-17 11:07:22 -0400418 def get_int_ip(node):
419 """
420 Get the VPP interfaces and IP addresses
421
422 :param node: VPP node.
423 :type node: dict
424 :returns: Dictionary containing VPP interfaces and IP addresses
425 :rtype: dictionary
426 """
427 interfaces = {}
428 cmd = 'vppctl show int addr'
429 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
430 if ret != 0:
431 return interfaces
432
433 lines = stdout.split('\n')
434 if len(lines[0]) is not 0:
435 if lines[0].split(' ')[0] == 'FileNotFoundError':
436 return interfaces
437
John DeNiscoc6b2a202017-11-01 12:37:47 -0400438 name = ''
John DeNiscoa3db0782017-10-17 11:07:22 -0400439 for line in lines:
440 if len(line) is 0:
441 continue
442
443 # If the first character is not whitespace
444 # create a new interface
445 if len(re.findall(r'\s', line[0])) is 0:
446 spl = line.split()
447 name = spl[0]
448 if name == 'local0':
449 continue
450 interfaces[name] = {}
451 interfaces[name]['state'] = spl[1].lstrip('(').rstrip('):\r')
452 else:
453 interfaces[name]['address'] = line.lstrip(' ').rstrip('\r')
454
455 return interfaces
456
457 @staticmethod
John DeNisco68b0ee32017-09-27 16:35:23 -0400458 def get_hardware(node):
459 """
460 Get the VPP hardware information and return it in a
461 dictionary
462
463 :param node: VPP node.
464 :type node: dict
John DeNiscoa3db0782017-10-17 11:07:22 -0400465 :returns: Dictionary containing VPP hardware information
John DeNisco68b0ee32017-09-27 16:35:23 -0400466 :rtype: dictionary
467 """
468
469 interfaces = {}
470 cmd = 'vppctl show hard'
471 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
472 if ret != 0:
473 return interfaces
474
475 lines = stdout.split('\n')
476 if len(lines[0]) is not 0:
477 if lines[0].split(' ')[0] == 'FileNotFoundError':
478 return interfaces
479
480 for line in lines:
481 if len(line) is 0:
482 continue
483
484 # If the first character is not whitespace
485 # create a new interface
486 if len(re.findall(r'\s', line[0])) is 0:
487 spl = line.split()
488 name = spl[0]
489 interfaces[name] = {}
490 interfaces[name]['index'] = spl[1]
491 interfaces[name]['state'] = spl[2]
492
493 # Ethernet address
494 rfall = re.findall(r'Ethernet address', line)
495 if rfall:
496 spl = line.split()
497 interfaces[name]['mac'] = spl[2]
498
499 # Carrier
500 rfall = re.findall(r'carrier', line)
501 if rfall:
502 spl = line.split('carrier ')
503 interfaces[name]['carrier'] = spl[1]
504
505 # Socket
506 rfall = re.findall(r'cpu socket', line)
507 if rfall:
508 spl = line.split('cpu socket ')
509 interfaces[name]['cpu socket'] = spl[1]
510
511 # Queues and Descriptors
512 rfall = re.findall(r'rx queues', line)
513 if rfall:
514 spl = line.split(',')
515 interfaces[name]['rx queues'] = spl[0].lstrip(' ').split(' ')[2]
516 interfaces[name]['rx descs'] = spl[1].split(' ')[3]
517 interfaces[name]['tx queues'] = spl[2].split(' ')[3]
518 interfaces[name]['tx descs'] = spl[3].split(' ')[3]
519
520 return interfaces
521
522 def _get_installed_vpp_pkgs_ubuntu(self):
523 """
524 Get the VPP hardware information and return it in a
525 dictionary
526
527 :returns: List of the packages installed
528 :rtype: list
529 """
530
531 pkgs = []
532 cmd = 'dpkg -l | grep vpp'
533 (ret, stdout, stderr) = self.exec_command(cmd)
534 if ret != 0:
535 return pkgs
536
537 lines = stdout.split('\n')
538 for line in lines:
539 items = line.split()
540 if len(items) < 2:
541 continue
542 pkg = {'name': items[1], 'version': items[2]}
543 pkgs.append(pkg)
544
545 return pkgs
546
547 def _get_installed_vpp_pkgs_centos(self):
548 """
549 Get the VPP hardware information and return it in a
550 dictionary
551
552 :returns: List of the packages installed
553 :rtype: list
554 """
555
556 pkgs = []
557 cmd = 'rpm -qa | grep vpp'
558 (ret, stdout, stderr) = self.exec_command(cmd)
559 if ret != 0:
560 return pkgs
561
562 lines = stdout.split('\n')
563 for line in lines:
564 if len(line) == 0:
565 continue
566
567 items = line.split()
568 if len(items) < 2:
569 pkg = {'name': items[0]}
570 else:
571 pkg = {'name': items[1], 'version': items[2]}
572
573 pkgs.append(pkg)
574
575 return pkgs
576
577 def get_installed_vpp_pkgs(self):
578 """
579 Get the VPP hardware information and return it in a
580 dictionary
581
582 :returns: List of the packages installed
583 :rtype: list
584 """
585
586 distro = self.get_linux_distro()
587 if distro[0] == 'Ubuntu':
588 pkgs = self._get_installed_vpp_pkgs_ubuntu()
589 elif distro[0] == 'CentOS Linux':
590 pkgs = self._get_installed_vpp_pkgs_centos()
591 else:
John DeNisco4dc83972018-03-30 10:50:19 -0400592 pkgs = self._get_installed_vpp_pkgs_centos()
John DeNisco68b0ee32017-09-27 16:35:23 -0400593 return []
594
595 return pkgs
596
597 @staticmethod
598 def get_interfaces_numa_node(node, *iface_keys):
599 """Get numa node on which are located most of the interfaces.
600
601 Return numa node with highest count of interfaces provided as arguments.
602 Return 0 if the interface does not have numa_node information available.
603 If all interfaces have unknown location (-1), then return 0.
604 If most of interfaces have unknown location (-1), but there are
605 some interfaces with known location, then return the second most
606 location of the provided interfaces.
607
608 :param node: Node from DICT__nodes.
609 :param iface_keys: Interface keys for lookup.
610 :type node: dict
611 :type iface_keys: strings
612 """
613 numa_list = []
614 for if_key in iface_keys:
615 try:
616 numa_list.append(node['interfaces'][if_key].get('numa_node'))
617 except KeyError:
618 pass
619
620 numa_cnt_mc = Counter(numa_list).most_common()
621 numa_cnt_mc_len = len(numa_cnt_mc)
622 if numa_cnt_mc_len > 0 and numa_cnt_mc[0][0] != -1:
623 return numa_cnt_mc[0][0]
624 elif numa_cnt_mc_len > 1 and numa_cnt_mc[0][0] == -1:
625 return numa_cnt_mc[1][0]
626
627 return 0
628
629 @staticmethod
John DeNiscoc6b2a202017-11-01 12:37:47 -0400630 def restart(node):
631 """
632
633 Starts vpp for a given node
634
635 :param node: VPP node.
636 :type node: dict
637 """
638
639 cmd = 'service vpp restart'
640 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
641 if ret != 0:
642 raise RuntimeError('{} failed on node {} {} {}'.
643 format(cmd, node['host'],
644 stdout, stderr))
645
646 @staticmethod
John DeNisco68b0ee32017-09-27 16:35:23 -0400647 def start(node):
648 """
649
650 Starts vpp for a given node
651
652 :param node: VPP node.
653 :type node: dict
654 """
655
656 cmd = 'service vpp start'
657 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
658 if ret != 0:
659 raise RuntimeError('{} failed on node {} {} {}'.
660 format(cmd, node['host'],
661 stdout, stderr))
662
663 @staticmethod
664 def stop(node):
665 """
666
667 Stops vpp for a given node
668
669 :param node: VPP node.
670 :type node: dict
671 """
672
673 cmd = 'service vpp stop'
674 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
675 if ret != 0:
676 raise RuntimeError('{} failed on node {} {} {}'.
677 format(cmd, node['host'],
678 stdout, stderr))
679
John DeNiscoa7da67f2018-01-26 14:55:33 -0500680 # noinspection RegExpRedundantEscape
John DeNisco68b0ee32017-09-27 16:35:23 -0400681 @staticmethod
682 def status(node):
683 """
684
685 Gets VPP status
686
687 :param: node
688 :type node: dict
689 :returns: status, errors
690 :rtype: tuple(str, list)
691 """
692 errors = []
693 vutil = VPPUtil()
694 pkgs = vutil.get_installed_vpp_pkgs()
695 if len(pkgs) == 0:
696 return "Not Installed", errors
697
698 cmd = 'service vpp status'
699 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
700
701 # Get the active status
702 state = re.findall(r'Active:[\w (\)]+', stdout)[0].split(' ')
703 if len(state) > 2:
704 statestr = "{} {}".format(state[1], state[2])
705 else:
706 statestr = "Invalid"
707
708 # For now we won't look for DPDK errors
709 # lines = stdout.split('\n')
710 # for line in lines:
711 # if 'EAL' in line or \
712 # 'FAILURE' in line or \
713 # 'failed' in line or \
714 # 'Failed' in line:
715 # errors.append(line.lstrip(' '))
716
717 return statestr, errors
718
719 @staticmethod
720 def get_linux_distro():
721 """
722 Get the linux distribution and check if it is supported
723
724 :returns: linux distro, None if the distro is not supported
725 :rtype: list
726 """
727
728 distro = platform.linux_distribution()
729 if distro[0] == 'Ubuntu' or \
730 distro[0] == 'CentOS Linux' or \
John DeNisco4dc83972018-03-30 10:50:19 -0400731 distro[:7] == 'Red Hat':
John DeNisco68b0ee32017-09-27 16:35:23 -0400732 return distro
733 else:
734 raise RuntimeError('Linux Distribution {} is not supported'.format(distro[0]))
735
736 @staticmethod
737 def version():
738 """
739
740 Gets VPP Version information
741
742 :returns: version
743 :rtype: dict
744 """
745
746 version = {}
747 cmd = 'vppctl show version verbose'
748 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
749 if ret != 0:
750 return version
751
752 lines = stdout.split('\n')
753 if len(lines[0]) is not 0:
754 if lines[0].split(' ')[0] == 'FileNotFoundError':
755 return version
756
757 for line in lines:
758 if len(line) is 0:
759 continue
760 dct = line.split(':')
761 version[dct[0]] = dct[1].lstrip(' ')
762
763 return version
John DeNiscoc6b2a202017-11-01 12:37:47 -0400764
765 @staticmethod
766 def show_bridge(node):
767 """
768 Shows the current bridge configuration
769
770 :param node: VPP node.
771 :type node: dict
John DeNisco9fa5cf42018-02-06 15:23:05 -0500772 :returns: A list of interfaces
John DeNiscoc6b2a202017-11-01 12:37:47 -0400773 """
774
John DeNisco9fa5cf42018-02-06 15:23:05 -0500775 ifaces = []
John DeNiscoc6b2a202017-11-01 12:37:47 -0400776 cmd = 'vppctl show bridge'
777 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
778 if ret != 0:
779 raise RuntimeError('{} failed on node {} {} {}'.
780 format(cmd, node['host'],
781 stdout, stderr))
782 lines = stdout.split('\r\n')
783 bridges = []
784 for line in lines:
785 if line == 'no bridge-domains in use':
786 print line
John DeNisco9fa5cf42018-02-06 15:23:05 -0500787 return ifaces
John DeNiscoc6b2a202017-11-01 12:37:47 -0400788 if len(line) == 0:
789 continue
790
791 lspl = line.lstrip(' ').split()
792 if lspl[0] != 'BD-ID':
793 bridges.append(lspl[0])
794
795 for bridge in bridges:
796 cmd = 'vppctl show bridge {} detail'.format(bridge)
797 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
798 if ret != 0:
799 raise RuntimeError('{} failed on node {} {} {}'.
800 format(cmd, node['host'],
801 stdout, stderr))
John DeNisco9fa5cf42018-02-06 15:23:05 -0500802
803 lines = stdout.split('\r\n')
804 for line in lines:
805 iface = re.findall(r'[a-zA-z]+\d+/\d+/\d+', line)
806 if len(iface):
807 ifcidx ={'name': iface[0], 'index': line.split()[1] }
808 ifaces.append(ifcidx)
809
810 print stdout
John DeNisco4dc83972018-03-30 10:50:19 -0400811 return ifaces