]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Add create & attach times to SolidFire attributes.
authorJohn Griffith <john.griffith@solidfire.com>
Fri, 19 Jul 2013 23:05:55 +0000 (17:05 -0600)
committerJohn Griffith <john.griffith@solidfire.com>
Mon, 22 Jul 2013 15:06:00 +0000 (09:06 -0600)
This change simply adds create_time and attach_time to
the SolidFire devices attributes.

Times are taken from the volume-ref object, attach_time
is only set/present after an attach, and is also removed
from the attributes list on a detach.

This also required that we actually set attach_time on the
volume in the db.  We have the column, but we weren't actually
setting it, so this change required that be fixed.

In the future we should also look at changing the attach_time
from a string to a proper date-time object.

Change-Id: Ib9577ac160596a6878d1729f6022885b6cfa90e2

cinder/db/sqlalchemy/api.py
cinder/tests/test_solidfire.py
cinder/volume/driver.py
cinder/volume/drivers/scality.py
cinder/volume/drivers/solidfire.py
cinder/volume/manager.py

index a2e4bf814d9667dcc42acdfe5bfc431e7fb62842..25fb2ae9715dac3bce727ff654dbd0cb08b0ef91 100644 (file)
@@ -1078,6 +1078,7 @@ def volume_detached(context, volume_id):
         volume_ref['attach_status'] = 'detached'
         volume_ref['instance_uuid'] = None
         volume_ref['attached_host'] = None
+        volume_ref['attach_time'] = None
         volume_ref.save(session=session)
 
 
index f57c8515a3ffed2f9481f6d29488773acd245ac0..99094a19dd861fb2a893ada643dc6b4d72bd205c 100644 (file)
@@ -19,6 +19,7 @@ import mox
 
 from cinder import exception
 from cinder.openstack.common import log as logging
+from cinder.openstack.common import timeutils
 from cinder import test
 from cinder.volume import configuration as conf
 from cinder.volume.drivers.solidfire import SolidFireDriver
@@ -143,7 +144,8 @@ class SolidFireVolumeTestCase(test.TestCase):
                    'name': 'testvol',
                    'size': 1,
                    'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66',
-                   'volume_type_id': 'fast'}
+                   'volume_type_id': 'fast',
+                   'created_at': timeutils.utcnow()}
 
         sfv = SolidFireDriver(configuration=self.configuration)
         model_update = sfv.create_volume(testvol)
@@ -156,7 +158,9 @@ class SolidFireVolumeTestCase(test.TestCase):
                    'name': 'testvol',
                    'size': 1,
                    'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66',
-                   'volume_type_id': None}
+                   'volume_type_id': None,
+                   'created_at': timeutils.utcnow()}
+
         sfv = SolidFireDriver(configuration=self.configuration)
         model_update = sfv.create_volume(testvol)
         self.assertNotEqual(model_update, None)
@@ -169,7 +173,9 @@ class SolidFireVolumeTestCase(test.TestCase):
                    'name': 'testvol',
                    'size': 1,
                    'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66',
-                   'volume_type_id': None}
+                   'volume_type_id': None,
+                   'created_at': timeutils.utcnow()}
+
         self.configuration.sf_emulate_512 = False
         sfv = SolidFireDriver(configuration=self.configuration)
         model_update = sfv.create_volume(testvol)
@@ -189,7 +195,8 @@ class SolidFireVolumeTestCase(test.TestCase):
                                         '74-4cb7-bd55-14aed659a0cc.4060 0',
                    'provider_auth': 'CHAP stack-1-a60e2611875f40199931f2'
                                     'c76370d66b 2FE0CQ8J196R',
-                   'provider_geometry': '4096 4096'
+                   'provider_geometry': '4096 4096',
+                   'created_at': timeutils.utcnow(),
                    }
 
         sfv = SolidFireDriver(configuration=self.configuration)
@@ -208,7 +215,8 @@ class SolidFireVolumeTestCase(test.TestCase):
                    'size': 1,
                    'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66',
                    'metadata': [preset_qos],
-                   'volume_type_id': None}
+                   'volume_type_id': None,
+                   'created_at': timeutils.utcnow()}
 
         sfv = SolidFireDriver(configuration=self.configuration)
         model_update = sfv.create_volume(testvol)
@@ -224,7 +232,8 @@ class SolidFireVolumeTestCase(test.TestCase):
         testvol = {'project_id': 'testprjid',
                    'name': 'testvol',
                    'size': 1,
-                   'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
+                   'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66',
+                   'created_at': timeutils.utcnow()}
         sfv = SolidFireDriver(configuration=self.configuration)
         try:
             sfv.create_volume(testvol)
