d['size'] = vol['size']
d['availability_zone'] = vol['availability_zone']
d['created_at'] = vol['created_at']
+ d['bootable'] = vol['bootable']
d['attachments'] = []
if vol['attach_status'] == 'attached':
else:
d['metadata'] = {}
- if vol.get('volume_glance_metadata'):
- d['bootable'] = 'true'
- else:
- d['bootable'] = 'false'
-
return d
image_href = None
image_uuid = None
if self.ext_mgr.is_loaded('os-image-create'):
+ # NOTE(jdg): misleading name "imageRef" as it's an image-id
image_href = volume.get('imageRef')
if image_href:
image_uuid = self._image_uuid_from_href(image_href)
--- /dev/null
+# 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 Boolean, Column, MetaData, Table
+
+
+def upgrade(migrate_engine):
+ """Add bootable column to volumes."""
+ meta = MetaData()
+ meta.bind = migrate_engine
+
+ volumes = Table('volumes', meta, autoload=True)
+ bootable = Column('bootable', Boolean)
+
+ volumes.create_column(bootable)
+ volumes.update().values(bootable=False).execute()
+
+ glance_metadata = Table('volume_glance_metadata', meta, autoload=True)
+ glance_items = list(glance_metadata.select().execute())
+ for item in glance_items:
+ volumes.update().\
+ where(volumes.c.id == item['volume_id']).\
+ values(bootable=True).execute()
+
+
+def downgrade(migrate_engine):
+ """Remove bootable column to volumes."""
+ meta = MetaData()
+ meta.bind = migrate_engine
+
+ volumes = Table('volumes', meta, autoload=True)
+ bootable = volumes.columns.bootable
+ #bootable = Column('bootable', Boolean)
+ volumes.drop_column(bootable)
--- /dev/null
+BEGIN TRANSACTION;
+
+ CREATE TABLE volumes_v10 (
+ 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),
+ PRIMARY KEY (id)
+ );
+
+ INSERT INTO volumes_v10
+ 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
+ FROM volumes;
+
+ DROP TABLE volumes;
+ ALTER TABLE volumes_v10 RENAME TO volumes;
+ COMMIT;
+
+
volume_type_id = Column(String(36))
source_volid = Column(String(36))
+ deleted = Column(Boolean, default=False)
+ bootable = Column(Boolean, default=False)
class VolumeMetadata(BASE, CinderBase):
'server_id': 'fakeuuid',
'id': '1',
'volume_id': '1'}],
- 'bootable': 'false',
+ 'bootable': False,
'volume_type': 'vol_type_name',
'snapshot_id': None,
'source_volid': None,
'server_id': 'fakeuuid',
'id': '1',
'volume_id': '1'}],
- 'bootable': 'false',
+ 'bootable': False,
'volume_type': 'vol_type_name',
'image_id': test_id,
'snapshot_id': None,
'server_id': 'fakeuuid',
'device': '/',
}],
- 'bootable': 'false',
+ 'bootable': False,
'volume_type': 'vol_type_name',
'snapshot_id': None,
'source_volid': None,
'server_id': 'fakeuuid',
'device': '/',
}],
- 'bootable': 'false',
+ 'bootable': False,
'volume_type': 'vol_type_name',
'snapshot_id': None,
'source_volid': None,
'server_id': 'fakeuuid',
'id': '1',
'volume_id': '1'}],
- 'bootable': 'false',
+ 'bootable': False,
'volume_type': 'vol_type_name',
'snapshot_id': None,
'source_volid': None,
'server_id': 'fakeuuid',
'id': '1',
'volume_id': '1'}],
- 'bootable': 'false',
+ 'bootable': False,
'volume_type': 'vol_type_name',
'snapshot_id': None,
'source_volid': None,
'server_id': 'fakeuuid',
'id': '1',
'volume_id': '1'}],
- 'bootable': 'false',
+ 'bootable': False,
'volume_type': 'vol_type_name',
'snapshot_id': None,
'source_volid': None,
'availability_zone': 'fakeaz',
'display_name': 'displayname',
'attachments': [],
- 'bootable': 'false',
+ 'bootable': False,
'volume_type': 'vol_type_name',
'snapshot_id': None,
'source_volid': None,
'server_id': 'fakeuuid',
'id': '1',
'volume_id': '1'}],
- 'bootable': 'true',
+ 'bootable': True,
'volume_type': 'vol_type_name',
'snapshot_id': None,
'source_volid': None,
'source_volid': None,
'volume_type_id': '3e196c20-3c06-11e2-81c1-0800200c9a66',
'volume_metadata': [],
+ 'bootable': False,
'volume_type': {'name': 'vol_type_name'}}
volume.update(kwargs)
+ if kwargs.get('volume_glance_metadata', None):
+ volume['bootable'] = True
return volume
vol['display_name'] = name
vol['display_description'] = description
vol['source_volid'] = None
+ vol['bootable'] = False
try:
vol['snapshot_id'] = snapshot['id']
except (KeyError, TypeError):
vol['display_name'] = name
vol['display_description'] = description
vol['availability_zone'] = 'cinder'
+ vol['bootable'] = False
return vol
flags.DECLARE('volume_driver', 'cinder.volume.manager')
flags.DECLARE('xiv_proxy', 'cinder.volume.drivers.xiv')
flags.DECLARE('backup_service', 'cinder.backup.manager')
-
def_vol_type = 'fake_vol_type'
self.assertFalse(engine.dialect.has_table(engine.connect(),
"transfers"))
+
+ def test_migration_011(self):
+ """Test adding transfers table 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, 10)
+ metadata = sqlalchemy.schema.MetaData()
+ metadata.bind = engine
+
+ volumes_v10 = sqlalchemy.Table('volumes',
+ metadata,
+ autoload=True)
+
+ migration_api.upgrade(engine, TestMigrations.REPOSITORY, 11)
+ metadata = sqlalchemy.schema.MetaData()
+ metadata.bind = engine
+
+ self.assertTrue(engine.dialect.has_table(engine.connect(),
+ "volumes"))
+ volumes = sqlalchemy.Table('volumes',
+ metadata,
+ autoload=True)
+
+ # Make sure we didn't miss any columns in the upgrade
+ for column in volumes_v10.c:
+ self.assertTrue(volumes.c.__contains__(column.name))
+
+ self.assertTrue(isinstance(volumes.c.bootable.type,
+ sqlalchemy.types.BOOLEAN))
+
+ migration_api.downgrade(engine, TestMigrations.REPOSITORY, 10)
+ metadata = sqlalchemy.schema.MetaData()
+ metadata.bind = engine
+
+ volumes = sqlalchemy.Table('volumes',
+ metadata,
+ autoload=True)
+ self.assertTrue('bootable' not in volumes.c)
+
+ # Make sure we put all the columns back
+ for column in volumes_v10.c:
+ self.assertTrue(volumes.c.__contains__(column.name))
def get(self, context, volume_id):
rv = self.db.volume_get(context, volume_id)
- glance_meta = rv.get('volume_glance_metadata', None)
volume = dict(rv.iteritems())
check_policy(context, 'get', volume)
-
- # NOTE(jdg): As per bug 1115629 iteritems doesn't pick
- # up the glance_meta dependency, add it explicitly if
- # it exists in the rv
- if glance_meta:
- volume['volume_glance_metadata'] = glance_meta
-
return volume
def get_all(self, context, marker=None, limit=None, sort_key='created_at',
model_update = self.driver.create_volume_from_snapshot(
volume_ref,
snapshot_ref)
+
+ originating_vref = self.db.volume_get(context,
+ snapshot_ref['volume_id'])
+ if originating_vref.bootable:
+ self.db.volume_update(context,
+ volume_ref['id'],
+ {'bootable': True})
elif srcvol_ref is not None:
model_update = self.driver.create_cloned_volume(volume_ref,
srcvol_ref)
+ if srcvol_ref.bootable:
+ self.db.volume_update(context,
+ volume_ref['id'],
+ {'bootable': True})
else:
# create the volume from an image
cloned = self.driver.clone_image(volume_ref, image_location)
volume_ref = self.db.volume_update(context,
volume_ref['id'],
updates)
+
+ # TODO(jdg): Wrap this in a try block and update status
+ # appropriately if the download image fails
self._copy_image_to_volume(context,
volume_ref,
image_service,
image_id)
-
+ self.db.volume_update(context,
+ volume_ref['id'],
+ {'bootable': True})
return model_update, cloned
def create_volume(self, context, volume_id, request_spec=None,