]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Enable setting blocksize on volumes.
authorJohn Griffith <john.griffith@solidfire.com>
Wed, 10 Jul 2013 21:34:26 +0000 (15:34 -0600)
committerJohn Griffith <john.griffith@solidfire.com>
Wed, 10 Jul 2013 22:32:09 +0000 (16:32 -0600)
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

cinder/db/sqlalchemy/migrate_repo/versions/013_add_provider_geometry_column.py [new file with mode: 0644]
cinder/db/sqlalchemy/migrate_repo/versions/013_sqlite_downgrade.sql [new file with mode: 0644]
cinder/db/sqlalchemy/models.py
cinder/tests/test_migrations.py
cinder/tests/test_solidfire.py
cinder/volume/driver.py
cinder/volume/drivers/solidfire.py

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 (file)
index 0000000..c027992
--- /dev/null
@@ -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 (file)
index 0000000..509fe43
--- /dev/null
@@ -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;
index 6cbd3189f679a63fcb19cae8dff24b87a8fc22b3..d665f0dd8068dc470ff64d850946c59eaf42bc67 100644 (file)
@@ -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))
index 87a42df5512ca91803dcf7720c6745203551d822..b33d309f02fc10b1032f3182f1c7425bd089cc91 100644 (file)
@@ -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)
index bb2bc06e6502edd550221d5531bc0201ee3a8f47..9606dbe19777ec04f398350015717fa625874e2b 100644 (file)
 #    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 = {}
index bb29fe5c1f990ded3c7d0d64571af99d882fda35..834631c44babebe9ad27c8793f218638cc01d64d 100644 (file)
@@ -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):
index 4b9385b1b76d05fb3d6d747f17ff4d7b0999fcea..4d04ce5d9390fd2bdc0f08185073daca8fd8f86b 100644 (file)
@@ -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):