Fix inspection for 18.10, requirements
[vpp.git] / extras / vpp_config / vpplib / AutoConfig.py
index 26603e8..2664a6a 100644 (file)
@@ -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
@@ -622,14 +629,14 @@ class AutoConfig(object):
             tcp = tcp + "  v4-halfopen-table-buckets " + \
                   "{:d}".format((aos + pos) / 4) + "\n"
             tcp = tcp + "  v4-halfopen-table-memory 3g\n"
+            tcp = tcp + "  local-endpoints-table-buckets " + "{:d}".format((aos + pos) / 4) + "\n"
+            tcp = tcp + "  local-endpoints-table-memory 3g\n"
         tcp = tcp + "}\n\n"
 
         tcp = tcp + "tcp {\n"
         tcp = tcp + "  preallocated-connections " + "{:d}".format(aos + pos) + "\n"
         if aos > 0:
             tcp = tcp + "  preallocated-half-open-connections " + "{:d}".format(aos) + "\n"
-            tcp = tcp + "  local-endpoints-table-buckets " + "{:d}".format((aos + pos) / 4) + "\n"
-            tcp = tcp + "  local-endpoints-table-memory 3g\n"
         tcp = tcp + "}\n\n"
 
         return tcp.rstrip('\n')
@@ -1041,10 +1048,11 @@ class AutoConfig(object):
                     if answer == 'y':
                         if 'unused' in device and len(device['unused']) != 0 and device['unused'][0] != '':
                             driver = device['unused'][0]
-                            VppPCIUtil.bind_vpp_device(node, driver, dvid)
-                        else:
-                            logging.debug('Could not bind device {}'.format(dvid))
-                        vppd[dvid] = device
+                            ret = VppPCIUtil.bind_vpp_device(node, driver, dvid)
+                            if ret:
+                                logging.debug('Could not bind device {}'.format(dvid))
+                            else:
+                                vppd[dvid] = device
                 for dit in vppd.items():
                     dvid = dit[0]
                     device = dit[1]
@@ -1074,11 +1082,12 @@ class AutoConfig(object):
                     if 'unused' in device and len(device['unused']) != 0 and device['unused'][0] != '':
                         driver = device['unused'][0]
                         logging.debug('Binding device {} to driver {}'.format(dvid, driver))
-                        VppPCIUtil.bind_vpp_device(node, driver, dvid)
-                    else:
-                        logging.debug('Could not bind device {}'.format(dvid))
-                    dpdk_devices[dvid] = device
-                    del other_devices[dvid]
+                        ret = VppPCIUtil.bind_vpp_device(node, driver, dvid)
+                        if ret:
+                            logging.debug('Could not bind device {}'.format(dvid))
+                        else:
+                            dpdk_devices[dvid] = device
+                            del other_devices[dvid]
 
     def update_interfaces_config(self):
         """
@@ -1155,11 +1164,12 @@ class AutoConfig(object):
                         if 'unused' in device and len(device['unused']) != 0 and device['unused'][0] != '':
                             driver = device['unused'][0]
                             logging.debug('Binding device {} to driver {}'.format(dvid, driver))
-                            VppPCIUtil.bind_vpp_device(node, driver, dvid)
-                        else:
-                            logging.debug('Could not bind device {}'.format(dvid))
-                        dpdk_devices[dvid] = device
-                        del kernel_devices[dvid]
+                            ret = VppPCIUtil.bind_vpp_device(node, driver, dvid)
+                            if ret:
+                                logging.debug('Could not bind device {}'.format(dvid))
+                            else:
+                                dpdk_devices[dvid] = device
+                                del kernel_devices[dvid]
 
             dlen = len(dpdk_devices)
             if dlen > 0:
@@ -1184,11 +1194,12 @@ class AutoConfig(object):
                         if 'unused' in device and len(device['unused']) != 0 and device['unused'][0] != '':
                             driver = device['unused'][0]
                             logging.debug('Binding device {} to driver {}'.format(dvid, driver))
-                            VppPCIUtil.bind_vpp_device(node, driver, dvid)
-                        else:
-                            logging.debug('Could not bind device {}'.format(dvid))
-                        kernel_devices[dvid] = device
-                        del dpdk_devices[dvid]
+                            ret = VppPCIUtil.bind_vpp_device(node, driver, dvid)
+                            if ret:
+                                logging.debug('Could not bind device {}'.format(dvid))
+                            else:
+                                kernel_devices[dvid] = device
+                                del dpdk_devices[dvid]
 
             interfaces = {}
             for dit in dpdk_devices.items():
@@ -1379,6 +1390,14 @@ class AutoConfig(object):
         else:
             print ("\nNo devices bound to DPDK drivers")
 
+        other_devs = vpp.get_other_devices()
+        if len(other_devs):
+            print ("\nDevices not bound to Kernel or DPDK drivers:")
+            vpp.show_vpp_devices(other_devs, show_interfaces=True,
+                                 show_header=False)
+        else:
+            print ("\nNo devices not bound to Kernel or DPDK drivers")
+
         vpputl = VPPUtil()
         interfaces = vpputl.get_hardware(node)
         if interfaces == {}:
@@ -1390,17 +1409,17 @@ class AutoConfig(object):
             print ("None")
             return
 
-        print "{:30} {:6} {:4} {:7} {:4} {:7}". \
-            format('Name', 'Socket', 'RXQs',
+        print "{:30} {:4} {:4} {:7} {:4} {:7}". \
+            format('Name', 'Numa', 'RXQs',
                    'RXDescs', 'TXQs', 'TXDescs')
         for intf in sorted(interfaces.items()):
             name = intf[0]
             value = intf[1]
             if name == 'local0':
                 continue
-            socket = rx_qs = rx_ds = tx_qs = tx_ds = ''
-            if 'cpu socket' in value:
-                socket = int(value['cpu socket'])
+            numa = rx_qs = rx_ds = tx_qs = tx_ds = ''
+            if 'numa' in value:
+                numa = int(value['numa'])
             if 'rx queues' in value:
                 rx_qs = int(value['rx queues'])
             if 'rx descs' in value:
@@ -1410,8 +1429,8 @@ class AutoConfig(object):
             if 'tx descs' in value:
                 tx_ds = int(value['tx descs'])
 
-            print ("{:30} {:>6} {:>4} {:>7} {:>4} {:>7}".
-                   format(name, socket, rx_qs, rx_ds, tx_qs, tx_ds))
+            print ("{:30} {:>4} {:>4} {:>7} {:>4} {:>7}".
+                   format(name, numa, rx_qs, rx_ds, tx_qs, tx_ds))
 
     @staticmethod
     def hugepage_info(node):
@@ -1637,16 +1656,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 +1733,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))