ade905e24f74c37da9404c64815ca8b7633d1255
[vpp.git] / extras / vpp_config / vpplib / VPPUtil.py
1 # 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"""
15 import logging
16 import re
17 import subprocess
18 import platform
19
20 from collections import Counter
21
22 # VPP_VERSION = '1707'
23 # VPP_VERSION = '1710'
24 VPP_VERSION = '1804'
25
26
27 class 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/'
144         # When using a stable branch
145         # 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)
148         # When using master
149         # reps += 'repositories/fd.io.master.ubuntu.{}.main/ ./\n'.format(ubuntu_version)
150
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         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')
181
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
210         # 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)
216         # When using stable
217         # reps += 'baseurl=https://nexus.fd.io/content/repositories/fd.io.stable.{}.{}/\n'.\
218         #     format(fdio_release, centos_version)
219         # When using release
220         reps = '[fdio-release]\n'
221         reps += 'name=fd.io release branch latest merge\n'
222         reps += 'baseurl=https://nexus.fd.io/content/repositories/fd.io.{}/\n'.format(centos_version)
223         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')
239         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')
243         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')
247
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()
256         logging.info("  {}".format(distro[0]))
257         if distro[0] == 'Ubuntu':
258             logging.info("Install Ubuntu")
259             self._install_vpp_ubuntu(node)
260         elif distro[0] == 'CentOS Linux':
261             logging.info("Install CentOS")
262             self._install_vpp_centos(node)
263         else:
264             logging.info("Install CentOS (default)")
265             self._install_vpp_centos(node)
266         return
267
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")
310                 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')
313                 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")
343                 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')
347                 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')
351                 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         """
368
369         # First stop VPP
370         self.stop(node)
371
372         distro = self.get_linux_distro()
373         if distro[0] == 'Ubuntu':
374             logging.info("Uninstall Ubuntu")
375             self._uninstall_vpp_ubuntu(node)
376         elif distro[0] == 'CentOS Linux':
377             logging.info("Uninstall CentOS")
378             self._uninstall_vpp_centos(node)
379         else:
380             logging.info("Uninstall CentOS (Default)")
381             self._uninstall_vpp_centos(node)
382             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
412     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
429     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
449         name = ''
450         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
469     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
476         :returns: Dictionary containing VPP hardware information
477         :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:
603             pkgs = self._get_installed_vpp_pkgs_centos()
604             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
641     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
658     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
691     # noinspection RegExpRedundantEscape
692     @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 \
742                         distro[:7] == 'Red Hat':
743             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
775
776     @staticmethod
777     def show_bridge(node):
778         """
779         Shows the current bridge configuration
780
781         :param node: VPP node.
782         :type node: dict
783         :returns: A list of interfaces
784         """
785
786         ifaces = []
787         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
798                 return ifaces
799             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))
813
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
822         return ifaces