aboutsummaryrefslogtreecommitdiffstats
path: root/extras/vpp_config/vpplib
diff options
context:
space:
mode:
authorJohn DeNisco <jdenisco@cisco.com>2018-02-06 15:23:05 -0500
committerDamjan Marion <dmarion.lists@gmail.com>2018-02-16 08:09:27 +0000
commit9fa5cf46690601e4e25605d548671c84634363e3 (patch)
tree83f5066290114e58341b93ca614c7e22b610f063 /extras/vpp_config/vpplib
parent56a0d06cb410b669eddf1533f22ec3afedb4b242 (diff)
Add iperf VM/vhost creation
Change-Id: I27a59203f406120558f73bfcc12dca8835ae6361 Signed-off-by: John DeNisco <jdenisco@cisco.com>
Diffstat (limited to 'extras/vpp_config/vpplib')
-rw-r--r--extras/vpp_config/vpplib/AutoConfig.py200
-rw-r--r--extras/vpp_config/vpplib/VPPUtil.py15
2 files changed, 209 insertions, 6 deletions
diff --git a/extras/vpp_config/vpplib/AutoConfig.py b/extras/vpp_config/vpplib/AutoConfig.py
index 26603e8e380..f435d18b9e7 100644
--- a/extras/vpp_config/vpplib/AutoConfig.py
+++ b/extras/vpp_config/vpplib/AutoConfig.py
@@ -33,6 +33,10 @@ MIN_SYSTEM_CPUS = 2
MIN_TOTAL_HUGE_PAGES = 1024
MAX_PERCENT_FOR_HUGE_PAGES = 70
+IPERFVM_XML = 'configs/iperf-vm.xml'
+IPERFVM_IMAGE = 'images/xenial-mod.img'
+IPERFVM_ISO = 'configs/cloud-config.iso'
+
class AutoConfig(object):
"""Auto Configuration Tools"""
@@ -56,6 +60,7 @@ class AutoConfig(object):
self._hugepage_config = ""
self._clean = clean
self._loadconfig()
+ self._sockfilename = ""
def get_nodes(self):
"""
@@ -551,7 +556,9 @@ class AutoConfig(object):
# If total_vpp_cpus is 0 or is less than the numa nodes with ports
# then we shouldn't get workers
- total_workers_node = total_vpp_cpus / len(ports_per_numa)
+ total_workers_node = 0
+ if len(ports_per_numa):
+ total_workers_node = total_vpp_cpus / len(ports_per_numa)
total_main = 0
if reserve_vpp_main_core:
total_main = 1
@@ -1637,16 +1644,20 @@ class AutoConfig(object):
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 = '/var/run/vpp/sock{}.sock'.format(inum)
+ sockfilename = '/var/run/vpp/{}.sock'.format(name.replace('/', '_'))
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))
+ raise RuntimeError("Couldn't execute the command {}, {}.".format(cmd, stderr))
vintname = stdout.rstrip('\r\n')
+ cmd = 'chmod 777 {}'.format(sockfilename)
+ (ret, stdout, stderr) = vpputl.exec_command(cmd)
+ if ret != 0:
+ raise RuntimeError("Couldn't execute the command {}, {}.".format(cmd, stderr))
+
interface = {'name': name, 'virtualinterface': '{}'.format(vintname),
'bridge': '{}'.format(inum)}
inum += 1
@@ -1710,3 +1721,184 @@ class AutoConfig(object):
print("\nA script as been created at {}".format(filename))
print("This script can be run using the following:")
print("vppctl exec {}\n".format(filename))
+
+ def _iperf_vm_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
+
+ while True:
+ print '\nPlease pick one interface to connect to the iperf VM.'
+ 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, 'n')
+ if answer == 'y':
+ self._sockfilename = '/var/run/vpp/{}.sock'.format(name.replace('/', '_'))
+ if os.path.exists(self._sockfilename):
+ os.remove(self._sockfilename)
+ cmd = 'vppctl create vhost-user socket {} server'.format(self._sockfilename)
+ (ret, stdout, stderr) = vpputl.exec_command(cmd)
+ if ret != 0:
+ raise RuntimeError("Couldn't execute the command {}, {}.".format(cmd, stderr))
+ vintname = stdout.rstrip('\r\n')
+
+ cmd = 'chmod 777 {}'.format(self._sockfilename)
+ (ret, stdout, stderr) = vpputl.exec_command(cmd)
+ if ret != 0:
+ raise RuntimeError("Couldn't execute the command {}, {}.".format(cmd, stderr))
+
+ 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_iperf_virtual_interface(self):
+ """
+ After asking the user some questions, and create and bridge a virtual interface
+ to be used with iperf VM
+
+ """
+
+ for i in self._nodes.items():
+ node = i[1]
+
+ # Show the current bridge and interface configuration
+ print "\nThis the current bridge configuration:"
+ ifaces = VPPUtil.show_bridge(node)
+ question = "\nWould you like to keep this configuration [Y/n]? "
+ answer = self._ask_user_yn(question, 'y')
+ if answer == 'y':
+ self._sockfilename = '/var/run/vpp/{}.sock'.format(ifaces[0]['name'].replace('/', '_'))
+ if os.path.exists(self._sockfilename):
+ continue
+
+ # Create a script that builds a bridge configuration with physical interfaces
+ # and virtual interfaces
+ ints_with_vints = self._iperf_vm_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 /var/run/vpp/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_iperf_vm'
+ 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))
+
+ @staticmethod
+ def destroy_iperf_vm(name):
+ """
+ After asking the user some questions, create a VM and connect the interfaces
+ to VPP interfaces
+
+ :param name: The name of the VM to be be destroyed
+ :type name: str
+ """
+
+ cmd = 'virsh list'
+ (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
+ if ret != 0:
+ logging.debug(stderr)
+ raise RuntimeError("Couldn't execute the command {} : {}".format(cmd, stderr))
+
+ if re.findall(name, stdout):
+ cmd = 'virsh destroy {}'.format(name)
+ (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
+ if ret != 0:
+ logging.debug(stderr)
+ raise RuntimeError("Couldn't execute the command {} : {}".format(cmd, stderr))
+
+ def create_iperf_vm(self, vmname):
+ """
+ After asking the user some questions, create a VM and connect the interfaces
+ to VPP interfaces
+
+ """
+
+ # Read the iperf VM template file
+ distro = VPPUtil.get_linux_distro()
+ if distro[0] == 'Ubuntu':
+ tfilename = '{}/vpp/vpp-config/configs/iperf-ubuntu.xml.template'.format(self._rootdir)
+ else:
+ tfilename = '{}/vpp/vpp-config/configs/iperf-centos.xml.template'.format(self._rootdir)
+
+ with open(tfilename, 'r') as tfile:
+ tcontents = tfile.read()
+ tfile.close()
+
+ # Add the variables
+ imagename = '{}/vpp/vpp-config/{}'.format(self._rootdir, IPERFVM_IMAGE)
+ isoname = '{}/vpp/vpp-config/{}'.format(self._rootdir, IPERFVM_ISO)
+ tcontents = tcontents.format(vmname=vmname, imagename=imagename, isoname=isoname,
+ vhostsocketname=self._sockfilename)
+
+ # Write the xml
+ ifilename = '{}/vpp/vpp-config/{}'.format(self._rootdir, IPERFVM_XML)
+ with open(ifilename, 'w+') as ifile:
+ ifile.write(tcontents)
+ ifile.close()
+
+ cmd = 'virsh create {}'.format(ifilename)
+ (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
+ if ret != 0:
+ logging.debug(stderr)
+ raise RuntimeError("Couldn't execute the command {} : {}".format(cmd, stderr))
diff --git a/extras/vpp_config/vpplib/VPPUtil.py b/extras/vpp_config/vpplib/VPPUtil.py
index 4ea94135b49..07d65b0d538 100644
--- a/extras/vpp_config/vpplib/VPPUtil.py
+++ b/extras/vpp_config/vpplib/VPPUtil.py
@@ -753,8 +753,10 @@ class VPPUtil(object):
:param node: VPP node.
:type node: dict
+ :returns: A list of interfaces
"""
+ ifaces = []
cmd = 'vppctl show bridge'
(ret, stdout, stderr) = VPPUtil.exec_command(cmd)
if ret != 0:
@@ -766,7 +768,7 @@ class VPPUtil(object):
for line in lines:
if line == 'no bridge-domains in use':
print line
- return
+ return ifaces
if len(line) == 0:
continue
@@ -781,4 +783,13 @@ class VPPUtil(object):
raise RuntimeError('{} failed on node {} {} {}'.
format(cmd, node['host'],
stdout, stderr))
- print stdout
+
+ lines = stdout.split('\r\n')
+ for line in lines:
+ iface = re.findall(r'[a-zA-z]+\d+/\d+/\d+', line)
+ if len(iface):
+ ifcidx ={'name': iface[0], 'index': line.split()[1] }
+ ifaces.append(ifcidx)
+
+ print stdout
+ return ifaces \ No newline at end of file