Add OVS logger 19/23519/1
authorGeorge Paraskevopoulos <geopar@intracom-telecom.com>
Fri, 21 Oct 2016 11:39:35 +0000 (14:39 +0300)
committerJose Lausuch <jose.lausuch@ericsson.com>
Fri, 21 Oct 2016 15:01:03 +0000 (15:01 +0000)
Add utility class to log OVS flows from a remote server.

Change-Id: I80cb5b20dc15477771beb912f44cab28c7397e24
Signed-off-by: George Paraskevopoulos <geopar@intracom-telecom.com>
(cherry picked from commit b2b00380b8d77b0037c9ef809d2538bb4e9428aa)

testcases/features/sfc/SSHUtils.py [new file with mode: 0644]
testcases/features/sfc/ovs_utils.py [new file with mode: 0644]
testcases/features/sfc/sfc.py
testcases/features/sfc/sfc_colorado1.py

diff --git a/testcases/features/sfc/SSHUtils.py b/testcases/features/sfc/SSHUtils.py
new file mode 100644 (file)
index 0000000..55cc510
--- /dev/null
@@ -0,0 +1,120 @@
+##############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# Authors: George Paraskevopoulos (geopar@intracom-telecom.com)
+#          Jose Lausuch (jose.lausuch@ericsson.com)
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+
+import paramiko
+import functest.utils.functest_logger as rl
+import os
+
+logger = rl.Logger('SSHUtils').getLogger()
+
+
+def get_ssh_client(hostname, username, password=None, jumphost=None):
+    client = None
+    try:
+        if jumphost is None:
+            client = paramiko.SSHClient()
+        else:
+            client = JumpHostHopClient()
+            client.configure_jump_host(jumphost['ip'],
+                                       jumphost['username'],
+                                       jumphost['password'])
+
+        if client is None:
+            raise Exception('Could not connect to client')
+
+        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+        client.connect(hostname,
+                       username=username,
+                       password=password)
+        return client
+    except Exception, e:
+        logger.error(e)
+        return None
+
+
+def get_file(ssh_conn, src, dest):
+    try:
+        sftp = ssh_conn.open_sftp()
+        sftp.get(src, dest)
+        return True
+    except Exception, e:
+        logger.error("Error [get_file(ssh_conn, '%s', '%s']: %s" %
+                     (src, dest, e))
+        return None
+
+
+def put_file(ssh_conn, src, dest):
+    try:
+        sftp = ssh_conn.open_sftp()
+        sftp.put(src, dest)
+        return True
+    except Exception, e:
+        logger.error("Error [put_file(ssh_conn, '%s', '%s']: %s" %
+                     (src, dest, e))
+        return None
+
+
+class JumpHostHopClient(paramiko.SSHClient):
+    '''
+    Connect to a remote server using a jumphost hop
+    '''
+    def __init__(self, *args, **kwargs):
+        self.logger = rl.Logger("JumpHostHopClient").getLogger()
+        self.jumphost_ssh = None
+        self.jumphost_transport = None
+        self.jumphost_channel = None
+        self.jumphost_ip = None
+        self.jumphost_ssh_key = None
+        self.local_ssh_key = os.path.join(os.getcwd(), 'id_rsa')
+        super(JumpHostHopClient, self).__init__(*args, **kwargs)
+
+    def configure_jump_host(self, jh_ip, jh_user, jh_pass,
+                            jh_ssh_key='/root/.ssh/id_rsa'):
+        self.jumphost_ip = jh_ip
+        self.jumphost_ssh_key = jh_ssh_key
+        self.jumphost_ssh = paramiko.SSHClient()
+        self.jumphost_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+        self.jumphost_ssh.connect(jh_ip,
+                                  username=jh_user,
+                                  password=jh_pass)
+        self.jumphost_transport = self.jumphost_ssh.get_transport()
+
+    def connect(self, hostname, port=22, username='root', password=None,
+                pkey=None, key_filename=None, timeout=None, allow_agent=True,
+                look_for_keys=True, compress=False, sock=None, gss_auth=False,
+                gss_kex=False, gss_deleg_creds=True, gss_host=None,
+                banner_timeout=None):
+        try:
+            if self.jumphost_ssh is None:
+                raise Exception('You must configure the jump '
+                                'host before calling connect')
+
+            get_file_res = get_file(self.jumphost_ssh,
+                                    self.jumphost_ssh_key,
+                                    self.local_ssh_key)
+            if get_file_res is None:
+                raise Exception('Could\'t fetch SSH key from jump host')
+            jumphost_key = (paramiko.RSAKey
+                            .from_private_key_file(self.local_ssh_key))
+
+            self.jumphost_channel = self.jumphost_transport.open_channel(
+                "direct-tcpip",
+                (hostname, 22),
+                (self.jumphost_ip, 22))
+
+            self.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+            super(JumpHostHopClient, self).connect(hostname,
+                                                   username=username,
+                                                   pkey=jumphost_key,
+                                                   sock=self.jumphost_channel)
+            os.remove(self.local_ssh_key)
+        except Exception, e:
+            self.logger.error(e)
diff --git a/testcases/features/sfc/ovs_utils.py b/testcases/features/sfc/ovs_utils.py
new file mode 100644 (file)
index 0000000..83a3628
--- /dev/null
@@ -0,0 +1,80 @@
+##############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# Author: George Paraskevopoulos (geopar@intracom-telecom.com)
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+import functest.utils.functest_logger as rl
+import os
+import time
+
+logger = rl.Logger('ovs_utils').getLogger()
+
+
+class OVSLogger(object):
+    def __init__(self, basedir):
+        self.ovs_dir = os.path.join(basedir, 'odl-sfc/ovs')
+        self.__mkdir_p(self.ovs_dir)
+
+    def __mkdir_p(self, dirpath):
+        if not os.path.exists(dirpath):
+            os.makedirs(dirpath)
+
+    def __ssh_host(self, ssh_conn):
+        return ssh_conn.get_transport().getpeername()[0]
+
+    def __dump_to_file(self, operation, host, text, timestamp=None):
+        ts = (timestamp if timestamp is not None
+              else time.strftime("%Y%m%d-%H%M%S"))
+        dumpdir = os.path.join(self.ovs_dir, ts)
+        self.__mkdir_p(dumpdir)
+        fname = '{0}_{1}'.format(operation, host)
+        with open(os.path.join(dumpdir, fname), 'w') as f:
+            f.write(text)
+
+    def __remote_cmd(self, ssh_conn, cmd):
+        try:
+            _, stdout, stderr = ssh_conn.exec_command(cmd)
+            errors = stderr.readlines()
+            if len(errors) > 0:
+                host = self.__ssh_host(ssh_conn)
+                logger.error(''.join(errors))
+                raise Exception('Could not execute {0} in {1}'
+                                .format(cmd, host))
+            output = ''.join(stdout.readlines())
+            return output
+        except Exception, e:
+            logger.error('[__remote_command(ssh_client, {0})]: {1}'
+                         .format(cmd, e))
+            return None
+
+    def ofctl_dump_flows(self, ssh_conn, br='br-int',
+                         choose_table=None, timestamp=None):
+        try:
+            cmd = 'ovs-ofctl -OOpenFlow13 dump-flows {0}'.format(br)
+            if choose_table is not None:
+                cmd = '{0} table={1}'.format(cmd, choose_table)
+            output = self.__remote_cmd(ssh_conn, cmd)
+            operation = 'ofctl_dump_flows'
+            host = self.__ssh_host(ssh_conn)
+            self.__dump_to_file(operation, host, output, timestamp=timestamp)
+            return output
+        except Exception, e:
+            logger.error('[ofctl_dump_flows(ssh_client, {0}, {1})]: {2}'
+                         .format(br, choose_table, e))
+            return None
+
+    def vsctl_show(self, ssh_conn, timestamp=None):
+        try:
+            cmd = 'ovs-vsctl show'
+            output = self.__remote_cmd(ssh_conn, cmd)
+            operation = 'vsctl_show'
+            host = self.__ssh_host(ssh_conn)
+            self.__dump_to_file(operation, host, output, timestamp=timestamp)
+            return output
+        except Exception, e:
+            logger.error('[vsctl_show(ssh_client)]: {0}'.format(e))
+            return None
index 8fd68bc..038f165 100755 (executable)
@@ -21,6 +21,7 @@ args = parser.parse_args()
 """ logging configuration """
 logger = ft_logger.Logger("ODL_SFC").getLogger()
 
+FUNCTEST_RESULTS_DIR = '/home/opnfv/functest/results/'
 FUNCTEST_REPO = ft_utils.FUNCTEST_REPO
 
 HOME = os.environ['HOME'] + "/"
index a1cf8a8..8c82d6d 100755 (executable)
@@ -20,6 +20,7 @@ args = parser.parse_args()
 """ logging configuration """
 logger = ft_logger.Logger("ODL_SFC").getLogger()
 
+FUNCTEST_RESULTS_DIR = '/home/opnfv/functest/results/'
 FUNCTEST_REPO = ft_utils.FUNCTEST_REPO
 
 HOME = os.environ['HOME'] + "/"