From: Juan Zuluaga Date: Thu, 13 Nov 2014 15:46:37 +0000 (-0500) Subject: ZFSSA iSCSI driver should support extra specs X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=d86779a09881bb0548534120ff0f84b7ffa22050;p=openstack-build%2Fcinder-build.git ZFSSA iSCSI driver should support extra specs Support for extra specs at volume creation time, would allow more flexibility to create custom volumes. The following scoped keys are supported: -zfssa:volblocksize -zfssa:sparse -zfssa:compression -zfssa:logbias Closes-Bug: #1379403 DocImpact Change-Id: I8768d07f19147dc2544bebc0dbf3392313838e8f --- diff --git a/cinder/tests/test_zfssa.py b/cinder/tests/test_zfssa.py index b02e7bda6..8021527ee 100644 --- a/cinder/tests/test_zfssa.py +++ b/cinder/tests/test_zfssa.py @@ -115,24 +115,21 @@ class FakeZFSSA(object): def get_target(self, target): return 'iqn.1986-03.com.sun:02:00000-aaaa-bbbb-cccc-ddddd' - def create_lun(self, pool, project, lun, volsize, targetgroup, - volblocksize, sparse, compression, logbias): + def create_lun(self, pool, project, lun, volsize, targetgroup, specs): out = {} if not self.host and not self.user: return out - out = {"logbias": logbias, - "compression": compression, - "status": "online", + out = {"status": "online", "lunguid": "600144F0F8FBD5BD000053CE53AB0001", "initiatorgroup": ["fake_initgrp"], "volsize": volsize, "pool": pool, - "volblocksize": volblocksize, "name": lun, "project": project, - "sparse": sparse, "targetgroup": targetgroup} + if specs: + out.update(specs) return out @@ -273,6 +270,8 @@ class TestZFSSAISCSIDriver(test.TestCase): self.configuration.zfssa_target_portal = '1.1.1.1:3260' self.configuration.zfssa_target_interfaces = 'e1000g0' self.configuration.zfssa_rest_timeout = 60 + self.configuration.volume_backend_name = 'fake_zfssa' + self.configuration.safe_get = self.fake_safe_get def test_create_delete_volume(self): self.drv.create_volume(self.test_vol) @@ -315,9 +314,32 @@ class TestZFSSAISCSIDriver(test.TestCase): self.drv.extend_volume(self.test_vol, 3) self.drv.delete_volume(self.test_vol) + @mock.patch('cinder.volume.volume_types.get_volume_type_extra_specs') + def test_get_voltype_specs(self, get_volume_type_extra_specs): + volume_type_id = mock.sentinel.volume_type_id + volume = {'volume_type_id': volume_type_id} + get_volume_type_extra_specs.return_value = { + 'zfssa:volblocksize': '128k', + 'zfssa:compression': 'gzip' + } + ret = self.drv._get_voltype_specs(volume) + self.assertEqual(ret.get('volblocksize'), '128k') + self.assertEqual(ret.get('sparse'), + self.configuration.zfssa_lun_sparse) + self.assertEqual(ret.get('compression'), 'gzip') + self.assertEqual(ret.get('logbias'), + self.configuration.zfssa_lun_logbias) + def tearDown(self): super(TestZFSSAISCSIDriver, self).tearDown() + def fake_safe_get(self, value): + try: + val = getattr(self.configuration, value) + except AttributeError: + val = None + return val + class FakeAddIni2InitGrp(object): diff --git a/cinder/volume/drivers/zfssa/zfssaiscsi.py b/cinder/volume/drivers/zfssa/zfssaiscsi.py index a18b8edbe..47334468a 100644 --- a/cinder/volume/drivers/zfssa/zfssaiscsi.py +++ b/cinder/volume/drivers/zfssa/zfssaiscsi.py @@ -26,6 +26,7 @@ from cinder.openstack.common import log from cinder.volume import driver from cinder.volume.drivers.san import san from cinder.volume.drivers.zfssa import zfssarest +from cinder.volume import volume_types CONF = cfg.CONF LOG = log.getLogger(__name__) @@ -70,6 +71,11 @@ ZFSSA_OPTS = [ CONF.register_opts(ZFSSA_OPTS) +ZFSSA_LUN_SPECS = {'zfssa:volblocksize', + 'zfssa:sparse', + 'zfssa:compression', + 'zfssa:logbias'} + def factory_zfssa(): return zfssarest.ZFSSAApi() @@ -213,15 +219,13 @@ class ZFSSAISCSIDriver(driver.ISCSIDriver): LOG.debug('zfssa.create_volume: volume=' + volume['name']) lcfg = self.configuration volsize = str(volume['size']) + 'g' + specs = self._get_voltype_specs(volume) self.zfssa.create_lun(lcfg.zfssa_pool, lcfg.zfssa_project, volume['name'], volsize, - targetgroup=lcfg.zfssa_target_group, - volblocksize=lcfg.zfssa_lun_volblocksize, - sparse=lcfg.zfssa_lun_sparse, - compression=lcfg.zfssa_lun_compression, - logbias=lcfg.zfssa_lun_logbias) + lcfg.zfssa_target_group, + specs) def delete_volume(self, volume): """Deletes a volume with the given volume['name'].""" @@ -429,3 +433,30 @@ class ZFSSAISCSIDriver(driver.ISCSIDriver): lcfg.zfssa_project, volume['name'], '') + + def _get_voltype_specs(self, volume): + """Get specs suitable for volume creation.""" + vtype = volume.get('volume_type_id', None) + extra_specs = None + if vtype: + extra_specs = volume_types.get_volume_type_extra_specs(vtype) + + return self._get_specs(extra_specs) + + def _get_specs(self, xspecs): + """Return a dict with extra specs and/or config values.""" + result = {} + for spc in ZFSSA_LUN_SPECS: + val = None + prop = spc.split(':')[1] + cfg = 'zfssa_lun_' + prop + if xspecs: + val = xspecs.pop(spc, None) + + if val is None: + val = self.configuration.safe_get(cfg) + + if val is not None and val != '': + result.update({prop: val}) + + return result diff --git a/cinder/volume/drivers/zfssa/zfssarest.py b/cinder/volume/drivers/zfssa/zfssarest.py index 92128189c..d8203666c 100644 --- a/cinder/volume/drivers/zfssa/zfssarest.py +++ b/cinder/volume/drivers/zfssa/zfssarest.py @@ -384,12 +384,10 @@ class ZFSSAApi(object): LOG.error(exception_msg) raise exception.VolumeBackendAPIException(data=exception_msg) - def create_lun(self, pool, project, lun, volsize, targetgroup, - volblocksize='8k', sparse=False, compression=None, - logbias=None): + def create_lun(self, pool, project, lun, volsize, targetgroup, specs): + """Create a LUN. - required - pool, project, lun, volsize, targetgroup. - optional - volblocksize, sparse, compression, logbias + specs - contains volume properties (e.g blocksize, compression). """ svc = '/api/storage/v1/pools/' + pool + '/projects/' + \ project + '/luns' @@ -397,14 +395,10 @@ class ZFSSAApi(object): 'name': lun, 'volsize': volsize, 'targetgroup': targetgroup, - 'initiatorgroup': 'com.sun.ms.vss.hg.maskAll', - 'volblocksize': volblocksize, - 'sparse': sparse + 'initiatorgroup': 'com.sun.ms.vss.hg.maskAll' } - if compression and compression != '': - arg.update({'compression': compression}) - if logbias and logbias != '': - arg.update({'logbias': logbias}) + if specs: + arg.update(specs) ret = self.rclient.post(svc, arg) if ret.status != restclient.Status.CREATED: