self.array.create_host],
self.driver._connect, VOLUME, CONNECTOR)
+ @mock.patch(DRIVER_OBJ + "._get_host", autospec=True)
+ def test_connect_already_connected(self, mock_host):
+ mock_host.return_value = PURE_HOST
+ expected = {"host": PURE_HOST_NAME, "lun": 1}
+ self.array.list_volume_hosts.return_value = \
+ [expected, {"host": "extra", "lun": 2}]
+ self.array.connect_host.side_effect = exception.PureAPIException(
+ code=400, reason="Connection already exists")
+ actual = self.driver._connect(VOLUME, CONNECTOR)
+ self.assertEqual(expected, actual)
+ self.assertTrue(self.array.connect_host.called)
+ self.assertTrue(self.array.list_volume_hosts)
+
+ @mock.patch(DRIVER_OBJ + "._get_host", autospec=True)
+ def test_connect_already_connected_list_hosts_empty(self, mock_host):
+ mock_host.return_value = PURE_HOST
+ self.array.list_volume_hosts.return_value = []
+ self.array.connect_host.side_effect = exception.PureAPIException(
+ code=400, reason="Connection already exists")
+ self.assertRaises(exception.PureDriverException,
+ lambda: self.driver._connect(VOLUME, CONNECTOR))
+ self.assertTrue(self.array.connect_host.called)
+ self.assertTrue(self.array.list_volume_hosts)
+
+ @mock.patch(DRIVER_OBJ + "._get_host", autospec=True)
+ def test_connect_already_connected_list_hosts_exception(self, mock_host):
+ mock_host.return_value = PURE_HOST
+ self.array.list_volume_hosts.side_effect = \
+ exception.PureAPIException(code=400, reason="")
+ self.array.connect_host.side_effect = exception.PureAPIException(
+ code=400, reason="Connection already exists")
+ self.assertRaises(exception.PureAPIException,
+ lambda: self.driver._connect(VOLUME, CONNECTOR))
+ self.assertTrue(self.array.connect_host.called)
+ self.assertTrue(self.array.list_volume_hosts)
+
def test_get_host(self):
good_host = PURE_HOST.copy()
good_host.update(iqn=["another-wrong-iqn", INITIATOR_IQN])
from oslo.utils import units
from cinder import exception
-from cinder.i18n import _LE, _LI, _LW
+from cinder.i18n import _, _LE, _LI, _LW
from cinder.openstack.common import log as logging
from cinder import utils
from cinder.volume.drivers.san import san
def _connect(self, volume, connector):
"""Connect the host and volume; return dict describing connection."""
+ connection = None
vol_name = _get_vol_name(volume)
host = self._get_host(connector)
if host:
" %(iqn)s.") % {"host_name": host_name, "iqn": iqn})
self._array.create_host(host_name, iqnlist=[iqn])
- return self._array.connect_host(host_name, vol_name)
+ try:
+ connection = self._array.connect_host(host_name, vol_name)
+ except exception.PureAPIException as err:
+ with excutils.save_and_reraise_exception() as ctxt:
+ if (err.kwargs["code"] == 400 and
+ "Connection already exists" in err.msg):
+ # Happens if the volume is already connected to the host.
+ ctxt.reraise = False
+ LOG.warn(_LW("Volume connection already exists with "
+ "message: %s") % err.msg)
+ # Get the info for the existing connection
+ connected_hosts = self._array.list_volume_hosts(vol_name)
+ for host_info in connected_hosts:
+ if host_info["host"] == host_name:
+ connection = host_info
+ break
+ if not connection:
+ raise exception.PureDriverException(
+ reason=_("Unable to connect or find connection to host"))
+ return connection
def _get_host(self, connector):
"""Return dict describing existing Purity host object or None."""