From: John Griffith Date: Wed, 10 Jul 2013 21:34:26 +0000 (-0600) Subject: Enable setting blocksize on volumes. X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=67078ab9329b8f3d844b033b4d64cf2bdcf6bab7;p=openstack-build%2Fcinder-build.git Enable setting blocksize on volumes. Some back-ends support blocksizes other than the default 512 (like 4096), this change adds a provider_geometry column to the volumes table, format is "physical_block_size logical_block_size". This can then be used by libvirt to determine if it should pass in non-default block_size info, and there's a method for future geometry/disk info that might be needed. Fixes bug: 1196248 Change-Id: I8d40bc56403154fbe955cd4ccf8f0c55fc9eb7c5 --- diff --git a/cinder/db/sqlalchemy/migrate_repo/versions/013_add_provider_geometry_column.py b/cinder/db/sqlalchemy/migrate_repo/versions/013_add_provider_geometry_column.py new file mode 100644 index 000000000..c027992fa --- /dev/null +++ b/cinder/db/sqlalchemy/migrate_repo/versions/013_add_provider_geometry_column.py @@ -0,0 +1,37 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from sqlalchemy import Column +from sqlalchemy import MetaData, String, Table + + +def upgrade(migrate_engine): + """Add provider_geometry column to volumes.""" + meta = MetaData() + meta.bind = migrate_engine + + volumes = Table('volumes', meta, autoload=True) + provider_geometry = Column('provider_geometry', String(255)) + volumes.create_column(provider_geometry) + volumes.update().values(provider_geometry=None).execute() + + +def downgrade(migrate_engine): + """Remove provider_geometry column from volumes.""" + meta = MetaData() + meta.bind = migrate_engine + + volumes = Table('volumes', meta, autoload=True) + provider_geometry = Column('provider_geometry', String(255)) + volumes.drop_column(provider_geometry) diff --git a/cinder/db/sqlalchemy/migrate_repo/versions/013_sqlite_downgrade.sql b/cinder/db/sqlalchemy/migrate_repo/versions/013_sqlite_downgrade.sql new file mode 100644 index 000000000..509fe434b --- /dev/null +++ b/cinder/db/sqlalchemy/migrate_repo/versions/013_sqlite_downgrade.sql @@ -0,0 +1,68 @@ +BEGIN TRANSACTION; + +CREATE TABLE volumes_v12 ( + created_at DATETIME, + updated_at DATETIME, + deleted_at DATETIME, + deleted BOOLEAN, + id VARCHAR(36) NOT NULL, + ec2_id INTEGER, + user_id VARCHAR(255), + project_id VARCHAR(255), + snapshot_id VARCHAR(36), + host VARCHAR(255), + size INTEGER, + availability_zone VARCHAR(255), + instance_uuid VARCHAR(36), + mountpoint VARCHAR(255), + attach_time VARCHAR(255), + status VARCHAR(255), + attach_status VARCHAR(255), + scheduled_at DATETIME, + launched_at DATETIME, + terminated_at DATETIME, + display_name VARCHAR(255), + display_description VARCHAR(255), + provider_location VARCHAR(255), + provider_auth VARCHAR(255), + volume_type_id VARCHAR(36), + source_volid VARCHAR(36), + bootable BOOLEAN, + attached_host VARCHAR(255), + PRIMARY KEY (id) +); + +INSERT INTO volumes_v12 + SELECT created_at, + updated_at, + deleted_at, + deleted, + id, + ec2_id, + user_id, + project_id, + snapshot_id, + host, + size, + availability_zone, + instance_uuid, + mountpoint, + attach_time, + status, + attach_status, + scheduled_at, + launched_at, + terminated_at, + display_name, + display_description, + provider_location, + provider_auth, + volume_type_id, + source_volid, + bootable, + attached_host + FROM volumes; + +DROP TABLE volumes; +ALTER TABLE volumes_v12 RENAME TO volumes; +COMMIT; diff --git a/cinder/db/sqlalchemy/models.py b/cinder/db/sqlalchemy/models.py index 6cbd3189f..d665f0dd8 100644 --- a/cinder/db/sqlalchemy/models.py +++ b/cinder/db/sqlalchemy/models.py @@ -111,6 +111,7 @@ class Volume(BASE, CinderBase): provider_location = Column(String(255)) provider_auth = Column(String(255)) + provider_geometry = Column(String(255)) volume_type_id = Column(String(36)) source_volid = Column(String(36)) diff --git a/cinder/tests/test_migrations.py b/cinder/tests/test_migrations.py index 87a42df55..b33d309f0 100644 --- a/cinder/tests/test_migrations.py +++ b/cinder/tests/test_migrations.py @@ -747,3 +747,29 @@ class TestMigrations(test.TestCase): metadata, autoload=True) self.assertTrue('attached_host' not in volumes.c) + + def test_migration_013(self): + """Test that adding provider_geometry column works correctly.""" + for (key, engine) in self.engines.items(): + migration_api.version_control(engine, + TestMigrations.REPOSITORY, + migration.INIT_VERSION) + migration_api.upgrade(engine, TestMigrations.REPOSITORY, 12) + metadata = sqlalchemy.schema.MetaData() + metadata.bind = engine + + migration_api.upgrade(engine, TestMigrations.REPOSITORY, 13) + volumes = sqlalchemy.Table('volumes', + metadata, + autoload=True) + self.assertTrue(isinstance(volumes.c.provider_geometry.type, + sqlalchemy.types.VARCHAR)) + + migration_api.downgrade(engine, TestMigrations.REPOSITORY, 12) + metadata = sqlalchemy.schema.MetaData() + metadata.bind = engine + + volumes = sqlalchemy.Table('volumes', + metadata, + autoload=True) + self.assertTrue('provider_geometry' not in volumes.c) diff --git a/cinder/tests/test_solidfire.py b/cinder/tests/test_solidfire.py index bb2bc06e6..9606dbe19 100644 --- a/cinder/tests/test_solidfire.py +++ b/cinder/tests/test_solidfire.py @@ -16,10 +16,6 @@ # under the License. import mox -from mox import IgnoreArg -from mox import IsA -from mox import stubout - from cinder import exception from cinder.openstack.common import log as logging @@ -160,6 +156,42 @@ class SolidFireVolumeTestCase(test.TestCase): sfv = SolidFire(configuration=self.configuration) model_update = sfv.create_volume(testvol) self.assertNotEqual(model_update, None) + self.assertEqual(model_update.get('provider_geometry', None), None) + + def test_create_volume_non_512(self): + self.stubs.Set(SolidFire, '_issue_api_request', + self.fake_issue_api_request) + testvol = {'project_id': 'testprjid', + 'name': 'testvol', + 'size': 1, + 'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66', + 'volume_type_id': None} + self.configuration.sf_emulate_512 = False + sfv = SolidFire(configuration=self.configuration) + model_update = sfv.create_volume(testvol) + self.assertEqual(model_update.get('provider_geometry', None), + '4096 4096') + self.configuration.sf_emulate_512 = True + + def test_initialize_connector_with_blocksizes(self): + connector = {'initiator': 'iqn.2012-07.org.fake:01'} + testvol = {'project_id': 'testprjid', + 'name': 'testvol', + 'size': 1, + 'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66', + 'volume_type_id': None, + 'provider_location': '10.10.7.1:3260 iqn.2010-01.com.' + 'solidfire:87hg.uuid-2cc06226-cc' + '74-4cb7-bd55-14aed659a0cc.4060 0', + 'provider_auth': 'CHAP stack-1-a60e2611875f40199931f2' + 'c76370d66b 2FE0CQ8J196R', + 'provider_geometry': '4096 4096' + } + + sfv = SolidFire(configuration=self.configuration) + properties = sfv.initialize_connection(testvol, connector) + self.assertEqual(properties['data']['physical_block_size'], '4096') + self.assertEqual(properties['data']['logical_block_size'], '4096') def test_create_volume_with_qos(self): preset_qos = {} diff --git a/cinder/volume/driver.py b/cinder/volume/driver.py index bb29fe5c1..834631c44 100644 --- a/cinder/volume/driver.py +++ b/cinder/volume/driver.py @@ -323,6 +323,12 @@ class ISCSIDriver(VolumeDriver): properties['auth_username'] = auth_username properties['auth_password'] = auth_secret + geometry = volume.get('provider_geometry', None) + if geometry: + (physical_block_size, logical_block_size) = geometry.split() + properties['physical_block_size'] = physical_block_size + properties['logical_block_size'] = logical_block_size + return properties def _run_iscsiadm(self, iscsi_properties, iscsi_command, **kwargs): diff --git a/cinder/volume/drivers/solidfire.py b/cinder/volume/drivers/solidfire.py index 4b9385b1b..4d04ce5d9 100644 --- a/cinder/volume/drivers/solidfire.py +++ b/cinder/volume/drivers/solidfire.py @@ -299,6 +299,9 @@ class SolidFire(SanISCSIDriver): model_update['provider_auth'] = ('CHAP %s %s' % (sfaccount['username'], chap_secret)) + if not self.configuration.sf_emulate_512: + model_update['provider_geometry'] = ('%s %s' % (4096, 4096)) + return model_update def _do_clone_volume(self, src_uuid, src_project_id, v_ref):