From a073e6eab677d8903bd35f94e5e8ebce9d392c2d Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Mon, 3 Jan 2011 16:05:55 -0800 Subject: Add support for rbd volumes. --- nova/virt/libvirt_conn.py | 23 ++++++++++++++----- nova/volume/driver.py | 56 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index 00edfbdc8..b515e53d7 100644 --- a/nova/virt/libvirt_conn.py +++ b/nova/virt/libvirt_conn.py @@ -223,11 +223,24 @@ class LibvirtConnection(object): def attach_volume(self, instance_name, device_path, mountpoint): virt_dom = self._conn.lookupByName(instance_name) mount_device = mountpoint.rpartition("/")[2] - xml = """ - - - - """ % (device_path, mount_device) + if device_path.startswith('/dev/'): + xml = """ + + + + """ % (device_path, mount_device) + elif ':' in device_path: + (protocol, name) = device_path.split(':') + xml = """ + + + + """ % (protocol, + name, + mount_device) + else: + raise exception.Invalid(_("Invalid device path %s") % device_path) + virt_dom.attachDevice(xml) def _get_disk_xml(self, xml, device): diff --git a/nova/volume/driver.py b/nova/volume/driver.py index 8353b9712..fa914f662 100644 --- a/nova/volume/driver.py +++ b/nova/volume/driver.py @@ -49,6 +49,8 @@ flags.DEFINE_string('iscsi_target_prefix', 'iqn.2010-10.org.openstack:', 'prefix for iscsi volumes') flags.DEFINE_string('iscsi_ip_prefix', '127.0', 'discover volumes on the ip that starts with this prefix') +flags.DEFINE_string('rbd_pool', 'rbd', + 'the rbd pool in which volumes are stored') class VolumeDriver(object): @@ -312,3 +314,57 @@ class FakeISCSIDriver(ISCSIDriver): """Execute that simply logs the command.""" logging.debug(_("FAKE ISCSI: %s"), cmd) return (None, None) + + +class RBDDriver(VolumeDriver): + """Implements RADOS block device (RBD) volume commands""" + + def check_for_setup_error(self): + """Returns an error if prerequisites aren't met""" + (stdout, stderr) = self._execute("rados lspools") + if stdout.find(FLAGS.rbd_pool + "\n") == -1: + raise exception.Error(_("rbd has no pool %s") % + FLAGS.rbd_pool) + + def create_volume(self, volume): + """Creates a logical volume.""" + if int(volume['size']) == 0: + size = 100 + else: + size = int(volume['size']) * 1024 + self._try_execute("rbd --pool %s --size %d create %s" % + (FLAGS.rbd_pool, + size, + volume['name'])) + + def delete_volume(self, volume): + """Deletes a logical volume.""" + self._try_execute("rbd --pool %s rm %s" % + (FLAGS.rbd_pool, + volume['name'])) + + def local_path(self, volume): + """Returns the path of the rbd volume.""" + # This is the same as the remote path + # since qemu accesses it directly. + return self.discover_volume(volume) + + def ensure_export(self, context, volume): + """Synchronously recreates an export for a logical volume.""" + pass + + def create_export(self, context, volume): + """Exports the volume""" + pass + + def remove_export(self, context, volume): + """Removes an export for a logical volume""" + pass + + def discover_volume(self, volume): + """Discover volume on a remote host""" + return "rbd:%s/%s" % (FLAGS.rbd_pool, volume['name']) + + def undiscover_volume(self, volume): + """Undiscover volume on a remote host""" + pass -- cgit From c93e8f5317ce0cc05e7af59b9e3dd8b8b6401b87 Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Mon, 3 Jan 2011 16:07:53 -0800 Subject: Update Authors. --- Authors | 1 + 1 file changed, 1 insertion(+) diff --git a/Authors b/Authors index 639e68a59..3f6437ee4 100644 --- a/Authors +++ b/Authors @@ -19,6 +19,7 @@ Jesse Andrews Joe Heck Joel Moore Jonathan Bryce +Josh Durgin Josh Kearney Joshua McKenty Justin Santa Barbara -- cgit From ef86d16f15276581932ab50029e895c9cbf655af Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Wed, 12 Jan 2011 12:29:28 +0100 Subject: Eagerly load fixed_ip property of instances. --- nova/db/sqlalchemy/api.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 4561fa219..cee6121a9 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -756,12 +756,14 @@ def instance_get_by_id(context, instance_id): if is_admin_context(context): result = session.query(models.Instance).\ options(joinedload('security_groups')).\ + options(joinedload('fixed_ip')).\ filter_by(id=instance_id).\ filter_by(deleted=can_read_deleted(context)).\ first() elif is_user_context(context): result = session.query(models.Instance).\ options(joinedload('security_groups')).\ + options(joinedload('fixed_ip')).\ filter_by(project_id=context.project_id).\ filter_by(id=instance_id).\ filter_by(deleted=False).\ -- cgit From c29fe496c1124369a8b9b77aeee84e8296f964f9 Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Wed, 12 Jan 2011 11:28:05 -0600 Subject: fixed pause and resume --- nova/virt/xenapi/vmops.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index e20930fe8..5ca127f36 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -252,7 +252,7 @@ class VMOps(object): raise Exception(_("suspend: instance not present %s") % instance_name) task = self._session.call_xenapi('Async.VM.suspend', vm) - self._wait_with_callback(task, callback) + self._wait_with_callback(instance.id, task, callback) def resume(self, instance, callback): """resume the specified instance""" @@ -262,7 +262,7 @@ class VMOps(object): raise Exception(_("resume: instance not present %s") % instance_name) task = self._session.call_xenapi('Async.VM.resume', vm, False, True) - self._wait_with_callback(task, callback) + self._wait_with_callback(instance.id, task, callback) def get_info(self, instance_id): """Return data about VM instance""" -- cgit From 3e9d08bded2f504a5dd03712c82e981f73ae16ed Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Wed, 12 Jan 2011 14:16:51 -0400 Subject: change novarc template from cc_port to osapi_port. Removed osapi_port from bin scripts. --- bin/nova-api | 1 - bin/nova-combined | 1 - nova/auth/manager.py | 2 +- nova/flags.py | 1 + 4 files changed, 2 insertions(+), 3 deletions(-) diff --git a/bin/nova-api b/bin/nova-api index 1c671201e..c7cbb3ab4 100755 --- a/bin/nova-api +++ b/bin/nova-api @@ -41,7 +41,6 @@ from nova import wsgi FLAGS = flags.FLAGS -flags.DEFINE_integer('osapi_port', 8774, 'OpenStack API port') flags.DEFINE_string('osapi_host', '0.0.0.0', 'OpenStack API host') flags.DEFINE_integer('ec2api_port', 8773, 'EC2 API port') flags.DEFINE_string('ec2api_host', '0.0.0.0', 'EC2 API host') diff --git a/bin/nova-combined b/bin/nova-combined index 53322f1a0..f932fdfd5 100755 --- a/bin/nova-combined +++ b/bin/nova-combined @@ -44,7 +44,6 @@ from nova import wsgi FLAGS = flags.FLAGS -flags.DEFINE_integer('osapi_port', 8774, 'OpenStack API port') flags.DEFINE_string('osapi_host', '0.0.0.0', 'OpenStack API host') flags.DEFINE_integer('ec2api_port', 8773, 'EC2 API port') flags.DEFINE_string('ec2api_host', '0.0.0.0', 'EC2 API host') diff --git a/nova/auth/manager.py b/nova/auth/manager.py index 89f02998d..6fb9b522f 100644 --- a/nova/auth/manager.py +++ b/nova/auth/manager.py @@ -747,7 +747,7 @@ class AuthManager(object): 's3': 'http://%s:%s' % (s3_host, FLAGS.s3_port), 'os': '%s://%s:%s%s' % (FLAGS.os_prefix, cc_host, - FLAGS.cc_port, + FLAGS.osapi_port, FLAGS.os_suffix), 'user': user.name, 'nova': FLAGS.ca_file, diff --git a/nova/flags.py b/nova/flags.py index fdcba6c72..ef66c3f3a 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -259,6 +259,7 @@ DEFINE_string('os_prefix', 'http', 'prefix for openstack') DEFINE_string('cc_host', '$my_ip', 'ip of api server') DEFINE_string('cc_dmz', '$my_ip', 'internal ip of api server') DEFINE_integer('cc_port', 8773, 'cloud controller port') +DEFINE_integer('osapi_port', 8774, 'OpenStack API port') DEFINE_string('ec2_suffix', '/services/Cloud', 'suffix for ec2') DEFINE_string('os_suffix', '/v1.0/', 'suffix for openstack') -- cgit From 70ac0dfea7a55c3580d4a9cd65752f894dfaa222 Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Wed, 12 Jan 2011 10:17:48 -0800 Subject: Check for whole pool name in check_for_setup_error --- nova/volume/driver.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nova/volume/driver.py b/nova/volume/driver.py index fa914f662..609a00310 100644 --- a/nova/volume/driver.py +++ b/nova/volume/driver.py @@ -322,7 +322,8 @@ class RBDDriver(VolumeDriver): def check_for_setup_error(self): """Returns an error if prerequisites aren't met""" (stdout, stderr) = self._execute("rados lspools") - if stdout.find(FLAGS.rbd_pool + "\n") == -1: + pools = stdout.split("\n") + if not FLAGS.rbd_pool in pools: raise exception.Error(_("rbd has no pool %s") % FLAGS.rbd_pool) -- cgit From 982067aefcd656de7751623e272d9b6cf1447dc3 Mon Sep 17 00:00:00 2001 From: Todd Willey Date: Wed, 12 Jan 2011 15:12:08 -0500 Subject: Stop error messages for logs when running nova-manage. --- bin/nova-manage | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/nova-manage b/bin/nova-manage index 3f5957190..3e290567c 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -77,12 +77,14 @@ from nova import crypto from nova import db from nova import exception from nova import flags +from nova import log as logging from nova import quota from nova import utils from nova.auth import manager from nova.cloudpipe import pipelib +logging.basicConfig() FLAGS = flags.FLAGS flags.DECLARE('fixed_range', 'nova.network.manager') flags.DECLARE('num_networks', 'nova.network.manager') -- cgit From a58fe1849ad7473f7e437e07611aa9c9611cf5e6 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Wed, 12 Jan 2011 22:45:44 +0100 Subject: Do joinedload_all('fixed_ip.floating_ips') instead of joinedload('fixed_ip') --- nova/db/sqlalchemy/api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index cee6121a9..e00f31cbe 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -756,14 +756,14 @@ def instance_get_by_id(context, instance_id): if is_admin_context(context): result = session.query(models.Instance).\ options(joinedload('security_groups')).\ - options(joinedload('fixed_ip')).\ + options(joinedload_all('fixed_ip.floating_ips')).\ filter_by(id=instance_id).\ filter_by(deleted=can_read_deleted(context)).\ first() elif is_user_context(context): result = session.query(models.Instance).\ options(joinedload('security_groups')).\ - options(joinedload('fixed_ip')).\ + options(joinedload_all('fixed_ip.floating_ips')).\ filter_by(project_id=context.project_id).\ filter_by(id=instance_id).\ filter_by(deleted=False).\ -- cgit