diff --git a/cinder/cmd/rtstool.py b/cinder/cmd/rtstool.py index d97a950b389..7713c685b12 100644 --- a/cinder/cmd/rtstool.py +++ b/cinder/cmd/rtstool.py @@ -82,14 +82,15 @@ def create(backing_device, name, userid, password, iser_enabled, # If no ips are given we'll bind to all IPv4 and v6 if not portals_ips: - portals_ips = ('0.0.0.0', '::0') + portals_ips = ('0.0.0.0', '[::0]') # TODO(emh): Binding to IPv6 fails sometimes -- let pass for now. - ips_allow_fail = ('::0',) + ips_allow_fail = ('[::0]',) for ip in portals_ips: try: - portal = rtslib_fb.NetworkPortal(tpg_new, ip, portals_port, - mode='any') + # rtslib expects IPv6 addresses to be surrounded by brackets + portal = rtslib_fb.NetworkPortal(tpg_new, _canonicalize_ip(ip), + portals_port, mode='any') except rtslib_fb.utils.RTSLibError: raise_exc = ip not in ips_allow_fail msg_type = 'Error' if raise_exc else 'Warning' @@ -258,6 +259,12 @@ def parse_optional_create(argv): return optional_args +def _canonicalize_ip(ip): + if ip.startswith('[') or "." in ip: + return ip + return "[" + ip + "]" + + def main(argv=None): if argv is None: argv = sys.argv diff --git a/cinder/tests/unit/test_cmd.py b/cinder/tests/unit/test_cmd.py index a095caa9f16..25a094b8459 100644 --- a/cinder/tests/unit/test_cmd.py +++ b/cinder/tests/unit/test_cmd.py @@ -925,11 +925,11 @@ class TestCinderRtstoolCmd(test.TestCase): lun.assert_called_once_with(tpg_new, storage_object=mock.sentinel.so_new) self.assertEqual(1, tpg_new.enable) - network_portal.assert_any_call(tpg_new, ip, 3260, - mode='any') if ip == '::0': - network_portal.assert_any_call(tpg_new, ip, 3260, mode='any') + ip = '[::0]' + + network_portal.assert_any_call(tpg_new, ip, 3260, mode='any') def test_create_rtslib_error_network_portal_ipv4(self): with mock.patch('sys.stdout', new=six.StringIO()): @@ -956,12 +956,6 @@ class TestCinderRtstoolCmd(test.TestCase): tpg_new = tpg.return_value lun.return_value = mock.sentinel.lun_new - def network_portal_exception(*args, **kwargs): - if set([tpg_new, '::0', 3260]).issubset(list(args)): - raise rtslib_fb.utils.RTSLibError() - else: - pass - cinder_rtstool.create(mock.sentinel.backing_device, mock.sentinel.name, mock.sentinel.userid, @@ -981,11 +975,11 @@ class TestCinderRtstoolCmd(test.TestCase): lun.assert_called_once_with(tpg_new, storage_object=mock.sentinel.so_new) self.assertEqual(1, tpg_new.enable) - network_portal.assert_any_call(tpg_new, ip, 3260, - mode='any') if ip == '::0': - network_portal.assert_any_call(tpg_new, ip, 3260, mode='any') + ip = '[::0]' + + network_portal.assert_any_call(tpg_new, ip, 3260, mode='any') def test_create_ipv4(self): self._test_create('0.0.0.0') @@ -993,11 +987,7 @@ class TestCinderRtstoolCmd(test.TestCase): def test_create_ipv6(self): self._test_create('::0') - @mock.patch.object(cinder_rtstool, 'rtslib_fb', autospec=True) - def test_create_ips_and_port(self, mock_rtslib): - port = 3261 - ips = ['ip1', 'ip2', 'ip3'] - + def _test_create_ips_and_port(self, mock_rtslib, port, ips, expected_ips): mock_rtslib.BlockStorageObject.return_value = mock.sentinel.bso mock_rtslib.Target.return_value = mock.sentinel.target_new mock_rtslib.FabricModule.return_value = mock.sentinel.iscsi_fabric @@ -1021,10 +1011,24 @@ class TestCinderRtstoolCmd(test.TestCase): storage_object=mock.sentinel.bso) mock_rtslib.NetworkPortal.assert_has_calls( - map(lambda ip: mock.call(tpg_new, ip, port, mode='any'), ips), - any_order=True + map(lambda ip: mock.call(tpg_new, ip, port, mode='any'), + expected_ips), any_order=True ) + @mock.patch.object(cinder_rtstool, 'rtslib_fb', autospec=True) + def test_create_ips_and_port_ipv4(self, mock_rtslib): + ips = ['10.0.0.2', '10.0.0.3', '10.0.0.4'] + port = 3261 + self._test_create_ips_and_port(mock_rtslib, port, ips, ips) + + @mock.patch.object(cinder_rtstool, 'rtslib_fb', autospec=True) + def test_create_ips_and_port_ipv6(self, mock_rtslib): + ips = ['fe80::fc16:3eff:fecb:ad2f'] + expected_ips = ['[fe80::fc16:3eff:fecb:ad2f]'] + port = 3261 + self._test_create_ips_and_port(mock_rtslib, port, ips, + expected_ips) + @mock.patch.object(rtslib_fb.root, 'RTSRoot') def test_add_initiator_rtslib_error(self, rtsroot): rtsroot.side_effect = rtslib_fb.utils.RTSLibError()