vnf_generic: convert sshmanager to class 43/27643/4
authorRoss Brattain <ross.b.brattain@intel.com>
Thu, 26 Jan 2017 23:14:59 +0000 (15:14 -0800)
committerRoss Brattain <ross.b.brattain@intel.com>
Wed, 8 Feb 2017 06:50:31 +0000 (06:50 +0000)
@contextmanager have an issue with respect to exceptions that makes
them not suitable for real usage.

@contextmanager uses yield to create a generator and then uses
generator.throw() to raise any exceptions.  Exceptions thrown from
generators loose their call stack due to the way generators work, so any
exception inside a context manager is harder to debug. For this reason
we don't use @contextmanager and instead always define a new class with
__enter__ and __exit__.

There is sample code that demonstrates the
issue with @contextmanager and generator.throw() here
https://gist.github.com/rbbratta/e28b6e64a4551522c3ac9815ca7f25f0

Change-Id: I5383c01f40a63e33680112f39b5bd9c858e328f1
Signed-off-by: Ross Brattain <ross.b.brattain@intel.com>
tests/unit/benchmark/scenarios/networking/test_vnf_generic.py
yardstick/benchmark/scenarios/networking/vnf_generic.py

index 0d9fbaf..9b7174e 100644 (file)
@@ -23,7 +23,7 @@ import mock
 import os
 
 from yardstick.benchmark.scenarios.networking.vnf_generic import \
-    ssh_manager, NetworkServiceTestCase, IncorrectConfig, IncorrectSetup
+    SshManager, NetworkServiceTestCase, IncorrectConfig, IncorrectSetup
 from yardstick.network_services.collector.subscriber import Collector
 from yardstick.network_services.vnf_generic.vnf.base import \
     GenericTrafficGen, GenericVNF
@@ -304,7 +304,7 @@ class TestNetworkServiceTestCase(unittest.TestCase):
                 mock.Mock(return_value=(0, SYS_CLASS_NET+IP_ADDR_SHOW, ""))
             ssh.return_value = ssh_mock
             for node, node_dict in self.context_cfg["nodes"].items():
-                with ssh_manager(node_dict) as conn:
+                with SshManager(node_dict) as conn:
                     self.assertIsNotNone(conn)
 
     def test___init__(self):
index d7ba418..2956d6d 100644 (file)
@@ -15,7 +15,6 @@
 
 from __future__ import absolute_import
 import logging
-from contextlib import contextmanager
 import yaml
 
 from yardstick.benchmark.scenarios import base
@@ -49,31 +48,32 @@ class IncorrectSetup(Exception):
     pass
 
 
-@contextmanager
-def ssh_manager(node):
-    """
-    args -> network device mappings
-    returns -> ssh connection ready to be used
-    """
-    conn = None
-    try:
-        ssh_port = node.get("ssh_port", ssh.DEFAULT_PORT)
-        conn = ssh.SSH(user=node.get("user", ""),
-                       host=node.get("ip", ""),
-                       password=node.get("password", ""),
-                       port=ssh_port)
-        conn.wait()
-
-    except (SSHError) as error:
-        LOG.info("connect failed to %s, due to %s", node.get("ip", ""), error)
-    try:
-        if conn:
-            yield conn
-        else:
-            yield False
-    finally:
-        if conn:
-            conn.close()
+class SshManager(object):
+    def __init__(self, node):
+        super(SshManager, self).__init__()
+        self.node = node
+        self.conn = None
+
+    def __enter__(self):
+        """
+        args -> network device mappings
+        returns -> ssh connection ready to be used
+        """
+        try:
+            ssh_port = self.node.get("ssh_port", ssh.DEFAULT_PORT)
+            self.conn = ssh.SSH(user=self.node["user"],
+                                host=self.node["ip"],
+                                password=self.node["password"],
+                                port=ssh_port)
+            self.conn.wait()
+        except (SSHError) as error:
+            LOG.info("connect failed to %s, due to %s", self.node["ip"], error)
+        # self.conn defaults to None
+        return self.conn
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        if self.conn:
+            self.conn.close()
 
 
 class NetworkServiceTestCase(base.Scenario):
@@ -208,7 +208,7 @@ class NetworkServiceTestCase(base.Scenario):
         for node, node_dict in context_cfg["nodes"].items():
 
             cmd = "PATH=$PATH:/sbin:/usr/sbin ip addr show"
-            with ssh_manager(node_dict) as conn:
+            with SshManager(node_dict) as conn:
                 exit_status = conn.execute(cmd)[0]
                 if exit_status != 0:
                     raise IncorrectSetup("Node's %s lacks ip tool." % node)