Merge "Tools: Improve Stability."
[vswitchperf.git] / vnfs / vnf / vnf.py
index c746aa8..3ad1dcd 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2015 Intel Corporation.
+# Copyright 2015-2017 Intel Corporation.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 Interface for VNF.
 """
 
+import time
+import pexpect
+from tools import tasks
 
-class IVnf(object):
+class IVnf(tasks.Process):
 
     """
     Interface for VNF.
     """
 
-    def __init__(self, memory, cpus,
-                 monitor_path, shared_path_host,
-                 shared_path_guest, guest_prompt):
+    _number_vnfs = 0
+
+    def __init__(self):
         """
         Initialization method.
 
         Purpose of this method is to initialize all
         common Vnf data, no services should be started by
         this call (use ``start`` method instead).
-
-        :param memory:   Virtual RAM size in megabytes.
-        :param cpus:     Number of Processors.
-        :param monitor_path: Configure monitor to given path.
-        :param shared_path_host: HOST path to shared location.
-        :param shared_path_guest: GUEST path to shared location.
-        :param guest_prompt: preconfigured command prompt which is used
-                           in execute_and_wait & wait methods
-                           to detect if particular call is finished.
         """
-        raise NotImplementedError()
+        self._number = IVnf._number_vnfs
+        self._logger.debug('Initializing %s. VM with index %s',
+                           self._number + 1, self._number)
+        IVnf._number_vnfs = IVnf._number_vnfs + 1
+        self._log_prefix = 'vnf_%d_cmd : ' % self._number
+        self._login_active = False
 
-    def start(self):
+    def stop(self):
         """
-        Starts VNF instance.
+        Stops VNF instance.
         """
-        raise NotImplementedError()
+        if self.is_running():
+            self._logger.info('Killing VNF...')
 
-    def stop(self):
+            # force termination of VNF and wait for it to terminate; It will avoid
+            # sporadic reboot of host. (caused by hugepages or DPDK ports)
+            super(IVnf, self).kill(signal='-9', sleep=10)
+
+    def login(self, dummy_timeout=120):
         """
-        Stops VNF instance.
+        Login to GUEST instance.
+
+        This can be used after booting the machine
+
+        :param timeout: Timeout to wait for login to complete.
+
+        :returns: True if login is active
         """
         raise NotImplementedError()
 
-    def execute(self, command, delay=30):
+    def execute(self, cmd, delay=0):
         """
-        execute ``command`` with given ``delay``.
+        execute ``cmd`` with given ``delay``.
 
         This method makes asynchronous call to guest system
         and waits given ``delay`` before returning. Can be
         used with ``wait`` method to create synchronous call.
 
-        :param command: Command to execute on guest system.
+        :param cmd: Command to execute on guest system.
         :param delay: Delay (in seconds) to wait after sending
                       command before returning. Please note that
                       this value can be floating point which
@@ -72,48 +82,92 @@ class IVnf(object):
 
         :returns: None.
         """
-        raise NotImplementedError()
+        self._logger.debug('%s%s', self._log_prefix, cmd)
+
+        # ensure that output from previous commands is flushed
+        try:
+            while not self._child.expect(r'.+', timeout=0.1):
+                pass
+        except (pexpect.TIMEOUT, pexpect.EOF):
+            pass
+
+        self._child.sendline(cmd)
+        time.sleep(delay)
 
-    def wait(self, guest_prompt, timeout=30):
+    def wait(self, prompt='', timeout=30):
         """
-        wait for ``guest_prompt`` on guest system for given ``timeout``.
+        wait for ``prompt`` on guest system for given ``timeout``.
 
         This method ends based on two conditions:
-        * ``guest_prompt`` has been detected
+        * ``prompt`` has been detected
         * ``timeout`` has been reached.
 
-        :param guest_prompt: method end condition. If ``guest_prompt``
+        :param prompt: method end condition. If ``prompt``
                              won't be detected during given timeout,
                              method will return False.
         :param timeout: Time to wait for prompt (in seconds).
                         Please note that this value can be floating
                         point which allows to pass milliseconds.
 
-        :returns: True if result_cmd has been detected before
-                  timeout has been reached, False otherwise.
+        :returns: output of executed command
         """
-        raise NotImplementedError()
+        self._child.expect(prompt, timeout=timeout)
+        return self._child.before
 
-    def execute_and_wait(self, command, timeout=30, guest_prompt=None):
+    def execute_and_wait(self, cmd, timeout=30, prompt=''):
         """
-        execute ``command`` with given ``timeout``.
+        execute ``cmd`` with given ``timeout``.
 
         This method makes synchronous call to guest system
-        and waits till ``command`` execution is finished
-        (based on ``guest_prompt value) or ''timeout'' has
+        and waits till ``cmd`` execution is finished
+        (based on ``prompt value) or ''timeout'' has
         been reached.
 
-        :param command: Command to execute on guest system.
+        :param cmd: Command to execute on guest system.
         :param timeout: Timeout till the end of execution is not
                         detected.
-        :param guest_prompt: method end condition. If ``guest_prompt``
+        :param prompt: method end condition. If ``prompt``
                              won't be detected during given timeout,
                              method will return False. If no argument
                              or None value will be passed, default
-                             ``guest_prompt`` passed in __init__
+                             ``prompt`` passed in __init__
                              method will be used.
 
-        :returns: True if end of execution has been detected
-                  before timeout has been reached, False otherwise.
+        :returns: output of executed command
         """
-        raise NotImplementedError()
+        self.execute(cmd)
+        return self.wait(prompt=prompt, timeout=timeout)
+
+    def validate_start(self, _dummyresult):
+        """ Validate call of VNF start()
+        """
+        if self._child and self._child.isalive():
+            return True
+
+        return False
+
+    def validate_stop(self, result):
+        """ Validate call of VNF stop()
+        """
+        return not self.validate_start(result)
+
+    @staticmethod
+    def validate_execute_and_wait(result, _dummy_cmd, _dummy_timeout=30, _dummy_prompt=''):
+        """ Validate command execution within VNF
+        """
+        return len(result) > 0
+
+    @staticmethod
+    def validate_login(result):
+        """ Validate successful login into guest
+        """
+        return result
+
+    @staticmethod
+    def reset_vnf_counter():
+        """
+        Reset internal VNF counters
+
+        This method is static
+        """
+        IVnf._number_vnfs = 0