Add send socket commands function 93/57593/7
authorRodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com>
Sat, 19 May 2018 18:31:37 +0000 (19:31 +0100)
committerRodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com>
Thu, 14 Jun 2018 07:16:06 +0000 (07:16 +0000)
Pktgen provides a TCP socket connection to allow the user to control
it from a remote console or program [1].

This new method will provide Yardstick the ability to send string
commands to a port in a remote host.

[1] http://pktgen-dpdk.readthedocs.io/en/latest/socket.html

JIRA: YARDSTICK-1186

Change-Id: I9d64ccad662fa3599de65654c5dab02833fcc91d
Signed-off-by: Rodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com>
yardstick/common/utils.py
yardstick/tests/functional/common/test_utils.py
yardstick/tests/unit/common/test_utils.py

index 108ee17..958ec62 100644 (file)
@@ -492,3 +492,25 @@ def wait_until_true(predicate, timeout=60, sleep=1, exception=None):
         if exception and issubclass(exception, Exception):
             raise exception  # pylint: disable=raising-bad-type
         raise exceptions.WaitTimeout
+
+
+def send_socket_command(host, port, command):
+    """Send a string command to a specific port in a host
+
+    :param host: (str) ip or hostname of the host
+    :param port: (int) port number
+    :param command: (str) command to send
+    :return: 0 if success, error number if error
+    """
+    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    ret = 0
+    try:
+        err_number = sock.connect_ex((host, int(port)))
+        if err_number != 0:
+            return err_number
+        sock.sendall(six.b(command))
+    except Exception:  # pylint: disable=broad-except
+        ret = 1
+    finally:
+        sock.close()
+    return ret
index b5333bb..b9f1f77 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import multiprocessing
 import unittest
+import socket
 import sys
+import time
 
 from yardstick.common import utils
 
@@ -32,3 +35,38 @@ class ImportModulesFromPackageTestCase(unittest.TestCase):
         library_obj = getattr(module_obj, library_name)
         class_obj = getattr(library_obj, class_name)
         self.assertEqual(class_name, class_obj().__class__.__name__)
+
+
+class SendSocketCommandTestCase(unittest.TestCase):
+
+    @staticmethod
+    def _run_socket_server(port):
+        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        sock.bind(('localhost', port))
+        sock.listen(1)
+        conn = None
+        while not conn:
+            conn, _ = sock.accept()
+        sock.close()
+
+    @staticmethod
+    def _terminate_server(socket_server):
+        # Wait until the socket server closes the open port.
+        time.sleep(1)
+        if socket_server and socket_server.is_alive():
+            socket_server.terminate()
+
+    def test_send_command(self):
+        port = 47001
+
+        socket_server = multiprocessing.Process(
+            name='run_socket_server',
+            target=SendSocketCommandTestCase._run_socket_server,
+            args=(port, )).start()
+
+        self.addCleanup(self._terminate_server, socket_server)
+
+        # Wait until the socket is open.
+        time.sleep(0.5)
+        self.assertEqual(
+            0, utils.send_socket_command('localhost', port, 'test_command'))
index 5fd91c8..10ad0a6 100644 (file)
@@ -16,6 +16,7 @@ import mock
 import os
 import six
 from six.moves import configparser
+import socket
 import time
 import unittest
 
@@ -1194,3 +1195,29 @@ class WaitUntilTrueTestCase(unittest.TestCase):
             self.assertIsNone(
                 utils.wait_until_true(lambda: False, timeout=1, sleep=1,
                                       exception=MyTimeoutException))
+
+
+class SendSocketCommandTestCase(unittest.TestCase):
+
+    @mock.patch.object(socket, 'socket')
+    def test_execute_correct(self, mock_socket):
+        mock_socket_obj = mock.Mock()
+        mock_socket_obj.connect_ex.return_value = 0
+        mock_socket.return_value = mock_socket_obj
+        self.assertEqual(0, utils.send_socket_command('host', 22, 'command'))
+        mock_socket.assert_called_once_with(socket.AF_INET, socket.SOCK_STREAM)
+        mock_socket_obj.connect_ex.assert_called_once_with(('host', 22))
+        mock_socket_obj.sendall.assert_called_once_with(six.b('command'))
+        mock_socket_obj.close.assert_called_once()
+
+    @mock.patch.object(socket, 'socket')
+    def test_execute_exception(self, mock_socket):
+        mock_socket_obj = mock.Mock()
+        mock_socket_obj.connect_ex.return_value = 0
+        mock_socket.return_value = mock_socket_obj
+        mock_socket_obj.sendall.side_effect = socket.error
+        self.assertEqual(1, utils.send_socket_command('host', 22, 'command'))
+        mock_socket.assert_called_once_with(socket.AF_INET, socket.SOCK_STREAM)
+        mock_socket_obj.connect_ex.assert_called_once_with(('host', 22))
+        mock_socket_obj.sendall.assert_called_once_with(six.b('command'))
+        mock_socket_obj.close.assert_called_once()