From ca9428037a33cf970d4d0c229121ee526614885a Mon Sep 17 00:00:00 2001 From: Rongze Zhu Date: Tue, 11 Sep 2012 07:53:35 +0000 Subject: Add 'detaching' to volume status Fixes bug #1004382 When attach a volume , the volume status is "available -> attaching -> in-use", But when detaching a volume , the volume status is "in-use -> available". So We need 'detaching' volume status, it make the change of state of the volume more clearly. Change-Id: I544220c206899307294d50e26679f5351fdc0cd7 --- nova/compute/api.py | 1 + nova/compute/manager.py | 14 +++++++++++--- nova/tests/fake_volume.py | 10 ++++++++++ nova/tests/policy.json | 2 ++ nova/tests/test_volume.py | 11 +++++++++++ nova/volume/api.py | 11 +++++++++++ nova/volume/cinder.py | 6 ++++++ 7 files changed, 52 insertions(+), 3 deletions(-) diff --git a/nova/compute/api.py b/nova/compute/api.py index 95ad4b7d0..d3b07c2e0 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -1842,6 +1842,7 @@ class API(base.Base): volume = self.volume_api.get(context, volume_id) self.volume_api.check_detach(context, volume) + self.volume_api.begin_detaching(context, volume) self.compute_rpcapi.detach_volume(context, instance=instance, volume_id=volume_id) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 9fc3104d0..94d9a8344 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -1970,9 +1970,17 @@ class ComputeManager(manager.SchedulerDependentManager): # but added for completeness in case we ever do. if connection_info and 'serial' not in connection_info: connection_info['serial'] = volume_id - self.driver.detach_volume(connection_info, - instance['name'], - mp) + try: + self.driver.detach_volume(connection_info, + instance['name'], + mp) + except Exception: # pylint: disable=W0702 + with excutils.save_and_reraise_exception(): + msg = _("Faild to detach volume %(volume_id)s from %(mp)s") + LOG.exception(msg % locals(), context=context, + instance=instance) + volume = self.volume_api.get(context, volume_id) + self.volume_api.roll_detaching(context, volume) @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) @reverts_task_state diff --git a/nova/tests/fake_volume.py b/nova/tests/fake_volume.py index 040897582..8093ff06f 100644 --- a/nova/tests/fake_volume.py +++ b/nova/tests/fake_volume.py @@ -258,3 +258,13 @@ class API(object): LOG.info('unreserving volume %s', volume['id']) volume = self.get(context, volume['id']) volume['status'] = 'available' + + def begin_detaching(self, context, volume): + LOG.info('beging detaching volume %s', volume['id']) + volume = self.get(context, volume['id']) + volume['status'] = 'detaching' + + def roll_detaching(self, context, volume): + LOG.info('roll detaching volume %s', volume['id']) + volume = self.get(context, volume['id']) + volume['status'] = 'in-use' diff --git a/nova/tests/policy.json b/nova/tests/policy.json index 073ba4142..d735f6b86 100644 --- a/nova/tests/policy.json +++ b/nova/tests/policy.json @@ -137,6 +137,8 @@ "volume:detach": [], "volume:reserve_volume": [], "volume:unreserve_volume": [], + "volume:begin_detaching": [], + "volume:roll_detaching": [], "volume:check_attach": [], "volume:check_detach": [], "volume:initialize_connection": [], diff --git a/nova/tests/test_volume.py b/nova/tests/test_volume.py index 0752d2b9b..5bd510406 100644 --- a/nova/tests/test_volume.py +++ b/nova/tests/test_volume.py @@ -490,6 +490,17 @@ class VolumeTestCase(test.TestCase): 'name', 'description') + def test_begin_roll_detaching_volume(self): + """Test begin_detaching and roll_detaching functions.""" + volume = self._create_volume() + volume_api = nova.volume.api.API() + volume_api.begin_detaching(self.context, volume) + volume = db.volume_get(self.context, volume['id']) + self.assertEqual(volume['status'], "detaching") + volume_api.roll_detaching(self.context, volume) + volume = db.volume_get(self.context, volume['id']) + self.assertEqual(volume['status'], "in-use") + class DriverTestCase(test.TestCase): """Base Test class for Drivers.""" diff --git a/nova/volume/api.py b/nova/volume/api.py index 3b8c62e11..eb03b94c3 100644 --- a/nova/volume/api.py +++ b/nova/volume/api.py @@ -303,6 +303,17 @@ class API(base.Base): volume['id'], {"status": "available"}) + @wrap_check_policy + def begin_detaching(self, context, volume): + self.db.volume_update(context, volume['id'], {"status": "detaching"}) + + @wrap_check_policy + def roll_detaching(self, context, volume): + if volume['status'] == "detaching": + self.db.volume_update(context, + volume['id'], + {"status": "in-use"}) + @wrap_check_policy def attach(self, context, volume, instance_uuid, mountpoint): host = volume['host'] diff --git a/nova/volume/cinder.py b/nova/volume/cinder.py index 9d5222c03..87b8036a1 100644 --- a/nova/volume/cinder.py +++ b/nova/volume/cinder.py @@ -165,6 +165,12 @@ class API(base.Base): def unreserve_volume(self, context, volume): cinderclient(context).volumes.unreserve(volume['id']) + def begin_detaching(self, context, volume): + cinderclient(context).volumes.begin_detaching(volume['id']) + + def roll_detaching(self, context, volume): + cinderclient(context).volumes.roll_detaching(volume['id']) + def attach(self, context, volume, instance_uuid, mountpoint): cinderclient(context).volumes.attach(volume['id'], instance_uuid, -- cgit