@@ -266,7 +275,9 @@ class SolidFireVolumeTestCase(test.TestCase):
         testvol = {'project_id': 'testprjid',
                    'name': 'test_volume',
                    'size': 1,
-                   'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
+                   'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66',
+                   'created_at': timeutils.utcnow()}
+
         sfv = SolidFireDriver(configuration=self.configuration)
         sfv.delete_volume(testvol)
 
@@ -276,7 +287,9 @@ class SolidFireVolumeTestCase(test.TestCase):
         testvol = {'project_id': 'testprjid',
                    'name': 'no-name',
                    'size': 1,
-                   'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
+                   'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66',
+                   'created_at': timeutils.utcnow()}
+
         sfv = SolidFireDriver(configuration=self.configuration)
         try:
             sfv.delete_volume(testvol)
@@ -294,7 +307,9 @@ class SolidFireVolumeTestCase(test.TestCase):
         testvol = {'project_id': 'testprjid',
                    'name': 'no-name',
                    'size': 1,
-                   'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
+                   'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66',
+                   'created_at': timeutils.utcnow()}
+
         sfv = SolidFireDriver(configuration=self.configuration)
         self.assertRaises(exception.SfAccountNotFound,
                           sfv.delete_volume,
@@ -323,7 +338,9 @@ class SolidFireVolumeTestCase(test.TestCase):
         testvol = {'project_id': 'testprjid',
                    'name': 'test_volume',
                    'size': 1,
-                   'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
+                   'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66',
+                   'created_at': timeutils.utcnow()}
+
         sfv = SolidFireDriver(configuration=self.configuration)
         sfv.extend_volume(testvol, 2)
 
@@ -349,7 +366,9 @@ class SolidFireVolumeTestCase(test.TestCase):
         testvol = {'project_id': 'testprjid',
                    'name': 'no-name',
                    'size': 1,
-                   'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
+                   'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66',
+                   'created_at': timeutils.utcnow()}
+
         sfv = SolidFireDriver(configuration=self.configuration)
         self.assertRaises(exception.SfAccountNotFound,
                           sfv.extend_volume,
index bb088573da049554ad09197c9f5dd3402121ed94..d00c900048413c32d633fed5c81d3f480bbd2726 100644 (file)
@@ -167,12 +167,12 @@ class VolumeDriver(object):
         """Disallow connection from connector"""
         raise NotImplementedError()
 
-    def attach_volume(self, context, volume_id, instance_uuid, host_name,
+    def attach_volume(self, context, volume, instance_uuid, host_name,
                       mountpoint):
         """Callback for volume attached to instance or host."""
         pass
 
-    def detach_volume(self, context, volume_id):
+    def detach_volume(self, context, volume):
         """Callback for volume detached."""
         pass
 
index 3a6a498134840a37c0b25d3e539263b277d91c71..abf2fcda54344ec1ac78feaaf685018384221a68 100644 (file)
@@ -210,7 +210,7 @@ class ScalityDriver(driver.VolumeDriver):
         """Disallow connection from connector."""
         pass
 
-    def detach_volume(self, context, volume_id):
+    def detach_volume(self, context, volume):
         """Callback for volume detached."""
         pass
 
index 2af030c3560160375ae495ba0b3d021dc0ecb408..25e40c828a39caba48197b2c3f5a21037e549678 100644 (file)
@@ -30,6 +30,7 @@ from oslo.config import cfg
 from cinder import context
 from cinder import exception
 from cinder.openstack.common import log as logging
+from cinder.openstack.common import timeutils
 from cinder.volume.drivers.san.san import SanISCSIDriver
 from cinder.volume import volume_types
 
@@ -364,9 +365,11 @@ class SolidFireDriver(SanISCSIDriver):
         # to set any that were provided
         params = {'volumeID': sf_volume_id}
 
+        create_time = timeutils.strtime(v_ref['created_at'])
         attributes = {'uuid': v_ref['id'],
                       'is_clone': 'True',
-                      'src_uuid': src_uuid}
+                      'src_uuid': src_uuid,
+                      'created_at': create_time}
         if qos:
             params['qos'] = qos
             for k, v in qos.items():
@@ -484,8 +487,10 @@ class SolidFireDriver(SanISCSIDriver):
         if type_id is not None:
             qos = self._set_qos_by_volume_type(ctxt, type_id)
 
+        create_time = timeutils.strtime(volume['created_at'])
         attributes = {'uuid': volume['id'],
-                      'is_clone': 'False'}
+                      'is_clone': 'False',
+                      'created_at': create_time}
         if qos:
             for k, v in qos.items():
                 attributes[k] = str(v)
@@ -662,3 +667,55 @@ class SolidFireDriver(SanISCSIDriver):
         data['thin_provision_percent'] =\
             results['thinProvisioningPercent']
         self.cluster_stats = data
+
+    def attach_volume(self, context, volume,
+                      instance_uuid, host_name,
+                      mountpoint):
+
+        LOG.debug(_("Entering SolidFire attach_volume..."))
+        sfaccount = self._get_sfaccount(volume['project_id'])
+        params = {'accountID': sfaccount['accountID']}
+
+        sf_vol = self._get_sf_volume(volume['id'], params)
+        if sf_vol is None:
+            LOG.error(_("Volume ID %s was not found on "
+                        "the SolidFire Cluster!"), volume['id'])
+            raise exception.VolumeNotFound(volume_id=volume['id'])
+
+        attributes = sf_vol['attributes']
+        attributes['attach_time'] = volume.get('attach_time', None)
+        attributes['attached_to'] = instance_uuid
+        params = {
+            'volumeID': sf_vol['volumeID'],
+            'attributes': attributes
+        }
+
+        data = self._issue_api_request('ModifyVolume', params)
+
+        if 'result' not in data:
+            raise exception.SolidFireAPIDataException(data=data)
+
+    def detach_volume(self, context, volume):
+
+        LOG.debug(_("Entering SolidFire attach_volume..."))
+        sfaccount = self._get_sfaccount(volume['project_id'])
+        params = {'accountID': sfaccount['accountID']}
+
+        sf_vol = self._get_sf_volume(volume['id'], params)
+        if sf_vol is None:
+            LOG.error(_("Volume ID %s was not found on "
+                        "the SolidFire Cluster!"), volume['id'])
+            raise exception.VolumeNotFound(volume_id=volume['id'])
+
+        attributes = sf_vol['attributes']
+        attributes['attach_time'] = None
+        attributes['attached_to'] = None
+        params = {
+            'volumeID': sf_vol['volumeID'],
+            'attributes': attributes
+        }
+
+        data = self._issue_api_request('ModifyVolume', params)
+
+        if 'result' not in data:
+            raise exception.SolidFireAPIDataException(data=data)
index 6b0fb3e2225383441871279ca61cf7e96a2c77c2..798f9854645b74d0d1e148e518bc6d0802d81862 100644 (file)
@@ -371,7 +371,7 @@ class VolumeManager(manager.SchedulerDependentManager):
         self.db.volume_update(context,
                               volume_ref['id'],
                               {'status': volume_ref['status'],
-                              'launched_at': now})
+                               'launched_at': now})
         LOG.info(_("volume %s: created successfully"), volume_ref['name'])
         self._reset_stats()
 
