]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
GPFS support for various volume attributes
authorDinesh Subhraveti <dineshs@us.ibm.com>
Thu, 8 Aug 2013 21:24:40 +0000 (14:24 -0700)
committerDinesh Subhraveti <dineshs@us.ibm.com>
Fri, 9 Aug 2013 20:24:12 +0000 (13:24 -0700)
Specify the following attributes when creating a new volume:

* The storage pool on which the volume is placed
* Number of block-level replicas
* Whether the physical blocks should be allocated locally on the node issuing
  the IO or striped across the cluster
* Whether writes to the volume should use direct IO
* Number of file system blocks to be laid out sequentially on disk to behave
  like a single large block
* Local storage attached to specific node(s) where the replicas of the
  volume should be allocated

Change-Id: I77bb7de32bbde5a125f8c6f9a727b538ea99bc18
Implements: blueprint gpfs-volume-attributes

cinder/tests/test_gpfs.py
cinder/volume/drivers/gpfs.py
etc/cinder/rootwrap.d/volume.filters

index 171649e8b254ca8fc184077ed37068693fe6119a..bae51bff72eef4846883c366f095719ccc8a3061 100644 (file)
@@ -92,8 +92,8 @@ class GPFSDriverTestCase(test.TestCase):
                        self._fake_delete_gpfs_file)
         self.stubs.Set(GPFSDriver, '_create_sparse_file',
                        self._fake_create_sparse_file)
-        self.stubs.Set(GPFSDriver, '_create_regular_file',
-                       self._fake_create_regular_file)
+        self.stubs.Set(GPFSDriver, '_allocate_file_blocks',
+                       self._fake_allocate_file_blocks)
         self.stubs.Set(GPFSDriver, '_get_available_capacity',
                        self._fake_get_available_capacity)
         self.stubs.Set(image_utils, 'qemu_img_info',
@@ -153,6 +153,23 @@ class GPFSDriverTestCase(test.TestCase):
         self.volume.delete_volume(self.context, volume_id)
         self.assertFalse(os.path.exists(path))
 
+    def test_create_volume_with_attributes(self):
+        self.stubs.Set(GPFSDriver, '_gpfs_change_attributes',
+                       self._fake_gpfs_change_attributes)
+        attributes = {'dio': 'yes', 'data_pool_name': 'ssd_pool',
+                      'replicas': '2', 'write_affinity_depth': '1',
+                      'block_group_factor': '1',
+                      'write_affinity_failure-group':
+                      '1,1,1:2;2,1,1:2;2,0,3:4'}
+        vol = self._create_volume(size=1, metadata=attributes)
+        volume_id = vol['id']
+        self.assertTrue(os.path.exists(self.volumes_path))
+        self.volume.create_volume(self.context, volume_id)
+        path = self.volumes_path + '/' + vol['name']
+        self.assertTrue(os.path.exists(path))
+        self.volume.delete_volume(self.context, volume_id)
+        self.assertFalse(os.path.exists(path))
+
     def _create_snapshot(self, volume_id, size='0'):
         """Create a snapshot object."""
         snap = {}
@@ -405,9 +422,12 @@ class GPFSDriverTestCase(test.TestCase):
     def _fake_create_sparse_file(self, path, size):
         self._fake_create_file(path)
 
-    def _fake_create_regular_file(self, path, size):
+    def _fake_allocate_file_blocks(self, path, size):
         self._fake_create_file(path)
 
+    def _fake_gpfs_change_attributes(self, options, path):
+        pass
+
     def _fake_gpfs_redirect(self, src):
         return True
 
index fe4577ce487606044293adcb85b62209831057a0..556f5cb1e5f44ca17d8db6f3f6cec6d05dd8d4c3 100644 (file)
@@ -211,8 +211,8 @@ class GPFSDriver(driver.VolumeDriver):
         self._execute('truncate', '-s', sizestr, path, run_as_root=True)
         self._execute('chmod', '666', path, run_as_root=True)
 
-    def _create_regular_file(self, path, size):
-        """Creates regular file of given size."""
+    def _allocate_file_blocks(self, path, size):
+        """Preallocate file blocks by writing zeros."""
 
         block_size_mb = 1
         block_count = size * units.GiB / (block_size_mb * units.MiB)
@@ -221,19 +221,51 @@ class GPFSDriver(driver.VolumeDriver):
                       'bs=%dM' % block_size_mb,
                       'count=%d' % block_count,
                       run_as_root=True)
-        self._execute('chmod', '666', path, run_as_root=True)
+
+    def _gpfs_change_attributes(self, options, path):
+        cmd = ['mmchattr']
+        cmd.extend(options)
+        cmd.append(path)
+        self._execute(*cmd, run_as_root=True)
+
+    def _set_volume_attributes(self, path, metadata):
+        """Set various GPFS attributes for this volume."""
+
+        options = []
+        for item in metadata:
+            if item['key'] == 'data_pool_name':
+                options.extend(['-P', item['value']])
+            elif item['key'] == 'replicas':
+                options.extend(['-r', item['value'], '-m', item['value']])
+            elif item['key'] == 'dio':
+                options.extend(['-D', item['value']])
+            elif item['key'] == 'write_affinity_depth':
+                options.extend(['--write-affinity-depth', item['value']])
+            elif item['key'] == 'block_group_factor':
+                options.extend(['--block-group-factor', item['value']])
+            elif item['key'] == 'write_affinity_failure_group':
+                options.extend(['--write-affinity-failure-group',
+                               item['value']])
+
+        if options:
+            self._gpfs_change_attributes(options, path)
 
     def create_volume(self, volume):
         """Creates a GPFS volume."""
         volume_path = self.local_path(volume)
         volume_size = volume['size']
 
-        if self.configuration.gpfs_sparse_volumes:
-            self._create_sparse_file(volume_path, volume_size)
-        else:
-            self._create_regular_file(volume_path, volume_size)
+        # Create a sparse file first; allocate blocks later if requested
+        self._create_sparse_file(volume_path, volume_size)
 
+        # Set the attributes prior to allocating any blocks so that
+        # they are allocated according to the policy
         v_metadata = volume.get('volume_metadata')
+        self._set_volume_attributes(volume_path, v_metadata)
+
+        if not self.configuration.gpfs_sparse_volumes:
+            self._allocate_file_blocks(volume_path, volume_size)
+
         fstype = None
         fslabel = None
         for item in v_metadata:
index b095475b9b12cb217e6dea95b148ca53c3fc2514..68109dd09bdc141ba182ff283dbfe86ed8598ac3 100644 (file)
@@ -73,6 +73,7 @@ blockdev: CommandFilter, blockdev, root
 mmgetstate: CommandFilter, /usr/lpp/mmfs/bin/mmgetstate, root
 mmclone: CommandFilter, /usr/lpp/mmfs/bin/mmclone, root
 mmlsattr: CommandFilter, /usr/lpp/mmfs/bin/mmlsattr, root
+mmchattr: CommandFilter, /usr/lpp/mmfs/bin/mmchattr, root
 mmlsconfig: CommandFilter, /usr/lpp/mmfs/bin/mmlsconfig, root
 mmlsfs: CommandFilter, /usr/lpp/mmfs/bin/mmlsfs, root
 find: CommandFilter, find, root