From 98c4249cf477b4ed26fc7c5ff80e7e5f3d0a1446 Mon Sep 17 00:00:00 2001 From: "Walter A. Boring IV" Date: Wed, 8 Jul 2015 09:25:07 -0700 Subject: [PATCH] Added ABCMeta class to the InitiatorConnector This patch adds python ABCMeta class to the InitiatorConnector for the purposes of defining a required contract that all Connector objects must adhere to. Currently, the existing required methods of connect_volume, disconnect_volume are the 2 required methods that must be implemented by the child Connector objects. This will be helpful for future features and forcing Connectors to adhere to the API interface Contract. Change-Id: Ie862ad7f358a70d57eddb2bce269230df3c3cdc7 Implements: blueprint os-brick-abc-connectors --- os_brick/initiator/connector.py | 21 ++++++++++++++-- os_brick/tests/base.py | 4 ++-- os_brick/tests/initiator/test_connector.py | 28 +++++++++++++++------- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/os_brick/initiator/connector.py b/os_brick/initiator/connector.py index c75695f87..c051469a7 100644 --- a/os_brick/initiator/connector.py +++ b/os_brick/initiator/connector.py @@ -20,6 +20,7 @@ The connectors here are responsible for discovering and removing volumes for each of the supported transport protocols. """ +import abc import copy import os import platform @@ -106,6 +107,7 @@ def get_connector_properties(root_helper, my_ip, multipath, enforce_multipath, return props +@six.add_metaclass(abc.ABCMeta) class InitiatorConnector(executor.Executor): def __init__(self, root_helper, driver=None, execute=putils.execute, @@ -232,21 +234,36 @@ class InitiatorConnector(executor.Executor): return False return True + @abc.abstractmethod def connect_volume(self, connection_properties): """Connect to a volume. The connection_properties describes the information needed by the specific protocol to use to make the connection. """ - raise NotImplementedError() + pass + @abc.abstractmethod def disconnect_volume(self, connection_properties, device_info): """Disconnect a volume from the local host. The connection_properties are the same as from connect_volume. The device_info is returned from connect_volume. """ - raise NotImplementedError() + pass + + +class FakeConnector(InitiatorConnector): + + fake_path = '/dev/vdFAKE' + + def connect_volume(self, connection_properties): + fake_device_info = {'type': 'fake', + 'path': self.fake_path} + return fake_device_info + + def disconnect_volume(self, connection_properties, device_info): + pass class ISCSIConnector(InitiatorConnector): diff --git a/os_brick/tests/base.py b/os_brick/tests/base.py index 11e706dce..ce3653dd8 100644 --- a/os_brick/tests/base.py +++ b/os_brick/tests/base.py @@ -17,18 +17,18 @@ import logging import os +import testtools import fixtures import mock from oslo_log import log as oslo_logging from oslo_utils import strutils -from oslotest import base LOG = oslo_logging.getLogger(__name__) -class TestCase(base.BaseTestCase): +class TestCase(testtools.TestCase): """Test case base class for all unit tests.""" diff --git a/os_brick/tests/initiator/test_connector.py b/os_brick/tests/initiator/test_connector.py index 6a308390f..523dcd610 100644 --- a/os_brick/tests/initiator/test_connector.py +++ b/os_brick/tests/initiator/test_connector.py @@ -112,15 +112,25 @@ class ConnectorTestCase(base.TestCase): self.cmds.append(" ".join(cmd)) return "", None + def fake_connection(self): + return { + 'driver_volume_type': 'fake', + 'data': { + 'volume_id': 'fake_volume_id', + 'target_portal': 'fake_location', + 'target_iqn': 'fake_iqn', + 'target_lun': 1, + } + } + def test_connect_volume(self): - self.connector = connector.InitiatorConnector(None) - self.assertRaises(NotImplementedError, - self.connector.connect_volume, None) + self.connector = connector.FakeConnector(None) + device_info = self.connector.connect_volume(self.fake_connection()) + self.assertIn('type', device_info) + self.assertIn('path', device_info) def test_disconnect_volume(self): - self.connector = connector.InitiatorConnector(None) - self.assertRaises(NotImplementedError, - self.connector.disconnect_volume, None, None) + self.connector = connector.FakeConnector(None) def test_factory(self): obj = connector.InitiatorConnector.factory('iscsi', None) @@ -158,13 +168,13 @@ class ConnectorTestCase(base.TestCase): "bogus", None) def test_check_valid_device_with_wrong_path(self): - self.connector = connector.InitiatorConnector(None) + self.connector = connector.FakeConnector(None) self.connector._execute = \ lambda *args, **kwargs: ("", None) self.assertFalse(self.connector.check_valid_device('/d0v')) def test_check_valid_device(self): - self.connector = connector.InitiatorConnector(None) + self.connector = connector.FakeConnector(None) self.connector._execute = \ lambda *args, **kwargs: ("", "") self.assertTrue(self.connector.check_valid_device('/dev')) @@ -172,7 +182,7 @@ class ConnectorTestCase(base.TestCase): def test_check_valid_device_with_cmd_error(self): def raise_except(*args, **kwargs): raise putils.ProcessExecutionError - self.connector = connector.InitiatorConnector(None) + self.connector = connector.FakeConnector(None) with mock.patch.object(self.connector, '_execute', side_effect=putils.ProcessExecutionError): self.assertFalse(self.connector.check_valid_device('/dev'))