From 99456bd690445443ae05c0d4fe1ec43ba6090f6f Mon Sep 17 00:00:00 2001 From: ZhuRongze Date: Fri, 13 Jul 2012 12:07:13 +0000 Subject: [PATCH] Send 'create volume from snapshot' to the proper host A simple solution for bug 1008866. When creating volume from snapshot on multicluster, in volume it will check if snapshot_id is set. If snapshot_id is set, make the call create volume directly to the volume host where the snapshot resides instead of passing it through the scheduler. So snapshot can be copy to new volume. Change-Id: Ie9c1a77f62abc40e294b1d0c604cf885652728da --- cinder/volume/api.py | 40 +++++++++++++++++++++++++++++------ etc/cinder/cinder.conf.sample | 5 +++++ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/cinder/volume/api.py b/cinder/volume/api.py index 614b39d816..9784d8719d 100644 --- a/cinder/volume/api.py +++ b/cinder/volume/api.py @@ -26,6 +26,7 @@ from cinder import exception from cinder import flags +from cinder.openstack.common import cfg from cinder.openstack.common import log as logging from cinder.openstack.common import rpc import cinder.policy @@ -34,7 +35,12 @@ from cinder import utils from cinder.db import base +volume_host_opt = cfg.BoolOpt('snapshot_same_host', + default=True, + help='Create volume from snapshot at the host where snapshot resides') + FLAGS = flags.FLAGS +FLAGS.register_opt(volume_host_opt) flags.DECLARE('storage_availability_zone', 'cinder.volume.manager') LOG = logging.getLogger(__name__) @@ -113,14 +119,36 @@ def create(self, context, size, name, description, snapshot=None, } volume = self.db.volume_create(context, options) - rpc.cast(context, - FLAGS.scheduler_topic, - {"method": "create_volume", - "args": {"topic": FLAGS.volume_topic, - "volume_id": volume['id'], - "snapshot_id": snapshot_id}}) + self._cast_create_volume(context, volume['id'], snapshot_id) return volume + def _cast_create_volume(self, context, volume_id, snapshot_id): + + # NOTE(Rongze Zhu): It is a simple solution for bug 1008866 + # If snapshot_id is set, make the call create volume directly to + # the volume host where the snapshot resides instead of passing it + # through the scheduer. So snapshot can be copy to new volume. + + if snapshot_id and FLAGS.snapshot_same_host: + snapshot_ref = self.db.snapshot_get(context, snapshot_id) + src_volume_ref = self.db.volume_get(context, + snapshot_ref['volume_id']) + topic = rpc.queue_get_for(context, + FLAGS.volume_topic, + src_volume_ref['host']) + rpc.cast(context, + topic, + {"method": "create_volume", + "args": {"volume_id": volume_id, + "snapshot_id": snapshot_id}}) + else: + rpc.cast(context, + FLAGS.scheduler_topic, + {"method": "create_volume", + "args": {"topic": FLAGS.volume_topic, + "volume_id": volume_id, + "snapshot_id": snapshot_id}}) + # TODO(yamahata): eliminate dumb polling def wait_creation(self, context, volume): volume_id = volume['id'] diff --git a/etc/cinder/cinder.conf.sample b/etc/cinder/cinder.conf.sample index ee97e65039..3491e9375c 100644 --- a/etc/cinder/cinder.conf.sample +++ b/etc/cinder/cinder.conf.sample @@ -564,6 +564,11 @@ ###### (IntOpt) maximum number of volume gigabytes to allow per host # max_gigabytes=10000 +######## defined in cinder.volume.api ######## + +# snapshot_same_host=true +#### (BoolOpt) Create volume form snapshot at the host where snapshot resides. + ######### defined in cinder.volume.driver ######### ###### (StrOpt) iscsi target user-land tool to use