Merge "testpmd_pvp_fix: Fix SR-IOV QemuPciPassthrough mode to not use vdev"
[vswitchperf.git] / core / vnf_controller.py
index e973bc5..937cd5c 100644 (file)
@@ -15,6 +15,8 @@
 """
 
 import logging
+import pexpect
+from conf import settings
 from vnfs.vnf.vnf import IVnf
 
 class VnfController(object):
@@ -24,15 +26,19 @@ class VnfController(object):
 
     Attributes:
         _vnf_class: A class object representing the VNF to be used.
-        _deployment_scenario: A string describing the scenario to set-up in the
+        _deployment: A string describing the scenario to set-up in the
             constructor.
         _vnfs: A list of vnfs controlled by the controller.
     """
 
-    def __init__(self, deployment_scenario, vnf_class):
-        """Sets up the VNF infrastructure for the PVP deployment scenario.
+    def __init__(self, deployment, vnf_class, extra_vnfs):
+        """Sets up the VNF infrastructure based on deployment scenario
 
         :param vnf_class: The VNF class to be used.
+        :param extra_vnfs: The number of VNFs not involved in given
+            deployment scenario. It will be used to correctly expand
+            configuration values and initialize shared dirs. This parameter
+            is used in case, that additional VNFs are executed by TestSteps.
         """
         # reset VNF ID counter for each testcase
         IVnf.reset_vnf_counter()
@@ -40,17 +46,42 @@ class VnfController(object):
         # setup controller with requested number of VNFs
         self._logger = logging.getLogger(__name__)
         self._vnf_class = vnf_class
-        self._deployment_scenario = deployment_scenario.upper()
-        if self._deployment_scenario == 'P2P':
-            self._vnfs = []
-        elif self._deployment_scenario == 'PVP':
-            self._vnfs = [vnf_class()]
-        elif self._deployment_scenario == 'PVVP':
-            self._vnfs = [vnf_class(), vnf_class()]
-        elif self._deployment_scenario == 'OP2P':
-            self._vnfs = []
-        self._logger.debug('__init__ ' + str(len(self._vnfs)) +
-                           ' VNF[s] with ' + ' '.join(map(str, self._vnfs)))
+        self._deployment = deployment.lower()
+        self._vnfs = []
+        if self._deployment == 'pvp':
+            vm_number = 1
+        elif (self._deployment.startswith('pvvp') or
+              self._deployment.startswith('pvpv')):
+            if len(self._deployment) > 4:
+                vm_number = int(self._deployment[4:])
+            else:
+                vm_number = 2
+        else:
+            # VnfController is created for all deployments, including deployments
+            # without VNFs like p2p
+            vm_number = 0
+
+        if vm_number + extra_vnfs > 0:
+            self._logger.debug('Check configuration for %s guests.', vm_number + extra_vnfs)
+            settings.check_vm_settings(vm_number + extra_vnfs)
+            # enforce that GUEST_NIC_NR is 1 or even number of NICs
+            updated = False
+            nics_nr = settings.getValue('GUEST_NICS_NR')
+            for index in range(len(nics_nr)):
+                if nics_nr[index] > 1 and nics_nr[index] % 2:
+                    updated = True
+                    nics_nr[index] = int(nics_nr[index] / 2) * 2
+            if updated:
+                settings.setValue('GUEST_NICS_NR', nics_nr)
+                self._logger.warning('Odd number of NICs was detected. Configuration '
+                                     'was updated to GUEST_NICS_NR = %s',
+                                     settings.getValue('GUEST_NICS_NR'))
+
+        if vm_number:
+            self._vnfs = [vnf_class() for _ in range(vm_number)]
+
+            self._logger.debug('__init__ ' + str(len(self._vnfs)) +
+                               ' VNF[s] with ' + ' '.join(map(str, self._vnfs)))
 
     def get_vnfs(self):
         """Returns a list of vnfs controlled by this controller.
@@ -59,6 +90,13 @@ class VnfController(object):
                            ' VNF[s] with ' + ' '.join(map(str, self._vnfs)))
         return self._vnfs
 
+    def get_vnfs_number(self):
+        """Returns a number of vnfs controlled by this controller.
+        """
+        self._logger.debug('get_vnfs_number ' + str(len(self._vnfs)) +
+                           ' VNF[s]')
+        return len(self._vnfs)
+
     def start(self):
         """Boots all VNFs set-up by __init__.
 
@@ -66,8 +104,12 @@ class VnfController(object):
         """
         self._logger.debug('start ' + str(len(self._vnfs)) +
                            ' VNF[s] with ' + ' '.join(map(str, self._vnfs)))
-        for vnf in self._vnfs:
-            vnf.start()
+        try:
+            for vnf in self._vnfs:
+                vnf.start()
+        except pexpect.TIMEOUT:
+            self.stop()
+            raise
 
     def stop(self):
         """Stops all VNFs set-up by __init__.