Allow unprivileged RADOS users to access rbd volumes.

This makes it possible to access rbd volumes with RADOS users with
restricted privileges. Previously, the admin user was always used.

This requires libvirt 0.9.8 or higher.

Change-Id: Ia4665c2a93a58a1c1290f467a3d9cd6cd22d7bd5
This commit is contained in:
Josh Durgin 2012-04-02 16:41:07 -07:00
parent 276716e790
commit 01f24caba8
5 changed files with 106 additions and 2 deletions

View File

@ -241,6 +241,59 @@ class LibvirtVolumeTestCase(test.TestCase):
self.assertEqual(tree.find('./source').get('protocol'), 'rbd')
rbd_name = '%s/%s' % (FLAGS.rbd_pool, name)
self.assertEqual(tree.find('./source').get('name'), rbd_name)
self.assertEqual(tree.find('./source/auth'), None)
libvirt_driver.disconnect_volume(connection_info, mount_device)
connection_info = vol_driver.terminate_connection(vol, self.connr)
def test_libvirt_rbd_driver_auth_enabled(self):
vol_driver = volume_driver.RBDDriver()
libvirt_driver = volume.LibvirtNetVolumeDriver(self.fake_conn)
name = 'volume-00000001'
vol = {'id': 1, 'name': name}
connection_info = vol_driver.initialize_connection(vol, self.connr)
uuid = '875a8070-d0b9-4949-8b31-104d125c9a64'
user = 'foo'
secret_type = 'ceph'
connection_info['data']['auth_enabled'] = True
connection_info['data']['auth_username'] = user
connection_info['data']['secret_type'] = secret_type
connection_info['data']['secret_uuid'] = uuid
mount_device = "vde"
conf = libvirt_driver.connect_volume(connection_info, mount_device)
tree = conf.format_dom()
self.assertEqual(tree.get('type'), 'network')
self.assertEqual(tree.find('./source').get('protocol'), 'rbd')
rbd_name = '%s/%s' % (FLAGS.rbd_pool, name)
self.assertEqual(tree.find('./source').get('name'), rbd_name)
self.assertEqual(tree.find('./auth').get('username'), user)
self.assertEqual(tree.find('./auth/secret').get('type'), secret_type)
self.assertEqual(tree.find('./auth/secret').get('uuid'), uuid)
libvirt_driver.disconnect_volume(connection_info, mount_device)
connection_info = vol_driver.terminate_connection(vol, self.connr)
def test_libvirt_rbd_driver_auth_disabled(self):
vol_driver = volume_driver.RBDDriver()
libvirt_driver = volume.LibvirtNetVolumeDriver(self.fake_conn)
name = 'volume-00000001'
vol = {'id': 1, 'name': name}
connection_info = vol_driver.initialize_connection(vol, self.connr)
uuid = '875a8070-d0b9-4949-8b31-104d125c9a64'
user = 'foo'
secret_type = 'ceph'
connection_info['data']['auth_enabled'] = False
connection_info['data']['auth_username'] = user
connection_info['data']['secret_type'] = secret_type
connection_info['data']['secret_uuid'] = uuid
mount_device = "vde"
conf = libvirt_driver.connect_volume(connection_info, mount_device)
tree = conf.format_dom()
self.assertEqual(tree.get('type'), 'network')
self.assertEqual(tree.find('./source').get('protocol'), 'rbd')
rbd_name = '%s/%s' % (FLAGS.rbd_pool, name)
self.assertEqual(tree.find('./source').get('name'), rbd_name)
self.assertEqual(tree.find('./auth'), None)
libvirt_driver.disconnect_volume(connection_info, mount_device)
connection_info = vol_driver.terminate_connection(vol, self.connr)

View File

@ -105,6 +105,31 @@ class LibvirtConfigGuestDiskTest(LibvirtConfigBaseTest):
<target bus="ide" dev="/dev/hda"/>
</disk>""")
def test_config_network_auth(self):
obj = config.LibvirtConfigGuestDisk()
obj.source_type = "network"
obj.source_protocol = "rbd"
obj.source_host = "pool/image"
obj.driver_name = "qemu"
obj.driver_format = "raw"
obj.target_dev = "/dev/vda"
obj.target_bus = "virtio"
obj.auth_username = "foo"
obj.auth_secret_type = "ceph"
obj.auth_secret_uuid = "b38a3f43-4be2-4046-897f-b67c2f5e0147"
xml = obj.to_xml()
self.assertXmlEqual(xml, """
<disk type="network" device="disk">
<driver name="qemu" type="raw"/>
<source protocol="rbd" name="pool/image"/>
<auth username="foo">
<secret type="ceph"
uuid="b38a3f43-4be2-4046-897f-b67c2f5e0147"/>
</auth>
<target bus="virtio" dev="/dev/vda"/>
</disk>""")
class LibvirtConfigGuestFilesysTest(LibvirtConfigBaseTest):

View File

@ -86,6 +86,9 @@ class LibvirtConfigGuestDisk(LibvirtConfigGuestDevice):
self.target_dev = None
self.target_path = None
self.target_bus = None
self.auth_username = None
self.auth_secret_type = None
self.auth_secret_uuid = None
def format_dom(self):
dev = super(LibvirtConfigGuestDisk, self).format_dom()
@ -114,6 +117,13 @@ class LibvirtConfigGuestDisk(LibvirtConfigGuestDevice):
dev.append(etree.Element("source", protocol=self.source_protocol,
name=self.source_host))
if self.auth_secret_type is not None:
auth = etree.Element("auth")
auth.set("username", self.auth_username)
auth.append(etree.Element("secret", type=self.auth_secret_type,
uuid=self.auth_secret_uuid))
dev.append(auth)
if self.source_type == "mount":
dev.append(etree.Element("target", dir=self.target_path))
else:

View File

@ -86,6 +86,11 @@ class LibvirtNetVolumeDriver(LibvirtVolumeDriver):
conf.source_host = connection_info['data']['name']
conf.target_dev = mount_device
conf.target_bus = "virtio"
netdisk_properties = connection_info['data']
if netdisk_properties.get('auth_enabled'):
conf.auth_username = netdisk_properties['auth_username']
conf.auth_secret_type = netdisk_properties['secret_type']
conf.auth_secret_uuid = netdisk_properties['secret_uuid']
return conf

View File

@ -56,7 +56,14 @@ volume_opts = [
help='The port that the iSCSI daemon is listening on'),
cfg.StrOpt('rbd_pool',
default='rbd',
help='the rbd pool in which volumes are stored'),
help='the RADOS pool in which rbd volumes are stored'),
cfg.StrOpt('rbd_user',
default=None,
help='the RADOS client name for accessing rbd volumes'),
cfg.StrOpt('rbd_secret_uuid',
default=None,
help='the libvirt uuid of the secret for the rbd_user'
'volumes'),
]
FLAGS = flags.FLAGS
@ -546,7 +553,11 @@ class RBDDriver(VolumeDriver):
return {
'driver_volume_type': 'rbd',
'data': {
'name': '%s/%s' % (FLAGS.rbd_pool, volume['name'])
'name': '%s/%s' % (FLAGS.rbd_pool, volume['name']),
'auth_enabled': FLAGS.rbd_secret_uuid is not None,
'auth_username': FLAGS.rbd_user,
'secret_type': 'ceph',
'secret_uuid': FLAGS.rbd_secret_uuid,
}
}