Last active
August 29, 2015 14:04
-
-
Save yosshy/5b6bd323bb631316ef3e to your computer and use it in GitHub Desktop.
Libvirt/QEMU iSCSI pass-through patch for Nova Juno
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<domain type='qemu' id='9'> | |
<name>instance-00000005</name> | |
<uuid>528dc044-4ea2-4cb7-9ebe-f1a03875490c</uuid> | |
<memory unit='KiB'>2097152</memory> | |
<currentMemory unit='KiB'>2097152</currentMemory> | |
<vcpu placement='static'>1</vcpu> | |
<resource> | |
<partition>/machine</partition> | |
</resource> | |
<sysinfo type='smbios'> | |
<system> | |
<entry name='manufacturer'>OpenStack Foundation</entry> | |
<entry name='product'>OpenStack Nova</entry> | |
<entry name='version'>2014.2</entry> | |
<entry name='serial'>ba8d6b41-89e8-4f4a-b887-cee4070e8d9f</entry> | |
<entry name='uuid'>528dc044-4ea2-4cb7-9ebe-f1a03875490c</entry> | |
</system> | |
</sysinfo> | |
<os> | |
<type arch='x86_64' machine='pc-i440fx-trusty'>hvm</type> | |
<boot dev='hd'/> | |
<smbios mode='sysinfo'/> | |
</os> | |
<features> | |
<acpi/> | |
<apic/> | |
</features> | |
<cpu> | |
<topology sockets='1' cores='1' threads='1'/> | |
</cpu> | |
<clock offset='utc'/> | |
<on_poweroff>destroy</on_poweroff> | |
<on_reboot>restart</on_reboot> | |
<on_crash>destroy</on_crash> | |
<devices> | |
<emulator>/usr/bin/qemu-system-x86_64</emulator> | |
<disk type='file' device='disk'> | |
<driver name='qemu' type='qcow2' cache='none'/> | |
<source file='/opt/stack/data/nova/instances/528dc044-4ea2-4cb7-9ebe-f1a03875490c/disk'/> | |
<target dev='vda' bus='virtio'/> | |
<alias name='virtio-disk0'/> | |
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> | |
</disk> | |
<disk type='network' device='disk'> | |
<driver name='qemu' type='raw' cache='none'/> | |
<auth username='XfeKqEHYULdN6NSbCiXH'> | |
<secret type='iscsi' uuid='dc3d9e94-f7f1-401a-88c2-477107bbb8af'/> | |
</auth> | |
<source protocol='iscsi' name='iqn.2010-10.org.openstack:volume-d09da9fc-4d71-4b11-b74a-7561c5dfd224/1'> | |
<host name='10.0.2.15' port='3260'/> | |
</source> | |
<target dev='vdb' bus='virtio'/> | |
<serial>d09da9fc-4d71-4b11-b74a-7561c5dfd224</serial> | |
<alias name='virtio-disk1'/> | |
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> | |
</disk> | |
<disk type='file' device='cdrom'> | |
<driver name='qemu' type='raw' cache='none'/> | |
<source file='/opt/stack/data/nova/instances/528dc044-4ea2-4cb7-9ebe-f1a03875490c/disk.config'/> | |
<target dev='hdd' bus='ide'/> | |
<readonly/> | |
<alias name='ide0-1-1'/> | |
<address type='drive' controller='0' bus='1' target='0' unit='1'/> | |
</disk> | |
<controller type='usb' index='0'> | |
<alias name='usb0'/> | |
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> | |
</controller> | |
<controller type='pci' index='0' model='pci-root'> | |
<alias name='pci.0'/> | |
</controller> | |
<controller type='ide' index='0'> | |
<alias name='ide0'/> | |
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> | |
</controller> | |
<interface type='bridge'> | |
<mac address='fa:16:3e:1f:7b:f9'/> | |
<source bridge='br100'/> | |
<target dev='vnet0'/> | |
<model type='virtio'/> | |
<driver name='qemu'/> | |
<filterref filter='nova-instance-instance-00000005-fa163e1f7bf9'/> | |
<alias name='net0'/> | |
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> | |
</interface> | |
<serial type='file'> | |
<source path='/opt/stack/data/nova/instances/528dc044-4ea2-4cb7-9ebe-f1a03875490c/console.log'/> | |
<target port='0'/> | |
<alias name='serial0'/> | |
</serial> | |
<serial type='pty'> | |
<source path='/dev/pts/25'/> | |
<target port='1'/> | |
<alias name='serial1'/> | |
</serial> | |
<console type='file'> | |
<source path='/opt/stack/data/nova/instances/528dc044-4ea2-4cb7-9ebe-f1a03875490c/console.log'/> | |
<target type='serial' port='0'/> | |
<alias name='serial0'/> | |
</console> | |
<input type='mouse' bus='ps2'/> | |
<input type='keyboard' bus='ps2'/> | |
<graphics type='vnc' port='5900' autoport='yes' listen='127.0.0.1' keymap='ja'> | |
<listen type='address' address='127.0.0.1'/> | |
</graphics> | |
<video> | |
<model type='cirrus' vram='9216' heads='1'/> | |
<alias name='video0'/> | |
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> | |
</video> | |
<memballoon model='virtio'> | |
<alias name='balloon0'/> | |
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> | |
</memballoon> | |
</devices> | |
<seclabel type='dynamic' model='apparmor' relabel='yes'> | |
<label>libvirt-528dc044-4ea2-4cb7-9ebe-f1a03875490c</label> | |
<imagelabel>libvirt-528dc044-4ea2-4cb7-9ebe-f1a03875490c</imagelabel> | |
</seclabel> | |
</domain> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit a65bb5b87f2f662e6dd3ec9a04d3d3fd1f4f29ab | |
Author: Akira Yoshiyama <[email protected]> | |
Date: Tue Jul 29 14:58:30 2014 +0000 | |
Add KVM/QEMU iSCSI pass-through capability. | |
This patch allows nova-compute to use KVM/QEMU iSCSI pass-through | |
capability for Cinder iSCSI volume drivers. It doesn't provide | |
iSCSI multipath capability, but host OS doesn't have to handle | |
iSCSI connection for volume because KVM/QEMU does it directly | |
with libiscsi. | |
To use this, you have to write a parameter at nova.conf: | |
volume_drivers = iscsi=nova.virt.libvirt.volume.LibvirtNetVolumeDriver,iser=nova.virt.libvirt.volume.LibvirtISERVolumeDriver,... | |
or just | |
volume_drivers = iscsi=nova.virt.libvirt.volume.LibvirtNetVolumeDriver | |
Note that qemu-system-x86 in Ubuntu has no iSCSI pass-through | |
support because libiscsi isn't in main repository but universe. | |
I've tested qemu-system-x86 built with libiscsi2 package of | |
Debian on Ubuntu 14.04. | |
diff --git a/nova/virt/libvirt/config.py b/nova/virt/libvirt/config.py | |
index 0255ac1..b0844ac 100644 | |
--- a/nova/virt/libvirt/config.py | |
+++ b/nova/virt/libvirt/config.py | |
@@ -1717,3 +1717,38 @@ class LibvirtConfigGuestMetaNovaOwner(LibvirtConfigObject): | |
project.set("uuid", self.projectid) | |
meta.append(project) | |
return meta | |
+ | |
+ | |
+class LibvirtConfigSecret(LibvirtConfigObject): | |
+ | |
+ def __init__(self): | |
+ super(LibvirtConfigSecret, | |
+ self).__init__(root_name="secret") | |
+ self.ephemeral = False | |
+ self.private = False | |
+ self.description = None | |
+ self.usage_type = None | |
+ self.usage_name = None | |
+ self.usage_target = None | |
+ | |
+ def get_bool_str(self, value): | |
+ if value: | |
+ return 'yes' | |
+ return 'no' | |
+ | |
+ def format_dom(self): | |
+ root = super(LibvirtConfigSecret, self).format_dom() | |
+ root.set("ephemeral", self.get_bool_str(self.ephemeral)) | |
+ root.set("private", self.get_bool_str(self.private)) | |
+ if self.description is not None: | |
+ root.append(self._text_node("description", str(self.description))) | |
+ if self.usage_target is not None and self.usage_type is not None: | |
+ usage = self._new_node("usage") | |
+ if self.usage_type is not None: | |
+ usage.set("type", self.usage_type) | |
+ if self.usage_name is not None: | |
+ usage.append(self._text_node('name', str(self.usage_name))) | |
+ if self.usage_target is not None: | |
+ usage.append(self._text_node('target', str(self.usage_target))) | |
+ root.append(usage) | |
+ return root | |
diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py | |
index 16c4e69..31c49a1 100644 | |
--- a/nova/virt/libvirt/driver.py | |
+++ b/nova/virt/libvirt/driver.py | |
@@ -5515,6 +5515,50 @@ class LibvirtDriver(driver.ComputeDriver): | |
return fs_type in [disk.FS_FORMAT_EXT2, disk.FS_FORMAT_EXT3, | |
disk.FS_FORMAT_EXT4, disk.FS_FORMAT_XFS] | |
+ def _find_secret(self, usage_type_str, usage_name): | |
+ if usage_type_str == 'iscsi': | |
+ usage_type = libvirt.VIR_SECRET_USAGE_TYPE_ISCSI | |
+ elif usage_type_str == 'ceph': | |
+ usage_type = libvirt.VIR_SECRET_USAGE_TYPE_CEPH | |
+ elif usage_type_str == 'volume': | |
+ usage_type = libvirt.VIR_SECRET_USAGE_TYPE_VOLUME | |
+ | |
+ return self._conn.secretLookupByUsage(usage_type, usage_name) | |
+ | |
+ def get_secret(self, secret_conf, password=None): | |
+ """Create a secret. | |
+ | |
+ secret_conf must be passed in. | |
+ """ | |
+ try: | |
+ usage_name = secret_conf.usage_name or secret_conf.usage_target | |
+ usage_type = secret_conf.usage_type | |
+ return self._find_secret(usage_type, usage_name) | |
+ except Exception: | |
+ pass | |
+ | |
+ xml = secret_conf.to_xml() | |
+ try: | |
+ LOG.debug(_LE('Secret XML: %s') % xml) | |
+ secret = self._conn.secretDefineXML(xml) | |
+ if password is not None: | |
+ secret.setValue(password) | |
+ return secret | |
+ except Exception: | |
+ with excutils.save_and_reraise_exception(): | |
+ LOG.error(_LE('Error defining a secret with XML: %s') % xml) | |
+ | |
+ def delete_secret(self, usage_type, usage_name): | |
+ """Delete a secret. | |
+ | |
+ secret_conf must be passed in. | |
+ """ | |
+ try: | |
+ secret = self._find_secret(usage_type, usage_name) | |
+ secret.undefine() | |
+ except Exception: | |
+ pass | |
+ | |
class HostState(object): | |
"""Manages information about the compute node through libvirt.""" | |
diff --git a/nova/virt/libvirt/volume.py b/nova/virt/libvirt/volume.py | |
index 261216b..ff94af5 100644 | |
--- a/nova/virt/libvirt/volume.py | |
+++ b/nova/virt/libvirt/volume.py | |
@@ -190,6 +190,31 @@ class LibvirtNetVolumeDriver(LibvirtBaseVolumeDriver): | |
super(LibvirtNetVolumeDriver, | |
self).__init__(connection, is_block_dev=False) | |
+ def _get_secret_uuid(self, conf, password=None): | |
+ secret_conf = vconfig.LibvirtConfigSecret() | |
+ secret_conf.ephemeral = False | |
+ secret_conf.private = False | |
+ secret_conf.usage_type = conf.source_protocol | |
+ if conf.source_protocol == 'rbd': | |
+ secret_conf.usage_type = 'ceph' | |
+ secret_conf.usage_name = conf.source_name | |
+ elif conf.source_protocol == 'iscsi': | |
+ secret_conf.usage_type = 'iscsi' | |
+ secret_conf.usage_target = conf.source_name | |
+ secret = self.connection.get_secret(secret_conf, password) | |
+ return secret.UUIDString() | |
+ | |
+ def _delete_secret_by_name(self, connection_info): | |
+ source_protocol = connection_info['driver_volume_type'] | |
+ netdisk_properties = connection_info['data'] | |
+ if source_protocol == 'rbd': | |
+ return | |
+ elif source_protocol == 'iscsi': | |
+ usage_type = 'iscsi' | |
+ usage_name = ("%(target_iqn)s/%(target_lun)s" % | |
+ netdisk_properties) | |
+ self.connection.delete_secret(usage_type, usage_name) | |
+ | |
def connect_volume(self, connection_info, disk_info): | |
conf = super(LibvirtNetVolumeDriver, | |
self).connect_volume(connection_info, | |
@@ -207,14 +232,32 @@ class LibvirtNetVolumeDriver(LibvirtBaseVolumeDriver): | |
auth_enabled = True # Force authentication locally | |
if CONF.libvirt.rbd_user: | |
conf.auth_username = CONF.libvirt.rbd_user | |
+ if conf.source_protocol == 'iscsi': | |
+ conf.source_name = ("%(target_iqn)s/%(target_lun)s" % | |
+ netdisk_properties) | |
+ ip, port = netdisk_properties.get('target_portal', "").split(':') | |
+ conf.source_hosts = [ip] | |
+ conf.source_ports = [port] | |
+ if netdisk_properties.get('auth_method') == 'CHAP': | |
+ auth_enabled = True | |
+ conf.auth_secret_type = 'iscsi' | |
+ password = netdisk_properties.get('auth_password') | |
+ conf.auth_secret_uuid = self._get_secret_uuid(conf, password) | |
if auth_enabled: | |
conf.auth_username = (conf.auth_username or | |
netdisk_properties['auth_username']) | |
- conf.auth_secret_type = netdisk_properties['secret_type'] | |
+ conf.auth_secret_type = (conf.auth_secret_type or | |
+ netdisk_properties['secret_type']) | |
conf.auth_secret_uuid = (conf.auth_secret_uuid or | |
netdisk_properties['secret_uuid']) | |
return conf | |
+ def disconnect_volume(self, connection_info, disk_dev): | |
+ """Detach the volume from instance_name.""" | |
+ super(LibvirtNetVolumeDriver, | |
+ self).disconnect_volume(connection_info, disk_dev) | |
+ self._delete_secret_by_name(connection_info) | |
+ | |
class LibvirtISCSIVolumeDriver(LibvirtBaseVolumeDriver): | |
"""Driver to attach Network volumes to libvirt.""" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment