diff options
| author | Vishvananda Ishaya <vishvananda@gmail.com> | 2012-02-09 15:05:21 -0800 |
|---|---|---|
| committer | Renuka Apte <renuka.apte@citrix.com> | 2012-02-16 16:45:15 -0800 |
| commit | 509e5ad9ef6ed38caa69d2c76b1adccedcdd315e (patch) | |
| tree | 982eabc1e080a1d0825fe871ecf418c5f182e6c8 /nova/virt | |
| parent | 844035b6c0f725c685cdff56a7bb77efe7825a5f (diff) | |
| download | nova-509e5ad9ef6ed38caa69d2c76b1adccedcdd315e.tar.gz nova-509e5ad9ef6ed38caa69d2c76b1adccedcdd315e.tar.xz nova-509e5ad9ef6ed38caa69d2c76b1adccedcdd315e.zip | |
Fixes nova-volume support for multiple luns
* stores lun in provider_location if specified
* passes lun in iscsi_properties instead of hard coding
* adds call to libvirt to list all used block devices
* make sure to synchronize connect and disconnect commands
* only disconnect from target if no luns are in use
* allow double logins to targets
* fixes typo in get_volume_connector in xenapi_connection
* fixes bug 929790
Change-Id: I2466dc750a6fa5e0b07f94314d38873740aa6b29
Diffstat (limited to 'nova/virt')
| -rw-r--r-- | nova/virt/libvirt/connection.py | 20 | ||||
| -rw-r--r-- | nova/virt/libvirt/volume.py | 42 | ||||
| -rw-r--r-- | nova/virt/xenapi_conn.py | 2 |
3 files changed, 47 insertions, 17 deletions
diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py index c3bfdedda..349faa157 100644 --- a/nova/virt/libvirt/connection.py +++ b/nova/virt/libvirt/connection.py @@ -1388,6 +1388,26 @@ class LibvirtConnection(driver.ComputeDriver): return domain + def get_all_block_devices(self): + """ + Return all block devices in use on this node. + """ + devices = [] + for dom_id in self._conn.listDomainsID(): + domain = self._conn.lookupByID(dom_id) + try: + doc = ElementTree.fromstring(domain.XMLDesc(0)) + except Exception: + continue + ret = doc.findall('./devices/disk') + for node in ret: + if node.get('type') != 'block': + continue + for child in node.getchildren(): + if child.tag == 'source': + devices.append(child.get('dev')) + return devices + def get_disks(self, instance_name): """ Note that this function takes an instance name. diff --git a/nova/virt/libvirt/volume.py b/nova/virt/libvirt/volume.py index 75fa0e5a9..055e34abc 100644 --- a/nova/virt/libvirt/volume.py +++ b/nova/virt/libvirt/volume.py @@ -103,14 +103,16 @@ class LibvirtISCSIVolumeDriver(LibvirtVolumeDriver): '-v', property_value) return self._run_iscsiadm(iscsi_properties, iscsi_command) + @utils.synchronized('connect_volume') def connect_volume(self, connection_info, mount_device): """Attach the volume to instance_name""" iscsi_properties = connection_info['data'] - # NOTE(vish): if we are on the same host as nova volume, the + # NOTE(vish): If we are on the same host as nova volume, the # discovery makes the target so we don't need to # run --op new. Therefore, we check to see if the # target exists, and if we get 255 (Not Found), then - # we run --op new + # we run --op new. This will also happen if another + # volume is using the same target. try: self._run_iscsiadm(iscsi_properties, ()) except exception.ProcessExecutionError as exc: @@ -131,18 +133,17 @@ class LibvirtISCSIVolumeDriver(LibvirtVolumeDriver): "node.session.auth.password", iscsi_properties['auth_password']) - self._run_iscsiadm(iscsi_properties, ("--login",)) + # NOTE(vish): If we have another lun on the same target, we may + # have a duplicate login + self._run_iscsiadm(iscsi_properties, ("--login",), + check_exit_code=[0, 255]) self._iscsiadm_update(iscsi_properties, "node.startup", "automatic") - if FLAGS.iscsi_helper == 'tgtadm': - host_device = ("/dev/disk/by-path/ip-%s-iscsi-%s-lun-1" % - (iscsi_properties['target_portal'], - iscsi_properties['target_iqn'])) - else: - host_device = ("/dev/disk/by-path/ip-%s-iscsi-%s-lun-0" % - (iscsi_properties['target_portal'], - iscsi_properties['target_iqn'])) + host_device = ("/dev/disk/by-path/ip-%s-iscsi-%s-lun-%s" % + (iscsi_properties['target_portal'], + iscsi_properties['target_iqn'], + iscsi_properties.get('target_lun', 0))) # The /dev/disk/by-path/... node is not always present immediately # TODO(justinsb): This retry-with-delay is a pattern, move to utils? @@ -172,13 +173,22 @@ class LibvirtISCSIVolumeDriver(LibvirtVolumeDriver): sup = super(LibvirtISCSIVolumeDriver, self) return sup.connect_volume(connection_info, mount_device) + @utils.synchronized('connect_volume') def disconnect_volume(self, connection_info, mount_device): """Detach the volume from instance_name""" sup = super(LibvirtISCSIVolumeDriver, self) sup.disconnect_volume(connection_info, mount_device) iscsi_properties = connection_info['data'] - self._iscsiadm_update(iscsi_properties, "node.startup", "manual") - self._run_iscsiadm(iscsi_properties, ("--logout",), - check_exit_code=[0, 255]) - self._run_iscsiadm(iscsi_properties, ('--op', 'delete'), - check_exit_code=[0, 255]) + # NOTE(vish): Only disconnect from the target if no luns from the + # target are in use. + device_prefix = ("/dev/disk/by-path/ip-%s-iscsi-%s-lun-" % + (iscsi_properties['target_portal'], + iscsi_properties['target_iqn'])) + devices = self.connection.get_all_block_devices() + devices = [dev for dev in devices if dev.startswith(device_prefix)] + if not devices: + self._iscsiadm_update(iscsi_properties, "node.startup", "manual") + self._run_iscsiadm(iscsi_properties, ("--logout",), + check_exit_code=[0, 255]) + self._run_iscsiadm(iscsi_properties, ('--op', 'delete'), + check_exit_code=[0, 255]) diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index 1e2d11bb0..08542268c 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -346,7 +346,7 @@ class XenAPIConnection(driver.ComputeDriver): def get_volume_connector(self, _instance): """Return volume connector information""" if not self._initiator: - stats = self.get_host_stats(update=True) + stats = self.get_host_stats(refresh=True) try: self._initiator = stats['host_other-config']['iscsi_iqn'] except (TypeError, KeyError): |