@@ -609,10 +609,16 @@ class VolumeManager(manager.SchedulerDependentManager):
             elif volume['status'] != "available":
                 msg = _("status must be available")
                 raise exception.InvalidVolume(reason=msg)
+
+            # TODO(jdg): attach_time column is currently varchar
+            # we should update this to a date-time object
+            # also consider adding detach_time?
+            now = timeutils.strtime()
             self.db.volume_update(context, volume_id,
                                   {"instance_uuid": instance_uuid,
                                    "attached_host": host_name,
-                                   "status": "attaching"})
+                                   "status": "attaching",
+                                   "attach_time": now})
 
             if instance_uuid and not uuidutils.is_uuid_like(instance_uuid):
                 self.db.volume_update(context,
@@ -623,9 +629,10 @@ class VolumeManager(manager.SchedulerDependentManager):
             host_name_sanitized = utils.sanitize_hostname(
                 host_name) if host_name else None
 
+            volume = self.db.volume_get(context, volume_id)
             try:
                 self.driver.attach_volume(context,
-                                          volume_id,
+                                          volume,
                                           instance_uuid,
                                           host_name_sanitized,
                                           mountpoint)
@@ -646,8 +653,10 @@ class VolumeManager(manager.SchedulerDependentManager):
         """Updates db to show volume is detached"""
         # TODO(vish): refactor this into a more general "unreserve"
         # TODO(sleepsonthefloor): Is this 'elevated' appropriate?
+
+        volume = self.db.volume_get(context, volume_id)
         try:
-            self.driver.detach_volume(context, volume_id)
+            self.driver.detach_volume(context, volume)
         except Exception:
             with excutils.save_and_reraise_exception():
                 self.db.volume_update(context,
@@ -657,10 +666,10 @@ class VolumeManager(manager.SchedulerDependentManager):
         self.db.volume_detached(context.elevated(), volume_id)
 
         # Check for https://bugs.launchpad.net/cinder/+bug/1065702
-        volume_ref = self.db.volume_get(context, volume_id)
-        if (volume_ref['provider_location'] and
-                volume_ref['name'] not in volume_ref['provider_location']):
-            self.driver.ensure_export(context, volume_ref)
+        volume = self.db.volume_get(context, volume_id)
+        if (volume['provider_location'] and
+                volume['name'] not in volume['provider_location']):
+            self.driver.ensure_export(context, volume)
 
     def _copy_image_to_volume(self, context, volume, image_service, image_id):
         """Downloads Glance image to the specified volume."""