Skip to content

Commit

Permalink
libvirt: improve the specification of network disks
Browse files Browse the repository at this point in the history
Allow zero or more hosts, and make the name optional, since only a
host is needed to use nbd. This allows cinder to fully specify the
location of a sheepdog or rbd volume without depending on extra
configuration files, and lays the groundwork for supporting nbd.

Rename the internal attribute source_host to source_name to reflect
its usage in the libvirt xml, and add source_hosts and source_ports
attributes to store the new information.

Fixes: bug 1077817
blueprint better-libvirt-network-volume-support
Signed-off-by: Josh Durgin <josh.durgin@inktank.com>

Change-Id: I8ac431751692e52ba0786768cea996388962922d
  • Loading branch information
jdurgin committed May 28, 2013
1 parent 0952675 commit 4d99a34
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 8 deletions.
49 changes: 47 additions & 2 deletions nova/tests/virt/libvirt/test_libvirt_config.py
Expand Up @@ -434,7 +434,7 @@ def test_config_network(self):
obj = config.LibvirtConfigGuestDisk()
obj.source_type = "network"
obj.source_protocol = "iscsi"
obj.source_host = "foo.bar.com"
obj.source_name = "foo.bar.com"
obj.driver_name = "qemu"
obj.driver_format = "qcow2"
obj.target_dev = "/dev/hda"
Expand All @@ -448,11 +448,56 @@ def test_config_network(self):
<target bus="ide" dev="/dev/hda"/>
</disk>""")

def test_config_network_no_name(self):
obj = config.LibvirtConfigGuestDisk()
obj.source_type = 'network'
obj.source_protocol = 'nbd'
obj.source_hosts = ['foo.bar.com']
obj.source_ports = [None]
obj.driver_name = 'qemu'
obj.driver_format = 'raw'
obj.target_dev = '/dev/vda'
obj.target_bus = 'virtio'

xml = obj.to_xml()
self.assertXmlEqual(xml, """
<disk type="network" device="disk">
<driver name="qemu" type="raw"/>
<source protocol="nbd">
<host name="foo.bar.com"/>
</source>
<target bus="virtio" dev="/dev/vda"/>
</disk>""")

def test_config_network_multihost(self):
obj = config.LibvirtConfigGuestDisk()
obj.source_type = 'network'
obj.source_protocol = 'rbd'
obj.source_name = 'pool/image'
obj.source_hosts = ['foo.bar.com', '::1', '1.2.3.4']
obj.source_ports = [None, '123', '456']
obj.driver_name = 'qemu'
obj.driver_format = 'raw'
obj.target_dev = '/dev/vda'
obj.target_bus = 'virtio'

xml = obj.to_xml()
self.assertXmlEqual(xml, """
<disk type="network" device="disk">
<driver name="qemu" type="raw"/>
<source name="pool/image" protocol="rbd">
<host name="foo.bar.com"/>
<host name="::1" port="123"/>
<host name="1.2.3.4" port="456"/>
</source>
<target bus="virtio" dev="/dev/vda"/>
</disk>""")

def test_config_network_auth(self):
obj = config.LibvirtConfigGuestDisk()
obj.source_type = "network"
obj.source_protocol = "rbd"
obj.source_host = "pool/image"
obj.source_name = "pool/image"
obj.driver_name = "qemu"
obj.driver_format = "raw"
obj.target_dev = "/dev/vda"
Expand Down
26 changes: 26 additions & 0 deletions nova/tests/virt/libvirt/test_libvirt_volume.py
Expand Up @@ -218,6 +218,32 @@ def test_libvirt_rbd_driver(self):
self.assertEqual(tree.find('./source/auth'), None)
libvirt_driver.disconnect_volume(connection_info, "vde")

def test_libvirt_rbd_driver_hosts(self):
libvirt_driver = volume.LibvirtNetVolumeDriver(self.fake_conn)
name = 'volume-00000001'
vol = {'id': 1, 'name': name}
connection_info = self.rbd_connection(vol)
disk_info = {
"bus": "virtio",
"dev": "vde",
"type": "disk",
}
hosts = ['example.com', '1.2.3.4', '::1']
ports = [None, '6790', '6791']
connection_info['data']['hosts'] = hosts
connection_info['data']['ports'] = ports
conf = libvirt_driver.connect_volume(connection_info, disk_info)
tree = conf.format_dom()
self.assertEqual(tree.get('type'), 'network')
self.assertEqual(tree.find('./source').get('protocol'), 'rbd')
rbd_name = '%s/%s' % ('rbd', name)
self.assertEqual(tree.find('./source').get('name'), rbd_name)
self.assertEqual(tree.find('./source/auth'), None)
found_hosts = tree.findall('./source/host')
self.assertEqual([host.get('name') for host in found_hosts], hosts)
self.assertEqual([host.get('port') for host in found_hosts], ports)
libvirt_driver.disconnect_volume(connection_info, "vde")

def test_libvirt_rbd_driver_auth_enabled(self):
libvirt_driver = volume.LibvirtNetVolumeDriver(self.fake_conn)
name = 'volume-00000001'
Expand Down
16 changes: 13 additions & 3 deletions nova/virt/libvirt/config.py
Expand Up @@ -460,7 +460,9 @@ def __init__(self, **kwargs):
self.driver_cache = None
self.source_path = None
self.source_protocol = None
self.source_host = None
self.source_name = None
self.source_hosts = []
self.source_ports = []
self.target_dev = None
self.target_path = None
self.target_bus = None
Expand Down Expand Up @@ -499,8 +501,16 @@ def format_dom(self):
elif self.source_type == "mount":
dev.append(etree.Element("source", dir=self.source_path))
elif self.source_type == "network":
dev.append(etree.Element("source", protocol=self.source_protocol,
name=self.source_host))
source = etree.Element("source", protocol=self.source_protocol)
if self.source_name is not None:
source.set('name', self.source_name)
hosts_info = zip(self.source_hosts, self.source_ports)
for name, port in hosts_info:
host = etree.Element('host', name=name)
if port is not None:
host.set('port', port)
source.append(host)
dev.append(source)

if self.auth_secret_type is not None:
auth = etree.Element("auth")
Expand Down
8 changes: 5 additions & 3 deletions nova/virt/libvirt/volume.py
Expand Up @@ -131,7 +131,7 @@ def connect_volume(self, connection_info, disk_info):
disk_info)
conf.source_type = "network"
conf.source_protocol = "fake"
conf.source_host = "fake"
conf.source_name = "fake"
return conf


Expand All @@ -145,10 +145,12 @@ def connect_volume(self, connection_info, disk_info):
conf = super(LibvirtNetVolumeDriver,
self).connect_volume(connection_info,
disk_info)
netdisk_properties = connection_info['data']
conf.source_type = "network"
conf.source_protocol = connection_info['driver_volume_type']
conf.source_host = connection_info['data']['name']
netdisk_properties = connection_info['data']
conf.source_name = netdisk_properties.get('name')
conf.source_hosts = netdisk_properties.get('hosts', [])
conf.source_ports = netdisk_properties.get('ports', [])
auth_enabled = netdisk_properties.get('auth_enabled')
if (conf.source_protocol == 'rbd' and
CONF.rbd_secret_uuid):
Expand Down

0 comments on commit 4d99a34

Please sign in to comment.