diff --git a/brick_cinderclient_ext/__init__.py b/brick_cinderclient_ext/__init__.py index cbdf71b..0d1253e 100644 --- a/brick_cinderclient_ext/__init__.py +++ b/brick_cinderclient_ext/__init__.py @@ -39,6 +39,8 @@ ENFORCE_MULTIPATH_HELP_MESSAGE = ( 'and only the first path shown up is used.') NETWORK_INTERFACE_HELP_MESSAGE = ('Use a specific network interface to ' 'determine IP address.') +LOCAL_ATTACH_NIC_HELP_MESSAGE = ('Use a specific network interface for ' + 'connector during attach operation.') @utils.arg('--multipath', @@ -86,6 +88,10 @@ def do_get_connector(client, args): metavar='', default=False, help=ENFORCE_MULTIPATH_HELP_MESSAGE) +@utils.arg('--nic', + metavar='', + default=None, + help=LOCAL_ATTACH_NIC_HELP_MESSAGE) @brick_utils.require_root def do_local_attach(client, args): hostname = args.hostname @@ -96,8 +102,8 @@ def do_local_attach(client, args): args.mountpoint, args.mode, args.multipath, - args.enforce_multipath) - + args.enforce_multipath, + args.nic) utils.print_dict(device_info) diff --git a/brick_cinderclient_ext/client.py b/brick_cinderclient_ext/client.py index 565f391..ba8fc74 100644 --- a/brick_cinderclient_ext/client.py +++ b/brick_cinderclient_ext/client.py @@ -66,8 +66,7 @@ class Client(object): return conn_prop def attach(self, volume_id, hostname, mountpoint=None, mode='rw', - multipath=False, enforce_multipath=False): - + multipath=False, enforce_multipath=False, nic=None): # Check protocol type of storage backend. with actions.VerifyProtocol(self.volumes_client, volume_id) as cmd: # Retrieve vol-host attribute of volume. @@ -84,7 +83,8 @@ class Client(object): with actions.InitializeConnection( self.volumes_client, volume_id) as cmd: - connection = cmd.initialize(self, multipath, enforce_multipath) + connection = cmd.initialize(self, multipath, enforce_multipath, + nic) with actions.ConnectVolume(self.volumes_client, volume_id) as cmd: brick_connector = self._brick_get_connector( @@ -95,14 +95,15 @@ class Client(object): return device_info def detach(self, volume_id, attachment_uuid=None, multipath=False, - enforce_multipath=False, device_info=None): + enforce_multipath=False, device_info=None, nic=None): with actions.BeginDetach(self.volumes_client, volume_id) as cmd: cmd.reserve() with actions.InitializeConnectionForDetach( self.volumes_client, volume_id) as cmd: - connection = cmd.initialize(self, multipath, enforce_multipath) + connection = cmd.initialize(self, multipath, enforce_multipath, + nic) brick_connector = self._brick_get_connector( connection['driver_volume_type'], do_local_attach=True) diff --git a/brick_cinderclient_ext/tests/unit/test_volume_actions.py b/brick_cinderclient_ext/tests/unit/test_volume_actions.py index a453ebc..b6c8814 100644 --- a/brick_cinderclient_ext/tests/unit/test_volume_actions.py +++ b/brick_cinderclient_ext/tests/unit/test_volume_actions.py @@ -12,6 +12,7 @@ import ddt import mock +import netifaces from cinderclient import exceptions as cinder_exceptions from os_brick import exception @@ -47,14 +48,32 @@ class TestVolumeActions(base.BaseTestCase): self.v_client.volumes.reserve.assert_called_once_with(self.volume_id) - def test_initialize_connection(self): - self.brick_client.get_connector.return_value = None - with volume_actions.InitializeConnection(*self.command_args) as cmd: - cmd.initialize(self.brick_client, False, False) + @mock.patch('netifaces.ifaddresses', + return_value={netifaces.AF_INET: [{'addr': '127.0.0.1'}]}) + @mock.patch('netifaces.interfaces', return_value=['eth1']) + @mock.patch('brick_cinderclient_ext.brick_utils.get_my_ip', + return_value='1.0.0.0') + @ddt.data((None, {'ip': '1.0.0.0'}), + ('eth1', {'ip': '127.0.0.1'})) + @ddt.unpack + def test_initialize_connection(self, _nic, _conn_prop, + _fake_my_ip, _fake_interfaces, + _fake_ifaddresses): + """Test calling initialize_connection with different input params. - self.brick_client.get_connector.assert_called_once_with(False, False) + Contains next initialize connection test cases: + 1. Without any additional parameters in request; + 2. Using --nic as a parameter; + TODO (mdovgal): add other test cases; + """ + self.brick_client.get_connector.return_value = _conn_prop + with volume_actions.InitializeConnection(*self.command_args) as cmd: + cmd.initialize(self.brick_client, False, False, _nic) + + self.brick_client.get_connector.assert_called_once_with(False, False, + _nic) self.v_client.volumes.initialize_connection.assert_called_once_with( - self.volume_id, None) + self.volume_id, _conn_prop) @ddt.data('iscsi', 'iSCSI', 'ISCSI', 'rbd', 'RBD') def test_verify_protocol(self, protocol): diff --git a/brick_cinderclient_ext/volume_actions.py b/brick_cinderclient_ext/volume_actions.py index 5d5e312..db6503d 100644 --- a/brick_cinderclient_ext/volume_actions.py +++ b/brick_cinderclient_ext/volume_actions.py @@ -35,8 +35,9 @@ class Reserve(VolumeAction): class InitializeConnection(VolumeAction): - def initialize(self, brick_client, multipath, enforce_multipath): - conn_prop = brick_client.get_connector(multipath, enforce_multipath) + def initialize(self, brick_client, multipath, enforce_multipath, nic): + conn_prop = brick_client.get_connector(multipath, enforce_multipath, + nic) return self.volumes_client.volumes.initialize_connection( self.volume_id, conn_prop) diff --git a/releasenotes/notes/add_local_attach_nic_attr-923f867bd565dc36.yaml b/releasenotes/notes/add_local_attach_nic_attr-923f867bd565dc36.yaml new file mode 100644 index 0000000..e5584d7 --- /dev/null +++ b/releasenotes/notes/add_local_attach_nic_attr-923f867bd565dc36.yaml @@ -0,0 +1,3 @@ +--- +features: + - Added attribute --nic to local-attach command.