Add volume attribute support to volume created using clone, snapshot
The following patch adds support for volume attributes (setting of storage pool, replicas, dio, write affinity etc) in case of volume creation triggered using snapshot, clone. Change-Id: Ia6e24cafb85c0b2996e2524b45c189fb38e83848 Closes-Bug: #1386650
This commit is contained in:
parent
a7b164865c
commit
8417b9ac0f
@ -644,8 +644,9 @@ class GPFSDriverTestCase(test.TestCase):
|
|||||||
options.extend(['-T', 'test'])
|
options.extend(['-T', 'test'])
|
||||||
self.driver._gpfs_change_attributes(options, self.images_dir)
|
self.driver._gpfs_change_attributes(options, self.images_dir)
|
||||||
|
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._mkfs')
|
||||||
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._gpfs_change_attributes')
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._gpfs_change_attributes')
|
||||||
def test_set_volume_attributes(self, mock_change_attributes):
|
def test_set_volume_attributes(self, mock_change_attributes, mock_mkfs):
|
||||||
metadata = [dict([('key', 'data_pool_name'), ('value', 'test')]),
|
metadata = [dict([('key', 'data_pool_name'), ('value', 'test')]),
|
||||||
dict([('key', 'replicas'), ('value', 'test')]),
|
dict([('key', 'replicas'), ('value', 'test')]),
|
||||||
dict([('key', 'dio'), ('value', 'test')]),
|
dict([('key', 'dio'), ('value', 'test')]),
|
||||||
@ -653,16 +654,23 @@ class GPFSDriverTestCase(test.TestCase):
|
|||||||
dict([('key', 'block_group_factor'), ('value', 'test')]),
|
dict([('key', 'block_group_factor'), ('value', 'test')]),
|
||||||
dict([('key', 'write_affinity_failure_group'),
|
dict([('key', 'write_affinity_failure_group'),
|
||||||
('value', 'test')]),
|
('value', 'test')]),
|
||||||
|
dict([('key', 'test'),
|
||||||
|
('value', 'test')]),
|
||||||
|
dict([('key', 'fstype'),
|
||||||
|
('value', 'test')]),
|
||||||
|
dict([('key', 'fslabel'),
|
||||||
|
('value', 'test')]),
|
||||||
dict([('key', 'test'),
|
dict([('key', 'test'),
|
||||||
('value', 'test')])]
|
('value', 'test')])]
|
||||||
self.driver._set_volume_attributes('', metadata)
|
|
||||||
|
self.driver._set_volume_attributes('', '', metadata)
|
||||||
|
|
||||||
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._gpfs_change_attributes')
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._gpfs_change_attributes')
|
||||||
def test_set_volume_attributes_no_attributes(self, mock_change_attributes):
|
def test_set_volume_attributes_no_attributes(self, mock_change_attributes):
|
||||||
metadata = []
|
metadata = []
|
||||||
org_value = self.driver.configuration.gpfs_storage_pool
|
org_value = self.driver.configuration.gpfs_storage_pool
|
||||||
self.flags(volume_driver=self.driver_name, gpfs_storage_pool='system')
|
self.flags(volume_driver=self.driver_name, gpfs_storage_pool='system')
|
||||||
self.driver._set_volume_attributes('', metadata)
|
self.driver._set_volume_attributes('', '', metadata)
|
||||||
self.flags(volume_driver=self.driver_name,
|
self.flags(volume_driver=self.driver_name,
|
||||||
gpfs_storage_pool=org_value)
|
gpfs_storage_pool=org_value)
|
||||||
|
|
||||||
@ -671,7 +679,7 @@ class GPFSDriverTestCase(test.TestCase):
|
|||||||
metadata = []
|
metadata = []
|
||||||
org_value = self.driver.configuration.gpfs_storage_pool
|
org_value = self.driver.configuration.gpfs_storage_pool
|
||||||
self.flags(volume_driver=self.driver_name, gpfs_storage_pool='')
|
self.flags(volume_driver=self.driver_name, gpfs_storage_pool='')
|
||||||
self.driver._set_volume_attributes('', metadata)
|
self.driver._set_volume_attributes('', '', metadata)
|
||||||
self.flags(volume_driver=self.driver_name,
|
self.flags(volume_driver=self.driver_name,
|
||||||
gpfs_storage_pool=org_value)
|
gpfs_storage_pool=org_value)
|
||||||
|
|
||||||
@ -695,12 +703,6 @@ class GPFSDriverTestCase(test.TestCase):
|
|||||||
volume['size'] = 1000
|
volume['size'] = 1000
|
||||||
value = {}
|
value = {}
|
||||||
value['value'] = 'test'
|
value['value'] = 'test'
|
||||||
volume['volume_metadata'] = [dict([('key', 'fstype'),
|
|
||||||
('value', 'test')]),
|
|
||||||
dict([('key', 'fslabel'),
|
|
||||||
('value', 'test')]),
|
|
||||||
dict([('key', 'test'),
|
|
||||||
('value', 'test')])]
|
|
||||||
|
|
||||||
org_value = self.driver.configuration.gpfs_sparse_volumes
|
org_value = self.driver.configuration.gpfs_sparse_volumes
|
||||||
self.flags(volume_driver=self.driver_name, gpfs_sparse_volumes=False)
|
self.flags(volume_driver=self.driver_name, gpfs_sparse_volumes=False)
|
||||||
@ -728,12 +730,6 @@ class GPFSDriverTestCase(test.TestCase):
|
|||||||
volume['size'] = 1000
|
volume['size'] = 1000
|
||||||
value = {}
|
value = {}
|
||||||
value['value'] = 'test'
|
value['value'] = 'test'
|
||||||
volume['volume_metadata'] = [dict([('key', 'fstype_'),
|
|
||||||
('value', 'test')]),
|
|
||||||
dict([('key', 'fslabel'),
|
|
||||||
('value', 'test')]),
|
|
||||||
dict([('key', 'test'),
|
|
||||||
('value', 'test')])]
|
|
||||||
|
|
||||||
org_value = self.driver.configuration.gpfs_sparse_volumes
|
org_value = self.driver.configuration.gpfs_sparse_volumes
|
||||||
self.flags(volume_driver=self.driver_name, gpfs_sparse_volumes=True)
|
self.flags(volume_driver=self.driver_name, gpfs_sparse_volumes=True)
|
||||||
@ -741,7 +737,39 @@ class GPFSDriverTestCase(test.TestCase):
|
|||||||
self.flags(volume_driver=self.driver_name,
|
self.flags(volume_driver=self.driver_name,
|
||||||
gpfs_sparse_volumes=org_value)
|
gpfs_sparse_volumes=org_value)
|
||||||
|
|
||||||
|
@patch('cinder.utils.execute')
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._allocate_file_blocks')
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_volume_attributes')
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_rw_permission')
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._create_sparse_file')
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path')
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._verify_gpfs_path_state')
|
||||||
|
def test_create_volume_with_metadata(self,
|
||||||
|
mock_gpfs_path_state,
|
||||||
|
mock_local_path,
|
||||||
|
mock_sparse_file,
|
||||||
|
mock_rw_permission,
|
||||||
|
mock_set_volume_attributes,
|
||||||
|
mock_allocate_file_blocks,
|
||||||
|
mock_exec):
|
||||||
|
mock_local_path.return_value = 'test'
|
||||||
|
volume = {}
|
||||||
|
volume['size'] = 1000
|
||||||
|
value = {}
|
||||||
|
value['value'] = 'test'
|
||||||
|
mock_set_volume_attributes.return_value = True
|
||||||
|
metadata = [{'key': 'fake_key', 'value': 'fake_value'}]
|
||||||
|
|
||||||
|
org_value = self.driver.configuration.gpfs_sparse_volumes
|
||||||
|
self.flags(volume_driver=self.driver_name, gpfs_sparse_volumes=False)
|
||||||
|
self.driver.create_volume(volume)
|
||||||
|
self.assertEqual(True, self.driver._set_volume_attributes(volume,
|
||||||
|
'test', metadata))
|
||||||
|
self.flags(volume_driver=self.driver_name,
|
||||||
|
gpfs_sparse_volumes=org_value)
|
||||||
|
|
||||||
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._resize_volume_file')
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._resize_volume_file')
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_volume_attributes')
|
||||||
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._gpfs_redirect')
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._gpfs_redirect')
|
||||||
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_rw_permission')
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_rw_permission')
|
||||||
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._create_gpfs_copy')
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._create_gpfs_copy')
|
||||||
@ -751,6 +779,7 @@ class GPFSDriverTestCase(test.TestCase):
|
|||||||
mock_create_gpfs_copy,
|
mock_create_gpfs_copy,
|
||||||
mock_rw_permission,
|
mock_rw_permission,
|
||||||
mock_gpfs_redirect,
|
mock_gpfs_redirect,
|
||||||
|
mock_set_volume_attributes,
|
||||||
mock_resize_volume_file):
|
mock_resize_volume_file):
|
||||||
mock_resize_volume_file.return_value = 5 * units.Gi
|
mock_resize_volume_file.return_value = 5 * units.Gi
|
||||||
volume = {}
|
volume = {}
|
||||||
@ -759,6 +788,31 @@ class GPFSDriverTestCase(test.TestCase):
|
|||||||
{'size': 5.0})
|
{'size': 5.0})
|
||||||
|
|
||||||
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._resize_volume_file')
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._resize_volume_file')
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_volume_attributes')
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._gpfs_redirect')
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_rw_permission')
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._create_gpfs_copy')
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path')
|
||||||
|
def test_create_volume_from_snapshot_metadata(self,
|
||||||
|
mock_local_path,
|
||||||
|
mock_create_gpfs_copy,
|
||||||
|
mock_rw_permission,
|
||||||
|
mock_gpfs_redirect,
|
||||||
|
mock_set_volume_attributes,
|
||||||
|
mock_resize_volume_file):
|
||||||
|
mock_resize_volume_file.return_value = 5 * units.Gi
|
||||||
|
volume = {}
|
||||||
|
volume['size'] = 1000
|
||||||
|
mock_set_volume_attributes.return_value = True
|
||||||
|
metadata = [{'key': 'fake_key', 'value': 'fake_value'}]
|
||||||
|
|
||||||
|
self.assertEqual(True, self.driver._set_volume_attributes(volume,
|
||||||
|
'test', metadata))
|
||||||
|
self.assertEqual(self.driver.create_volume_from_snapshot(volume, ''),
|
||||||
|
{'size': 5.0})
|
||||||
|
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._resize_volume_file')
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_volume_attributes')
|
||||||
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_rw_permission')
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_rw_permission')
|
||||||
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._create_gpfs_clone')
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._create_gpfs_clone')
|
||||||
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path')
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path')
|
||||||
@ -766,6 +820,7 @@ class GPFSDriverTestCase(test.TestCase):
|
|||||||
mock_local_path,
|
mock_local_path,
|
||||||
mock_create_gpfs_clone,
|
mock_create_gpfs_clone,
|
||||||
mock_rw_permission,
|
mock_rw_permission,
|
||||||
|
mock_set_volume_attributes,
|
||||||
mock_resize_volume_file):
|
mock_resize_volume_file):
|
||||||
mock_resize_volume_file.return_value = 5 * units.Gi
|
mock_resize_volume_file.return_value = 5 * units.Gi
|
||||||
volume = {}
|
volume = {}
|
||||||
@ -773,6 +828,28 @@ class GPFSDriverTestCase(test.TestCase):
|
|||||||
self.assertEqual(self.driver.create_cloned_volume(volume, ''),
|
self.assertEqual(self.driver.create_cloned_volume(volume, ''),
|
||||||
{'size': 5.0})
|
{'size': 5.0})
|
||||||
|
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._resize_volume_file')
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_volume_attributes')
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_rw_permission')
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._create_gpfs_clone')
|
||||||
|
@patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path')
|
||||||
|
def test_create_cloned_volume_with_metadata(self,
|
||||||
|
mock_local_path,
|
||||||
|
mock_create_gpfs_clone,
|
||||||
|
mock_rw_permission,
|
||||||
|
mock_set_volume_attributes,
|
||||||
|
mock_resize_volume_file):
|
||||||
|
mock_resize_volume_file.return_value = 5 * units.Gi
|
||||||
|
volume = {}
|
||||||
|
volume['size'] = 1000
|
||||||
|
mock_set_volume_attributes.return_value = True
|
||||||
|
metadata = [{'key': 'fake_key', 'value': 'fake_value'}]
|
||||||
|
|
||||||
|
self.assertEqual(True, self.driver._set_volume_attributes(volume,
|
||||||
|
'test', metadata))
|
||||||
|
self.assertEqual(self.driver.create_cloned_volume(volume, ''),
|
||||||
|
{'size': 5.0})
|
||||||
|
|
||||||
@patch('cinder.utils.execute')
|
@patch('cinder.utils.execute')
|
||||||
def test_delete_gpfs_file_ok(self, mock_exec):
|
def test_delete_gpfs_file_ok(self, mock_exec):
|
||||||
mock_exec.side_effect = [('Parent Depth Parent inode File name\n'
|
mock_exec.side_effect = [('Parent Depth Parent inode File name\n'
|
||||||
|
@ -449,7 +449,7 @@ class GPFSDriver(driver.VolumeDriver):
|
|||||||
LOG.debug('Update volume attributes with mmchattr to %s.' % options)
|
LOG.debug('Update volume attributes with mmchattr to %s.' % options)
|
||||||
self._execute(*cmd, run_as_root=True)
|
self._execute(*cmd, run_as_root=True)
|
||||||
|
|
||||||
def _set_volume_attributes(self, path, metadata):
|
def _set_volume_attributes(self, volume, path, metadata):
|
||||||
"""Set various GPFS attributes for this volume."""
|
"""Set various GPFS attributes for this volume."""
|
||||||
|
|
||||||
set_pool = False
|
set_pool = False
|
||||||
@ -477,6 +477,16 @@ class GPFSDriver(driver.VolumeDriver):
|
|||||||
if options:
|
if options:
|
||||||
self._gpfs_change_attributes(options, path)
|
self._gpfs_change_attributes(options, path)
|
||||||
|
|
||||||
|
fstype = None
|
||||||
|
fslabel = None
|
||||||
|
for item in metadata:
|
||||||
|
if item['key'] == 'fstype':
|
||||||
|
fstype = item['value']
|
||||||
|
elif item['key'] == 'fslabel':
|
||||||
|
fslabel = item['value']
|
||||||
|
if fstype:
|
||||||
|
self._mkfs(volume, fstype, fslabel)
|
||||||
|
|
||||||
def create_volume(self, volume):
|
def create_volume(self, volume):
|
||||||
"""Creates a GPFS volume."""
|
"""Creates a GPFS volume."""
|
||||||
# Check if GPFS is mounted
|
# Check if GPFS is mounted
|
||||||
@ -491,21 +501,11 @@ class GPFSDriver(driver.VolumeDriver):
|
|||||||
# Set the attributes prior to allocating any blocks so that
|
# Set the attributes prior to allocating any blocks so that
|
||||||
# they are allocated according to the policy
|
# they are allocated according to the policy
|
||||||
v_metadata = volume.get('volume_metadata')
|
v_metadata = volume.get('volume_metadata')
|
||||||
self._set_volume_attributes(volume_path, v_metadata)
|
self._set_volume_attributes(volume, volume_path, v_metadata)
|
||||||
|
|
||||||
if not self.configuration.gpfs_sparse_volumes:
|
if not self.configuration.gpfs_sparse_volumes:
|
||||||
self._allocate_file_blocks(volume_path, volume_size)
|
self._allocate_file_blocks(volume_path, volume_size)
|
||||||
|
|
||||||
fstype = None
|
|
||||||
fslabel = None
|
|
||||||
for item in v_metadata:
|
|
||||||
if item['key'] == 'fstype':
|
|
||||||
fstype = item['value']
|
|
||||||
elif item['key'] == 'fslabel':
|
|
||||||
fslabel = item['value']
|
|
||||||
if fstype:
|
|
||||||
self._mkfs(volume, fstype, fslabel)
|
|
||||||
|
|
||||||
def create_volume_from_snapshot(self, volume, snapshot):
|
def create_volume_from_snapshot(self, volume, snapshot):
|
||||||
"""Creates a GPFS volume from a snapshot."""
|
"""Creates a GPFS volume from a snapshot."""
|
||||||
|
|
||||||
@ -514,6 +514,8 @@ class GPFSDriver(driver.VolumeDriver):
|
|||||||
self._create_gpfs_copy(src=snapshot_path, dest=volume_path)
|
self._create_gpfs_copy(src=snapshot_path, dest=volume_path)
|
||||||
self._set_rw_permission(volume_path)
|
self._set_rw_permission(volume_path)
|
||||||
self._gpfs_redirect(volume_path)
|
self._gpfs_redirect(volume_path)
|
||||||
|
v_metadata = volume.get('volume_metadata')
|
||||||
|
self._set_volume_attributes(volume, volume_path, v_metadata)
|
||||||
virt_size = self._resize_volume_file(volume, volume['size'])
|
virt_size = self._resize_volume_file(volume, volume['size'])
|
||||||
return {'size': math.ceil(virt_size / units.Gi)}
|
return {'size': math.ceil(virt_size / units.Gi)}
|
||||||
|
|
||||||
@ -524,6 +526,8 @@ class GPFSDriver(driver.VolumeDriver):
|
|||||||
dest = self.local_path(volume)
|
dest = self.local_path(volume)
|
||||||
self._create_gpfs_clone(src, dest)
|
self._create_gpfs_clone(src, dest)
|
||||||
self._set_rw_permission(dest)
|
self._set_rw_permission(dest)
|
||||||
|
v_metadata = volume.get('volume_metadata')
|
||||||
|
self._set_volume_attributes(volume, dest, v_metadata)
|
||||||
virt_size = self._resize_volume_file(volume, volume['size'])
|
virt_size = self._resize_volume_file(volume, volume['size'])
|
||||||
return {'size': math.ceil(virt_size / units.Gi)}
|
return {'size': math.ceil(virt_size / units.Gi)}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user