diff options
author | John DeNisco <jdenisco@cisco.com> | 2017-11-01 12:37:47 -0400 |
---|---|---|
committer | Chris Luke <chris_luke@comcast.com> | 2017-11-01 18:06:33 +0000 |
commit | c6b2a206b6a27bd136adb856cf51828bf91d892d (patch) | |
tree | 51a38aa2b75cfd344e742311778c635b317a2434 /extras/vpp_config/vpplib | |
parent | a74b7419bd6c7c5b23f59253b0b0b6c0d683794d (diff) |
A bit of cleanup, updated the README, started vhost test.
Change-Id: I49b998644b8b79c778c1186fc09831b1cd8fc015
Signed-off-by: John DeNisco <jdenisco@cisco.com>
Diffstat (limited to 'extras/vpp_config/vpplib')
-rw-r--r-- | extras/vpp_config/vpplib/AutoConfig.py | 153 | ||||
-rw-r--r-- | extras/vpp_config/vpplib/VPPUtil.py | 90 | ||||
-rw-r--r-- | extras/vpp_config/vpplib/VppGrubUtil.py | 9 | ||||
-rw-r--r-- | extras/vpp_config/vpplib/VppPCIUtil.py | 7 |
4 files changed, 224 insertions, 35 deletions
diff --git a/extras/vpp_config/vpplib/AutoConfig.py b/extras/vpp_config/vpplib/AutoConfig.py index ab943e0ef21..7b7d7a7be8f 100644 --- a/extras/vpp_config/vpplib/AutoConfig.py +++ b/extras/vpp_config/vpplib/AutoConfig.py @@ -17,7 +17,7 @@ import logging import os import re import yaml -import ipaddress +from netaddr import IPAddress from vpplib.VPPUtil import VPPUtil from vpplib.VppPCIUtil import VppPCIUtil @@ -90,30 +90,25 @@ class AutoConfig(object): Asks the user for a number within a range. default is returned if return is entered. - :returns: IP address and prefix len - :rtype: tuple + :returns: IP address with cidr + :rtype: str """ while True: - answer = raw_input("Please enter the IPv4 Address [n.n.n.n]: ") + answer = raw_input("Please enter the IPv4 Address [n.n.n.n/n]: ") try: - ipaddr = ipaddress.ip_address(u'{}'.format(answer)) + ipinput = answer.split('/') + ipaddr = IPAddress(ipinput[0]) + if len(ipinput) > 1: + plen = answer.split('/')[1] + else: + answer = raw_input("Please enter the netmask [n.n.n.n]: ") + plen = IPAddress(answer).netmask_bits() + return '{}/{}'.format(ipaddr, plen) except: print "Please enter a valid IPv4 address." continue - answer = raw_input("Please enter the netmask [n.n.n.n]: ") - try: - netmask = ipaddress.ip_address(u'{}'.format(answer)) - pl = ipaddress.ip_network(u'0.0.0.0/{}'.format(netmask)) - plen = pl.exploded.split('/')[1] - break - except: - print "Please enter a valid IPv4 address and netmask." - continue - - return ipaddr, plen - @staticmethod def _ask_user_range(question, first, last, default): """ @@ -1479,14 +1474,13 @@ other than VPP? [0-{}][0]? '.format(str(max_other_cores)) if name == 'local0': continue - question = "Would you like an address to interface {} [Y/n]? ".format(name) + question = "Would you like add address to interface {} [Y/n]? ".format(name) answer = self._ask_user_yn(question, 'y') if answer == 'y': address = {} - addr, plen = self._ask_user_ipv4() + addr = self._ask_user_ipv4() address['name'] = name address['addr'] = addr - address['plen'] = plen interfaces_with_ip.append(address) return interfaces_with_ip @@ -1527,8 +1521,7 @@ other than VPP? [0-{}][0]? '.format(str(max_other_cores)) for ints in ints_with_addrs: name = ints['name'] addr = ints['addr'] - plen = ints['plen'] - setipstr = 'set int ip address {} {}/{}\n'.format(name, addr, plen) + setipstr = 'set int ip address {} {}\n'.format(name, addr) setintupstr = 'set int state {} up\n'.format(name) content += setipstr + setintupstr @@ -1546,4 +1539,118 @@ other than VPP? [0-{}][0]? '.format(str(max_other_cores)) print("\nA script as been created at {}".format(filename)) print("This script can be run using the following:") - print("vppctl exec {}\n".format(filename))
\ No newline at end of file + print("vppctl exec {}\n".format(filename)) + + def _create_vints_questions(self, node): + """ + Ask the user some questions and get a list of interfaces + and IPv4 addresses associated with those interfaces + + :param node: Node dictionary. + :type node: dict + :returns: A list or interfaces with ip addresses + :rtype: list + """ + + vpputl = VPPUtil() + interfaces = vpputl.get_hardware(node) + if interfaces == {}: + return [] + + # First delete all the Virtual interfaces + for intf in sorted(interfaces.items()): + name = intf[0] + if name[:7] == 'Virtual': + cmd = 'vppctl delete vhost-user {}'.format(name) + (ret, stdout, stderr) = vpputl.exec_command(cmd) + if ret != 0: + logging.debug('{} failed on node {} {}'.format( + cmd, node['host'], stderr)) + + # Create a virtual interface, for each interface the user wants to use + interfaces = vpputl.get_hardware(node) + if interfaces == {}: + return [] + interfaces_with_virtual_interfaces = [] + inum = 1 + for intf in sorted(interfaces.items()): + name = intf[0] + if name == 'local0': + continue + + question = "Would you like connect this interface {} to the VM [Y/n]? ".format(name) + answer = self._ask_user_yn(question, 'y') + if answer == 'y': + sockfilename = '/tmp/sock{}.sock'.format(inum) + if os.path.exists(sockfilename): + os.remove(sockfilename) + cmd = 'vppctl create vhost-user socket {} server'.format(sockfilename) + (ret, stdout, stderr) = vpputl.exec_command(cmd) + if ret != 0: + raise RuntimeError("Create vhost failed on node {} {}." + .format(node['host'], stderr)) + vintname = stdout.rstrip('\r\n') + + interface = {'name': name, 'virtualinterface': '{}'.format(vintname), + 'bridge': '{}'.format(inum)} + inum += 1 + interfaces_with_virtual_interfaces.append(interface) + + return interfaces_with_virtual_interfaces + + def create_and_bridge_virtual_interfaces(self): + """ + After asking the user some questions, create a VM and connect the interfaces + to VPP interfaces + + """ + + for i in self._nodes.items(): + node = i[1] + + # Show the current bridge and interface configuration + print "\nThis the current bridge configuration:" + VPPUtil.show_bridge(node) + question = "\nWould you like to keep this configuration [Y/n]? " + answer = self._ask_user_yn(question, 'y') + if answer == 'y': + continue + + # Create a script that builds a bridge configuration with physical interfaces + # and virtual interfaces + ints_with_vints = self._create_vints_questions(node) + content = '' + for intf in ints_with_vints: + vhoststr = 'comment { The following command creates the socket }\n' + vhoststr += 'comment { and returns a virtual interface }\n' + vhoststr += 'comment {{ create vhost-user socket /tmp/sock{}.sock server }}\n'. \ + format(intf['bridge']) + + setintdnstr = 'set interface state {} down\n'.format(intf['name']) + + setintbrstr = 'set interface l2 bridge {} {}\n'.format(intf['name'], intf['bridge']) + setvintbrstr = 'set interface l2 bridge {} {}\n'.format(intf['virtualinterface'], intf['bridge']) + + # set interface state VirtualEthernet/0/0/0 up + setintvststr = 'set interface state {} up\n'.format(intf['virtualinterface']) + + # set interface state VirtualEthernet/0/0/0 down + setintupstr = 'set interface state {} up\n'.format(intf['name']) + + content += vhoststr + setintdnstr + setintbrstr + setvintbrstr + setintvststr + setintupstr + + # Write the content to the script + rootdir = node['rootdir'] + filename = rootdir + '/vpp/vpp-config/scripts/create_vms_and_connect_to_vpp' + with open(filename, 'w+') as sfile: + sfile.write(content) + + # Execute the script + cmd = 'vppctl exec {}'.format(filename) + (ret, stdout, stderr) = VPPUtil.exec_command(cmd) + if ret != 0: + logging.debug(stderr) + + print("\nA script as been created at {}".format(filename)) + print("This script can be run using the following:") + print("vppctl exec {}\n".format(filename)) diff --git a/extras/vpp_config/vpplib/VPPUtil.py b/extras/vpp_config/vpplib/VPPUtil.py index f042e80bd8f..4551cf45a5e 100644 --- a/extras/vpp_config/vpplib/VPPUtil.py +++ b/extras/vpp_config/vpplib/VPPUtil.py @@ -140,8 +140,11 @@ class VPPUtil(object): stderr)) reps = 'deb [trusted=yes] https://nexus.fd.io/content/' - reps += 'repositories/fd.io.stable.{}.ubuntu.{}.main/ ./\n' \ - .format(fdio_release, ubuntu_version) + # When using a stable branch + # reps += 'repositories/fd.io.stable.{}.ubuntu.{}.main/ ./\n' \ + # .format(fdio_release, ubuntu_version) + reps += 'repositories/fd.io.ubuntu.{}.main/ ./\n' \ + .format(ubuntu_version) cmd = 'echo "{0}" | sudo tee {1}'.format(reps, sfile) (ret, stdout, stderr) = self.exec_command(cmd) @@ -201,8 +204,11 @@ class VPPUtil(object): reps = '[fdio-stable-{}]\n'.format(fdio_release) reps += 'name=fd.io stable/{} branch latest merge\n'.format(fdio_release) - reps += 'baseurl=https://nexus.fd.io/content/repositories/fd.io.stable.{}.{}/\n'.\ - format(fdio_release, centos_version) + # When using stable + # reps += 'baseurl=https://nexus.fd.io/content/repositories/fd.io.stable.{}.{}/\n'.\ + # format(fdio_release, centos_version) + reps += 'baseurl=https://nexus.fd.io/content/repositories/fd.io.{}/\n'.\ + format(centos_version) reps += 'enabled=1\n' reps += 'gpgcheck=0' @@ -336,6 +342,10 @@ class VPPUtil(object): :param node: Node dictionary with cpuinfo. :type node: dict """ + + # First stop VPP + self.stop(node) + distro = self.get_linux_distro() if distro[0] == 'Ubuntu': self._uninstall_vpp_ubuntu(node) @@ -373,6 +383,23 @@ class VPPUtil(object): self.exec_command('vppctl sh {}'.format(value)) @staticmethod + def get_vms(node): + """ + Get a list of VMs that are connected to VPP interfaces + + :param node: VPP node. + :type node: dict + :returns: Dictionary containing a list of VMs and the interfaces that are connected to VPP + :rtype: dictionary + """ + + vmdict = {} + + print "Need to implement get vms" + + return vmdict + + @staticmethod def get_int_ip(node): """ Get the VPP interfaces and IP addresses @@ -393,6 +420,7 @@ class VPPUtil(object): if lines[0].split(' ')[0] == 'FileNotFoundError': return interfaces + name = '' for line in lines: if len(line) is 0: continue @@ -583,6 +611,23 @@ class VPPUtil(object): return 0 @staticmethod + def restart(node): + """ + + Starts vpp for a given node + + :param node: VPP node. + :type node: dict + """ + + cmd = 'service vpp restart' + (ret, stdout, stderr) = VPPUtil.exec_command(cmd) + if ret != 0: + raise RuntimeError('{} failed on node {} {} {}'. + format(cmd, node['host'], + stdout, stderr)) + + @staticmethod def start(node): """ @@ -699,3 +744,40 @@ class VPPUtil(object): version[dct[0]] = dct[1].lstrip(' ') return version + + @staticmethod + def show_bridge(node): + """ + Shows the current bridge configuration + + :param node: VPP node. + :type node: dict + """ + + cmd = 'vppctl show bridge' + (ret, stdout, stderr) = VPPUtil.exec_command(cmd) + if ret != 0: + raise RuntimeError('{} failed on node {} {} {}'. + format(cmd, node['host'], + stdout, stderr)) + lines = stdout.split('\r\n') + bridges = [] + for line in lines: + if line == 'no bridge-domains in use': + print line + return + if len(line) == 0: + continue + + lspl = line.lstrip(' ').split() + if lspl[0] != 'BD-ID': + bridges.append(lspl[0]) + + for bridge in bridges: + cmd = 'vppctl show bridge {} detail'.format(bridge) + (ret, stdout, stderr) = VPPUtil.exec_command(cmd) + if ret != 0: + raise RuntimeError('{} failed on node {} {} {}'. + format(cmd, node['host'], + stdout, stderr)) + print stdout diff --git a/extras/vpp_config/vpplib/VppGrubUtil.py b/extras/vpp_config/vpplib/VppGrubUtil.py index 4aac427c22a..1723170649e 100644 --- a/extras/vpp_config/vpplib/VppGrubUtil.py +++ b/extras/vpp_config/vpplib/VppGrubUtil.py @@ -101,12 +101,13 @@ class VppGrubUtil(object): value = cmdline.split('{}='.format(grubcmdline))[1] value = value.rstrip('"').lstrip('"') - iommu = re.findall(r'iommu=\w+', value) - pstate = re.findall(r'intel_pstate=\w+', value) + # jadfix intel_pstate=disable sometimes cause networks to hang on reboot + # iommu = re.findall(r'iommu=\w+', value) + # pstate = re.findall(r'intel_pstate=\w+', value) # If there is already some iommu commands set, leave them, # if not use ours - if iommu == [] and pstate == []: - value = '{} intel_pstate=disable'.format(value) + # if iommu == [] and pstate == []: + # value = '{} intel_pstate=disable'.format(value) # Replace isolcpus with ours isolcpus = re.findall(r'isolcpus=[\w+\-,]+', value) diff --git a/extras/vpp_config/vpplib/VppPCIUtil.py b/extras/vpp_config/vpplib/VppPCIUtil.py index 829d66ae374..591dfab96cd 100644 --- a/extras/vpp_config/vpplib/VppPCIUtil.py +++ b/extras/vpp_config/vpplib/VppPCIUtil.py @@ -251,11 +251,12 @@ class VppPCIUtil(object): :param devices: A list of devices :param show_interfaces: show the kernel information + :param show_header: Display the header if true :type devices: dict :type show_interfaces: bool + :type show_header: bool """ - if show_interfaces: header = "{:15} {:25} {:50}".format("PCI ID", "Kernel Interface(s)", @@ -265,8 +266,7 @@ class VppPCIUtil(object): "Description") dashseparator = ("-" * (len(header) - 2)) - - if show_header == True: + if show_header is True: print header print dashseparator for dit in devices.items(): @@ -298,7 +298,6 @@ class VppPCIUtil(object): :type device_id: string """ - rootdir = node['rootdir'] dpdk_script = rootdir + DPDK_SCRIPT cmd = dpdk_script + ' -u ' + ' ' + device_id |