Migrate block_device_mapping to use instance uuids.
This started out as wanting cleanup_volumes to take a UUID instead of an instance ID, and ended up as a wander through the joys of schema updates. I am assuming that we actually want to transition these tables across to using the instance UUID instead of just the ID. This is my first attempt at a schema update, so please review this patch with skepticism. Resolves bug 977975. Partially resolves blueprint finish-uuid-conversion. Change-Id: Ib5a6f8a872ea0530e201c70e9ac01cd14f82c557
This commit is contained in:
parent
62bcf37959
commit
58af96d3e0
@ -998,7 +998,7 @@ class CloudController(object):
|
||||
def _format_attr_block_device_mapping(instance, result):
|
||||
tmp = {}
|
||||
self._format_instance_root_device_name(instance, tmp)
|
||||
self._format_instance_bdm(context, instance_id,
|
||||
self._format_instance_bdm(context, instance['uuid'],
|
||||
tmp['rootDeviceName'], result)
|
||||
|
||||
def _format_attr_disable_api_termination(instance, result):
|
||||
@ -1098,13 +1098,13 @@ class CloudController(object):
|
||||
instances_set.append(i)
|
||||
return {'instancesSet': instances_set}
|
||||
|
||||
def _format_instance_bdm(self, context, instance_id, root_device_name,
|
||||
def _format_instance_bdm(self, context, instance_uuid, root_device_name,
|
||||
result):
|
||||
"""Format InstanceBlockDeviceMappingResponseItemType"""
|
||||
root_device_type = 'instance-store'
|
||||
mapping = []
|
||||
for bdm in db.block_device_mapping_get_all_by_instance(context,
|
||||
instance_id):
|
||||
instance_uuid):
|
||||
volume_id = bdm['volume_id']
|
||||
if (volume_id is None or bdm['no_device']):
|
||||
continue
|
||||
@ -1220,7 +1220,7 @@ class CloudController(object):
|
||||
i['launchTime'] = instance['created_at']
|
||||
i['amiLaunchIndex'] = instance['launch_index']
|
||||
self._format_instance_root_device_name(instance, i)
|
||||
self._format_instance_bdm(context, instance_id,
|
||||
self._format_instance_bdm(context, instance['uuid'],
|
||||
i['rootDeviceName'], i)
|
||||
host = instance['host']
|
||||
services = db.service_get_all_by_host(context.elevated(), host)
|
||||
|
@ -99,7 +99,7 @@ class MetadataRequestHandler(wsgi.Application):
|
||||
|
||||
# 'ephemeralN', 'swap' and ebs
|
||||
for bdm in db.block_device_mapping_get_all_by_instance(
|
||||
ctxt, instance_ref['id']):
|
||||
ctxt, instance_ref['uuid']):
|
||||
if bdm['no_device']:
|
||||
continue
|
||||
|
||||
|
@ -484,7 +484,7 @@ class API(BaseAPI):
|
||||
return size
|
||||
|
||||
def _update_image_block_device_mapping(self, elevated_context,
|
||||
instance_type, instance_id,
|
||||
instance_type, instance_uuid,
|
||||
mappings):
|
||||
"""tell vm driver to create ephemeral/swap device at boot time by
|
||||
updating BlockDeviceMapping
|
||||
@ -507,7 +507,7 @@ class API(BaseAPI):
|
||||
continue
|
||||
|
||||
values = {
|
||||
'instance_id': instance_id,
|
||||
'instance_uuid': instance_uuid,
|
||||
'device_name': bdm['device'],
|
||||
'virtual_name': virtual_name,
|
||||
'volume_size': size}
|
||||
@ -515,7 +515,7 @@ class API(BaseAPI):
|
||||
values)
|
||||
|
||||
def _update_block_device_mapping(self, elevated_context,
|
||||
instance_type, instance_id,
|
||||
instance_type, instance_uuid,
|
||||
block_device_mapping):
|
||||
"""tell vm driver to attach volume at boot time by updating
|
||||
BlockDeviceMapping
|
||||
@ -524,7 +524,7 @@ class API(BaseAPI):
|
||||
for bdm in block_device_mapping:
|
||||
assert 'device_name' in bdm
|
||||
|
||||
values = {'instance_id': instance_id}
|
||||
values = {'instance_uuid': instance_uuid}
|
||||
for key in ('device_name', 'delete_on_termination', 'virtual_name',
|
||||
'snapshot_id', 'volume_id', 'volume_size',
|
||||
'no_device'):
|
||||
@ -587,12 +587,13 @@ class API(BaseAPI):
|
||||
|
||||
# BlockDeviceMapping table
|
||||
self._update_image_block_device_mapping(elevated, instance_type,
|
||||
instance_id, image['properties'].get('mappings', []))
|
||||
self._update_block_device_mapping(elevated, instance_type, instance_id,
|
||||
instance_uuid, image['properties'].get('mappings', []))
|
||||
self._update_block_device_mapping(elevated, instance_type,
|
||||
instance_uuid,
|
||||
image['properties'].get('block_device_mapping', []))
|
||||
# override via command line option
|
||||
self._update_block_device_mapping(elevated, instance_type, instance_id,
|
||||
block_device_mapping)
|
||||
self._update_block_device_mapping(elevated, instance_type,
|
||||
instance_uuid, block_device_mapping)
|
||||
|
||||
# Set sane defaults if not specified
|
||||
updates = {}
|
||||
|
@ -354,7 +354,7 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
swap = None
|
||||
ephemerals = []
|
||||
for bdm in self.db.block_device_mapping_get_all_by_instance(
|
||||
context, instance['id']):
|
||||
context, instance['uuid']):
|
||||
LOG.debug(_('Setting up bdm %s'), bdm, instance=instance)
|
||||
|
||||
if bdm['no_device']:
|
||||
@ -616,13 +616,13 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
instance=instance)
|
||||
self.network_api.deallocate_for_instance(context, instance)
|
||||
|
||||
def _get_instance_volume_bdms(self, context, instance_id):
|
||||
def _get_instance_volume_bdms(self, context, instance_uuid):
|
||||
bdms = self.db.block_device_mapping_get_all_by_instance(context,
|
||||
instance_id)
|
||||
instance_uuid)
|
||||
return [bdm for bdm in bdms if bdm['volume_id']]
|
||||
|
||||
def _get_instance_volume_bdm(self, context, instance_id, volume_id):
|
||||
bdms = self._get_instance_volume_bdms(context, instance_id)
|
||||
def _get_instance_volume_bdm(self, context, instance_uuid, volume_id):
|
||||
bdms = self._get_instance_volume_bdms(context, instance_uuid)
|
||||
for bdm in bdms:
|
||||
# NOTE(vish): Comparing as strings because the os_api doesn't
|
||||
# convert to integer and we may wish to support uuids
|
||||
@ -630,8 +630,8 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
if str(bdm['volume_id']) == str(volume_id):
|
||||
return bdm
|
||||
|
||||
def _get_instance_volume_block_device_info(self, context, instance_id):
|
||||
bdms = self._get_instance_volume_bdms(context, instance_id)
|
||||
def _get_instance_volume_block_device_info(self, context, instance_uuid):
|
||||
bdms = self._get_instance_volume_bdms(context, instance_uuid)
|
||||
block_device_mapping = []
|
||||
for bdm in bdms:
|
||||
cinfo = utils.loads(bdm['connection_info'])
|
||||
@ -667,8 +667,6 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
def _shutdown_instance(self, context, instance, action_str):
|
||||
"""Shutdown an instance on this host."""
|
||||
context = context.elevated()
|
||||
instance_id = instance['id']
|
||||
instance_uuid = instance['uuid']
|
||||
LOG.audit(_('%(action_str)s instance') % {'action_str': action_str},
|
||||
context=context, instance=instance)
|
||||
|
||||
@ -680,9 +678,9 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
self._deallocate_network(context, instance)
|
||||
|
||||
# NOTE(vish) get bdms before destroying the instance
|
||||
bdms = self._get_instance_volume_bdms(context, instance_id)
|
||||
bdms = self._get_instance_volume_bdms(context, instance['uuid'])
|
||||
block_device_info = self._get_instance_volume_block_device_info(
|
||||
context, instance_id)
|
||||
context, instance['uuid'])
|
||||
self.driver.destroy(instance, self._legacy_nw_info(network_info),
|
||||
block_device_info)
|
||||
for bdm in bdms:
|
||||
@ -701,11 +699,12 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
|
||||
self._notify_about_instance_usage(context, instance, "shutdown.end")
|
||||
|
||||
def _cleanup_volumes(self, context, instance_id):
|
||||
def _cleanup_volumes(self, context, instance_uuid):
|
||||
bdms = self.db.block_device_mapping_get_all_by_instance(context,
|
||||
instance_id)
|
||||
instance_uuid)
|
||||
for bdm in bdms:
|
||||
LOG.debug(_("terminating bdm %s") % bdm)
|
||||
LOG.debug(_("terminating bdm %s") % bdm,
|
||||
instance_uuid=instance_uuid)
|
||||
if bdm['volume_id'] and bdm['delete_on_termination']:
|
||||
volume = self.volume_api.get(context, bdm['volume_id'])
|
||||
self.volume_api.delete(context, volume)
|
||||
@ -716,7 +715,7 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
instance_id = instance['id']
|
||||
self._notify_about_instance_usage(context, instance, "delete.start")
|
||||
self._shutdown_instance(context, instance, 'Terminating')
|
||||
self._cleanup_volumes(context, instance_id)
|
||||
self._cleanup_volumes(context, instance['uuid'])
|
||||
instance = self._instance_update(context,
|
||||
instance_id,
|
||||
vm_state=vm_states.DELETED,
|
||||
@ -1711,7 +1710,6 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
volume = self.volume_api.get(context, volume_id)
|
||||
context = context.elevated()
|
||||
instance_ref = self.db.instance_get_by_uuid(context, instance_uuid)
|
||||
instance_id = instance_ref['id']
|
||||
LOG.audit(_('Attaching volume %(volume_id)s to %(mountpoint)s'),
|
||||
locals(), context=context, instance=instance_ref)
|
||||
try:
|
||||
@ -1740,9 +1738,9 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
volume,
|
||||
connector)
|
||||
|
||||
self.volume_api.attach(context, volume, instance_id, mountpoint)
|
||||
self.volume_api.attach(context, volume, instance_ref['id'], mountpoint)
|
||||
values = {
|
||||
'instance_id': instance_id,
|
||||
'instance_uuid': instance_ref['uuid'],
|
||||
'connection_info': utils.dumps(connection_info),
|
||||
'device_name': mountpoint,
|
||||
'delete_on_termination': False,
|
||||
@ -1777,15 +1775,14 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
def detach_volume(self, context, instance_uuid, volume_id):
|
||||
"""Detach a volume from an instance."""
|
||||
instance_ref = self.db.instance_get_by_uuid(context, instance_uuid)
|
||||
instance_id = instance_ref['id']
|
||||
bdm = self._get_instance_volume_bdm(context, instance_id, volume_id)
|
||||
bdm = self._get_instance_volume_bdm(context, instance_uuid, volume_id)
|
||||
self._detach_volume(context, instance_ref, bdm)
|
||||
volume = self.volume_api.get(context, volume_id)
|
||||
connector = self.driver.get_volume_connector(instance_ref)
|
||||
self.volume_api.terminate_connection(context, volume, connector)
|
||||
self.volume_api.detach(context.elevated(), volume)
|
||||
self.db.block_device_mapping_destroy_by_instance_and_volume(
|
||||
context, instance_id, volume_id)
|
||||
context, instance_uuid, volume_id)
|
||||
return True
|
||||
|
||||
@exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
|
||||
@ -1888,7 +1885,7 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
|
||||
# If any volume is mounted, prepare here.
|
||||
block_device_info = self._get_instance_volume_block_device_info(
|
||||
context, instance_id)
|
||||
context, instance_ref['uuid'])
|
||||
if not block_device_info['block_device_mapping']:
|
||||
LOG.info(_('Instance has no volume.'), instance=instance_ref)
|
||||
|
||||
@ -1958,7 +1955,7 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
try:
|
||||
# Checking volume node is working correctly when any volumes
|
||||
# are attached to instances.
|
||||
if self._get_instance_volume_bdms(context, instance_id):
|
||||
if self._get_instance_volume_bdms(context, instance_ref['uuid']):
|
||||
rpc.call(context,
|
||||
FLAGS.volume_topic,
|
||||
{'method': 'check_for_export',
|
||||
@ -2010,7 +2007,7 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
instance=instance_ref)
|
||||
|
||||
# Detaching volumes.
|
||||
for bdm in self._get_instance_volume_bdms(ctxt, instance_ref['id']):
|
||||
for bdm in self._get_instance_volume_bdms(ctxt, instance_ref['uuid']):
|
||||
# NOTE(vish): We don't want to actually mark the volume
|
||||
# detached, or delete the bdm, just remove the
|
||||
# connection from this host.
|
||||
@ -2146,7 +2143,8 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
self.network_api.setup_networks_on_host(context, instance_ref,
|
||||
self.host)
|
||||
|
||||
for bdm in self._get_instance_volume_bdms(context, instance_ref['id']):
|
||||
for bdm in self._get_instance_volume_bdms(context,
|
||||
instance_ref['uuid']):
|
||||
volume_id = bdm['volume_id']
|
||||
volume = self.volume_api.get(context, volume_id)
|
||||
self.volume_api.update(context, volume, {'status': 'in-use'})
|
||||
@ -2477,7 +2475,7 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
"DELETED but still present on host."),
|
||||
locals(), instance=instance)
|
||||
self._shutdown_instance(context, instance, 'Terminating')
|
||||
self._cleanup_volumes(context, instance['id'])
|
||||
self._cleanup_volumes(context, instance['uuid'])
|
||||
else:
|
||||
raise Exception(_("Unrecognized value '%(action)s'"
|
||||
" for FLAGS.running_deleted_"
|
||||
|
@ -1086,9 +1086,10 @@ def block_device_mapping_update_or_create(context, values):
|
||||
return IMPL.block_device_mapping_update_or_create(context, values)
|
||||
|
||||
|
||||
def block_device_mapping_get_all_by_instance(context, instance_id):
|
||||
def block_device_mapping_get_all_by_instance(context, instance_uuid):
|
||||
"""Get all block device mapping belonging to a instance"""
|
||||
return IMPL.block_device_mapping_get_all_by_instance(context, instance_id)
|
||||
return IMPL.block_device_mapping_get_all_by_instance(context,
|
||||
instance_uuid)
|
||||
|
||||
|
||||
def block_device_mapping_destroy(context, bdm_id):
|
||||
@ -1096,11 +1097,11 @@ def block_device_mapping_destroy(context, bdm_id):
|
||||
return IMPL.block_device_mapping_destroy(context, bdm_id)
|
||||
|
||||
|
||||
def block_device_mapping_destroy_by_instance_and_volume(context, instance_id,
|
||||
def block_device_mapping_destroy_by_instance_and_volume(context, instance_uuid,
|
||||
volume_id):
|
||||
"""Destroy the block device mapping or raise if it does not exist."""
|
||||
return IMPL.block_device_mapping_destroy_by_instance_and_volume(
|
||||
context, instance_id, volume_id)
|
||||
context, instance_uuid, volume_id)
|
||||
|
||||
|
||||
####################
|
||||
|
@ -1316,7 +1316,7 @@ def instance_destroy(context, instance_id):
|
||||
'deleted_at': utils.utcnow(),
|
||||
'updated_at': literal_column('updated_at')})
|
||||
session.query(models.BlockDeviceMapping).\
|
||||
filter_by(instance_id=instance_id).\
|
||||
filter_by(instance_uuid=instance_ref['uuid']).\
|
||||
update({'deleted': True,
|
||||
'deleted_at': utils.utcnow(),
|
||||
'updated_at': literal_column('updated_at')})
|
||||
@ -2726,7 +2726,7 @@ def block_device_mapping_update_or_create(context, values):
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
result = _block_device_mapping_get_query(context, session=session).\
|
||||
filter_by(instance_id=values['instance_id']).\
|
||||
filter_by(instance_uuid=values['instance_uuid']).\
|
||||
filter_by(device_name=values['device_name']).\
|
||||
first()
|
||||
if not result:
|
||||
@ -2742,7 +2742,7 @@ def block_device_mapping_update_or_create(context, values):
|
||||
if (virtual_name is not None and
|
||||
block_device.is_swap_or_ephemeral(virtual_name)):
|
||||
session.query(models.BlockDeviceMapping).\
|
||||
filter_by(instance_id=values['instance_id']).\
|
||||
filter_by(instance_uuid=values['instance_uuid']).\
|
||||
filter_by(virtual_name=virtual_name).\
|
||||
filter(models.BlockDeviceMapping.device_name !=
|
||||
values['device_name']).\
|
||||
@ -2752,9 +2752,9 @@ def block_device_mapping_update_or_create(context, values):
|
||||
|
||||
|
||||
@require_context
|
||||
def block_device_mapping_get_all_by_instance(context, instance_id):
|
||||
def block_device_mapping_get_all_by_instance(context, instance_uuid):
|
||||
return _block_device_mapping_get_query(context).\
|
||||
filter_by(instance_id=instance_id).\
|
||||
filter_by(instance_uuid=instance_uuid).\
|
||||
all()
|
||||
|
||||
|
||||
@ -2770,12 +2770,12 @@ def block_device_mapping_destroy(context, bdm_id):
|
||||
|
||||
|
||||
@require_context
|
||||
def block_device_mapping_destroy_by_instance_and_volume(context, instance_id,
|
||||
def block_device_mapping_destroy_by_instance_and_volume(context, instance_uuid,
|
||||
volume_id):
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
_block_device_mapping_get_query(context, session=session).\
|
||||
filter_by(instance_id=instance_id).\
|
||||
filter_by(instance_uuid=instance_uuid).\
|
||||
filter_by(volume_id=volume_id).\
|
||||
update({'deleted': True,
|
||||
'deleted_at': utils.utcnow(),
|
||||
|
@ -0,0 +1,81 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2011 OpenStack LLC.
|
||||
# Copyright 2012 Michael Still and Canonical Inc
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 select, Column, ForeignKey, Integer
|
||||
from sqlalchemy import MetaData, String, Table
|
||||
from migrate import ForeignKeyConstraint
|
||||
|
||||
from nova import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
dialect = migrate_engine.url.get_dialect().name
|
||||
block_device_mapping = Table('block_device_mapping', meta, autoload=True)
|
||||
instances = Table('instances', meta, autoload=True)
|
||||
uuid_column = Column('instance_uuid', String(36))
|
||||
uuid_column.create(block_device_mapping)
|
||||
|
||||
try:
|
||||
block_device_mapping.update().values(
|
||||
instance_uuid=select(
|
||||
[instances.c.uuid],
|
||||
instances.c.id == block_device_mapping.c.instance_id)
|
||||
).execute()
|
||||
except Exception:
|
||||
uuid_column.drop()
|
||||
raise
|
||||
|
||||
fkeys = list(block_device_mapping.c.instance_id.foreign_keys)
|
||||
if fkeys:
|
||||
try:
|
||||
fkey_name = fkeys[0].constraint.name
|
||||
ForeignKeyConstraint(
|
||||
columns=[block_device_mapping.c.instance_id],
|
||||
refcolumns=[instances.c.id],
|
||||
name=fkey_name).drop()
|
||||
except Exception:
|
||||
LOG.error(_("foreign key constraint couldn't be removed"))
|
||||
raise
|
||||
|
||||
block_device_mapping.c.instance_id.drop()
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
block_device_mapping = Table('block_device_mapping', meta, autoload=True)
|
||||
instances = Table('instances', meta, autoload=True)
|
||||
id_column = Column('instance_id', Integer, ForeignKey('instances.id'))
|
||||
id_column.create(block_device_mapping)
|
||||
|
||||
try:
|
||||
block_device_mapping.update().values(
|
||||
instance_id=select(
|
||||
[instances.c.id],
|
||||
instances.c.uuid == block_device_mapping.c.instance_uuid)
|
||||
).execute()
|
||||
except Exception:
|
||||
id_column.drop()
|
||||
raise
|
||||
|
||||
block_device_mapping.c.instance_uuid.drop()
|
@ -0,0 +1,97 @@
|
||||
BEGIN TRANSACTION;
|
||||
CREATE TEMPORARY TABLE block_device_mapping_backup (
|
||||
created_at DATETIME,
|
||||
updated_at DATETIME,
|
||||
deleted_at DATETIME,
|
||||
deleted BOOLEAN,
|
||||
id INTEGER NOT NULL,
|
||||
instance_id INTEGER NOT NULL,
|
||||
device_name VARCHAR(255) NOT NULL,
|
||||
delete_on_termination BOOLEAN,
|
||||
virtual_name VARCHAR(255),
|
||||
snapshot_id INTEGER,
|
||||
volume_id INTEGER,
|
||||
volume_size INTEGER,
|
||||
no_device BOOLEAN,
|
||||
connection_info TEXT,
|
||||
instance_uuid VARCHAR(36),
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY(snapshot_id) REFERENCES snapshots (id),
|
||||
CHECK (deleted IN (0, 1)),
|
||||
CHECK (delete_on_termination IN (0, 1)),
|
||||
CHECK (no_device IN (0, 1)),
|
||||
FOREIGN KEY(volume_id) REFERENCES volumes (id),
|
||||
FOREIGN KEY(instance_id) REFERENCES instances (id)
|
||||
);
|
||||
|
||||
INSERT INTO block_device_mapping_backup
|
||||
SELECT created_at,
|
||||
updated_at,
|
||||
deleted_at,
|
||||
deleted,
|
||||
id,
|
||||
NULL,
|
||||
device_name,
|
||||
delete_on_termination,
|
||||
virtual_name,
|
||||
snapshot_id,
|
||||
volume_id,
|
||||
volume_size,
|
||||
no_device,
|
||||
connection_info,
|
||||
instance_uuid
|
||||
FROM block_device_mapping;
|
||||
|
||||
UPDATE block_device_mapping_backup
|
||||
SET instance_id=
|
||||
(SELECT id
|
||||
FROM instances
|
||||
WHERE block_device_mapping_backup.instance_uuid = instances.uuid
|
||||
);
|
||||
|
||||
DROP TABLE block_device_mapping;
|
||||
|
||||
CREATE TABLE block_device_mapping (
|
||||
created_at DATETIME,
|
||||
updated_at DATETIME,
|
||||
deleted_at DATETIME,
|
||||
deleted BOOLEAN,
|
||||
id INTEGER NOT NULL,
|
||||
instance_id INTEGER NOT NULL,
|
||||
device_name VARCHAR(255) NOT NULL,
|
||||
delete_on_termination BOOLEAN,
|
||||
virtual_name VARCHAR(255),
|
||||
snapshot_id INTEGER,
|
||||
volume_id INTEGER,
|
||||
volume_size INTEGER,
|
||||
no_device BOOLEAN,
|
||||
connection_info TEXT,
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY(snapshot_id) REFERENCES snapshots (id),
|
||||
CHECK (deleted IN (0, 1)),
|
||||
CHECK (delete_on_termination IN (0, 1)),
|
||||
CHECK (no_device IN (0, 1)),
|
||||
FOREIGN KEY(volume_id) REFERENCES volumes (id),
|
||||
FOREIGN KEY(instance_id) REFERENCES instances (id)
|
||||
);
|
||||
|
||||
INSERT INTO block_device_mapping
|
||||
SELECT created_at,
|
||||
updated_at,
|
||||
deleted_at,
|
||||
deleted,
|
||||
id,
|
||||
instance_id,
|
||||
device_name,
|
||||
delete_on_termination,
|
||||
virtual_name,
|
||||
snapshot_id,
|
||||
volume_id,
|
||||
volume_size,
|
||||
no_device,
|
||||
connection_info
|
||||
FROM block_device_mapping_backup;
|
||||
|
||||
DROP TABLE block_device_mapping_backup;
|
||||
|
||||
COMMIT;
|
@ -0,0 +1,97 @@
|
||||
BEGIN TRANSACTION;
|
||||
CREATE TEMPORARY TABLE block_device_mapping_backup (
|
||||
created_at DATETIME,
|
||||
updated_at DATETIME,
|
||||
deleted_at DATETIME,
|
||||
deleted BOOLEAN,
|
||||
id INTEGER NOT NULL,
|
||||
instance_id INTEGER NOT NULL,
|
||||
device_name VARCHAR(255) NOT NULL,
|
||||
delete_on_termination BOOLEAN,
|
||||
virtual_name VARCHAR(255),
|
||||
snapshot_id INTEGER,
|
||||
volume_id INTEGER,
|
||||
volume_size INTEGER,
|
||||
no_device BOOLEAN,
|
||||
connection_info TEXT,
|
||||
instance_uuid VARCHAR(36),
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY(snapshot_id) REFERENCES snapshots (id),
|
||||
CHECK (deleted IN (0, 1)),
|
||||
CHECK (delete_on_termination IN (0, 1)),
|
||||
CHECK (no_device IN (0, 1)),
|
||||
FOREIGN KEY(volume_id) REFERENCES volumes (id),
|
||||
FOREIGN KEY(instance_id) REFERENCES instances (id)
|
||||
);
|
||||
|
||||
INSERT INTO block_device_mapping_backup
|
||||
SELECT created_at,
|
||||
updated_at,
|
||||
deleted_at,
|
||||
deleted,
|
||||
id,
|
||||
instance_id,
|
||||
device_name,
|
||||
delete_on_termination,
|
||||
virtual_name,
|
||||
snapshot_id,
|
||||
volume_id,
|
||||
volume_size,
|
||||
no_device,
|
||||
connection_info,
|
||||
NULL
|
||||
FROM block_device_mapping;
|
||||
|
||||
UPDATE block_device_mapping_backup
|
||||
SET instance_uuid=
|
||||
(SELECT uuid
|
||||
FROM instances
|
||||
WHERE block_device_mapping_backup.instance_id = instances.id
|
||||
);
|
||||
|
||||
DROP TABLE block_device_mapping;
|
||||
|
||||
CREATE TABLE block_device_mapping (
|
||||
created_at DATETIME,
|
||||
updated_at DATETIME,
|
||||
deleted_at DATETIME,
|
||||
deleted BOOLEAN,
|
||||
id INTEGER NOT NULL,
|
||||
device_name VARCHAR(255) NOT NULL,
|
||||
delete_on_termination BOOLEAN,
|
||||
virtual_name VARCHAR(255),
|
||||
snapshot_id INTEGER,
|
||||
volume_id INTEGER,
|
||||
volume_size INTEGER,
|
||||
no_device BOOLEAN,
|
||||
connection_info TEXT,
|
||||
instance_uuid VARCHAR(36),
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY(snapshot_id) REFERENCES snapshots (id),
|
||||
CHECK (deleted IN (0, 1)),
|
||||
CHECK (delete_on_termination IN (0, 1)),
|
||||
CHECK (no_device IN (0, 1)),
|
||||
FOREIGN KEY(volume_id) REFERENCES volumes (id),
|
||||
FOREIGN KEY(instance_uuid) REFERENCES instances (uuid)
|
||||
);
|
||||
|
||||
INSERT INTO block_device_mapping
|
||||
SELECT created_at,
|
||||
updated_at,
|
||||
deleted_at,
|
||||
deleted,
|
||||
id,
|
||||
device_name,
|
||||
delete_on_termination,
|
||||
virtual_name,
|
||||
snapshot_id,
|
||||
volume_id,
|
||||
volume_size,
|
||||
no_device,
|
||||
connection_info,
|
||||
instance_uuid
|
||||
FROM block_device_mapping_backup;
|
||||
|
||||
DROP TABLE block_device_mapping_backup;
|
||||
|
||||
COMMIT;
|
@ -23,12 +23,17 @@ import sys
|
||||
from nova.db.sqlalchemy.session import get_engine
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
from nova import log as logging
|
||||
|
||||
|
||||
import sqlalchemy
|
||||
import migrate
|
||||
from migrate.versioning import util as migrate_util
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@migrate_util.decorator
|
||||
def patched_with_engine(f, *a, **kw):
|
||||
url = a[0]
|
||||
|
@ -482,12 +482,14 @@ class BlockDeviceMapping(BASE, NovaBase):
|
||||
__tablename__ = "block_device_mapping"
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
|
||||
instance_id = Column(Integer, ForeignKey('instances.id'), nullable=False)
|
||||
instance_uuid = Column(Integer, ForeignKey('instances.uuid'),
|
||||
nullable=False)
|
||||
instance = relationship(Instance,
|
||||
backref=backref('balock_device_mapping'),
|
||||
foreign_keys=instance_id,
|
||||
primaryjoin='and_(BlockDeviceMapping.instance_id=='
|
||||
'Instance.id,'
|
||||
foreign_keys=instance_uuid,
|
||||
primaryjoin='and_(BlockDeviceMapping.'
|
||||
'instance_uuid=='
|
||||
'Instance.uuid,'
|
||||
'BlockDeviceMapping.deleted=='
|
||||
'False)')
|
||||
device_name = Column(String(255), nullable=False)
|
||||
|
@ -945,42 +945,43 @@ class CloudTestCase(test.TestCase):
|
||||
'root_device_name': '/dev/sdc1'})
|
||||
|
||||
instance_id = inst1['id']
|
||||
instance_uuid = inst1['uuid']
|
||||
mappings0 = [
|
||||
{'instance_id': instance_id,
|
||||
{'instance_uuid': instance_uuid,
|
||||
'device_name': '/dev/sdb1',
|
||||
'snapshot_id': '1',
|
||||
'volume_id': '2'},
|
||||
{'instance_id': instance_id,
|
||||
{'instance_uuid': instance_uuid,
|
||||
'device_name': '/dev/sdb2',
|
||||
'volume_id': '3',
|
||||
'volume_size': 1},
|
||||
{'instance_id': instance_id,
|
||||
{'instance_uuid': instance_uuid,
|
||||
'device_name': '/dev/sdb3',
|
||||
'delete_on_termination': True,
|
||||
'snapshot_id': '4',
|
||||
'volume_id': '5'},
|
||||
{'instance_id': instance_id,
|
||||
{'instance_uuid': instance_uuid,
|
||||
'device_name': '/dev/sdb4',
|
||||
'delete_on_termination': False,
|
||||
'snapshot_id': '6',
|
||||
'volume_id': '7'},
|
||||
{'instance_id': instance_id,
|
||||
{'instance_uuid': instance_uuid,
|
||||
'device_name': '/dev/sdb5',
|
||||
'snapshot_id': '8',
|
||||
'volume_id': '9',
|
||||
'volume_size': 0},
|
||||
{'instance_id': instance_id,
|
||||
{'instance_uuid': instance_uuid,
|
||||
'device_name': '/dev/sdb6',
|
||||
'snapshot_id': '10',
|
||||
'volume_id': '11',
|
||||
'volume_size': 1},
|
||||
{'instance_id': instance_id,
|
||||
{'instance_uuid': instance_uuid,
|
||||
'device_name': '/dev/sdb7',
|
||||
'no_device': True},
|
||||
{'instance_id': instance_id,
|
||||
{'instance_uuid': instance_uuid,
|
||||
'device_name': '/dev/sdb8',
|
||||
'virtual_name': 'swap'},
|
||||
{'instance_id': instance_id,
|
||||
{'instance_uuid': instance_uuid,
|
||||
'device_name': '/dev/sdb9',
|
||||
'virtual_name': 'ephemeral3'}]
|
||||
|
||||
@ -990,9 +991,9 @@ class CloudTestCase(test.TestCase):
|
||||
def _tearDownBlockDeviceMapping(self, inst1, inst2, volumes):
|
||||
for vol in volumes:
|
||||
db.volume_destroy(self.context, vol['id'])
|
||||
for id in (inst1['id'], inst2['id']):
|
||||
for uuid in (inst1['uuid'], inst2['uuid']):
|
||||
for bdm in db.block_device_mapping_get_all_by_instance(
|
||||
self.context, id):
|
||||
self.context, uuid):
|
||||
db.block_device_mapping_destroy(self.context, bdm['id'])
|
||||
db.instance_destroy(self.context, inst2['id'])
|
||||
db.instance_destroy(self.context, inst1['id'])
|
||||
@ -1043,8 +1044,8 @@ class CloudTestCase(test.TestCase):
|
||||
(inst1, inst2, volumes) = self._setUpBlockDeviceMapping()
|
||||
|
||||
result = {}
|
||||
self.cloud._format_instance_bdm(self.context, inst1['id'], '/dev/sdb1',
|
||||
result)
|
||||
self.cloud._format_instance_bdm(self.context, inst1['uuid'],
|
||||
'/dev/sdb1', result)
|
||||
self.assertSubDictMatch(
|
||||
{'rootDeviceType': self._expected_instance_bdm1['rootDeviceType']},
|
||||
result)
|
||||
@ -1052,8 +1053,8 @@ class CloudTestCase(test.TestCase):
|
||||
self._expected_block_device_mapping0, result['blockDeviceMapping'])
|
||||
|
||||
result = {}
|
||||
self.cloud._format_instance_bdm(self.context, inst2['id'], '/dev/sdc1',
|
||||
result)
|
||||
self.cloud._format_instance_bdm(self.context, inst2['uuid'],
|
||||
'/dev/sdc1', result)
|
||||
self.assertSubDictMatch(
|
||||
{'rootDeviceType': self._expected_instance_bdm2['rootDeviceType']},
|
||||
result)
|
||||
@ -2166,6 +2167,7 @@ class CloudTestCase(test.TestCase):
|
||||
def fake_get(ctxt, instance_id):
|
||||
return {
|
||||
'id': 0,
|
||||
'uuid': 'e5fe5518-0288-4fa3-b0c4-c79764101b85',
|
||||
'root_device_name': '/dev/sdh',
|
||||
'security_groups': [{'name': 'fake0'}, {'name': 'fake1'}],
|
||||
'vm_state': vm_states.STOPPED,
|
||||
|
@ -124,7 +124,7 @@ class EC2ValidateTestCase(test.TestCase):
|
||||
instance_id='i-1234',
|
||||
device='/dev/vdc')
|
||||
|
||||
def test_describe_instance_ttribute(self):
|
||||
def test_describe_instance_attribute(self):
|
||||
for ec2_id, e in self.ec2_id_exception_map:
|
||||
self.assertRaises(e,
|
||||
self.cloud.describe_instance_attribute,
|
||||
|
@ -1402,37 +1402,38 @@ class ComputeTestCase(BaseTestCase):
|
||||
"""Confirm exception when pre_live_migration fails."""
|
||||
# creating instance testdata
|
||||
inst_ref = self._create_fake_instance({'host': 'dummy'})
|
||||
instance_id = inst_ref['id']
|
||||
|
||||
c = context.get_admin_context()
|
||||
topic = db.queue_get_for(c, FLAGS.compute_topic, inst_ref['host'])
|
||||
# creating volume testdata
|
||||
volume_id = 1
|
||||
db.volume_create(c, {'id': volume_id})
|
||||
values = {'instance_id': instance_id, 'device_name': '/dev/vdc',
|
||||
'delete_on_termination': False, 'volume_id': volume_id}
|
||||
values = {'instance_uuid': inst_ref['uuid'], 'device_name': '/dev/vdc',
|
||||
'delete_on_termination': False, 'volume_id': volume_id}
|
||||
db.block_device_mapping_create(c, values)
|
||||
|
||||
# creating mocks
|
||||
self.mox.StubOutWithMock(rpc, 'call')
|
||||
rpc.call(c, FLAGS.volume_topic, {"method": "check_for_export",
|
||||
"args": {'instance_id': instance_id}})
|
||||
rpc.call(c, FLAGS.volume_topic,
|
||||
{"method": "check_for_export",
|
||||
"args": {'instance_id': inst_ref['id']}})
|
||||
|
||||
self.mox.StubOutWithMock(self.compute.driver, 'get_instance_disk_info')
|
||||
self.compute.driver.get_instance_disk_info(inst_ref.name)
|
||||
|
||||
rpc.call(c, topic,
|
||||
{"method": "pre_live_migration",
|
||||
"args": {'instance_id': instance_id,
|
||||
"args": {'instance_id': inst_ref['id'],
|
||||
'block_migration': True,
|
||||
'disk': None}
|
||||
}).AndRaise(rpc.common.RemoteError('', '', ''))
|
||||
# mocks for rollback
|
||||
rpc.call(c, 'network', {'method': 'setup_networks_on_host',
|
||||
'args': {'instance_id': instance_id,
|
||||
'args': {'instance_id': inst_ref['id'],
|
||||
'host': self.compute.host,
|
||||
'teardown': False}})
|
||||
rpc.call(c, topic, {"method": "remove_volume_connection",
|
||||
"args": {'instance_id': instance_id,
|
||||
"args": {'instance_id': inst_ref['id'],
|
||||
'volume_id': volume_id}})
|
||||
rpc.cast(c, topic, {"method": "rollback_live_migration_at_destination",
|
||||
"args": {'instance_id': inst_ref['id']}})
|
||||
@ -1441,11 +1442,11 @@ class ComputeTestCase(BaseTestCase):
|
||||
self.mox.ReplayAll()
|
||||
self.assertRaises(rpc_common.RemoteError,
|
||||
self.compute.live_migration,
|
||||
c, instance_id, inst_ref['host'], True)
|
||||
c, inst_ref['id'], inst_ref['host'], True)
|
||||
|
||||
# cleanup
|
||||
for bdms in db.block_device_mapping_get_all_by_instance(c,
|
||||
instance_id):
|
||||
for bdms in db.block_device_mapping_get_all_by_instance(
|
||||
c, inst_ref['uuid']):
|
||||
db.block_device_mapping_destroy(c, bdms['id'])
|
||||
db.volume_destroy(c, volume_id)
|
||||
db.instance_destroy(c, inst_ref['id'])
|
||||
@ -1675,7 +1676,7 @@ class ComputeTestCase(BaseTestCase):
|
||||
|
||||
self.mox.StubOutWithMock(self.compute, "_cleanup_volumes")
|
||||
self.compute._cleanup_volumes(admin_context,
|
||||
instance['id']).AndReturn(None)
|
||||
instance['uuid']).AndReturn(None)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
self.compute._cleanup_running_deleted_instances(admin_context)
|
||||
@ -3095,11 +3096,11 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
'no_device': True}]
|
||||
|
||||
self.compute_api._update_image_block_device_mapping(
|
||||
self.context, instance_type, instance['id'], mappings)
|
||||
self.context, instance_type, instance['uuid'], mappings)
|
||||
|
||||
bdms = [self._parse_db_block_device_mapping(bdm_ref)
|
||||
for bdm_ref in db.block_device_mapping_get_all_by_instance(
|
||||
self.context, instance['id'])]
|
||||
self.context, instance['uuid'])]
|
||||
expected_result = [
|
||||
{'virtual_name': 'swap', 'device_name': '/dev/sdb1',
|
||||
'volume_size': swap_size},
|
||||
@ -3116,10 +3117,10 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
|
||||
self.compute_api._update_block_device_mapping(
|
||||
self.context, instance_types.get_default_instance_type(),
|
||||
instance['id'], block_device_mapping)
|
||||
instance['uuid'], block_device_mapping)
|
||||
bdms = [self._parse_db_block_device_mapping(bdm_ref)
|
||||
for bdm_ref in db.block_device_mapping_get_all_by_instance(
|
||||
self.context, instance['id'])]
|
||||
self.context, instance['uuid'])]
|
||||
expected_result = [
|
||||
{'snapshot_id': 0x12345678, 'device_name': '/dev/sda1'},
|
||||
|
||||
@ -3143,7 +3144,7 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
self.assertDictListMatch(bdms, expected_result)
|
||||
|
||||
for bdm in db.block_device_mapping_get_all_by_instance(
|
||||
self.context, instance['id']):
|
||||
self.context, instance['uuid']):
|
||||
db.block_device_mapping_destroy(self.context, bdm['id'])
|
||||
instance = db.instance_get_by_uuid(self.context, instance['uuid'])
|
||||
self.compute.terminate_instance(self.context, instance['uuid'])
|
||||
|
@ -47,20 +47,21 @@ class MetadataTestCase(test.TestCase):
|
||||
def setUp(self):
|
||||
super(MetadataTestCase, self).setUp()
|
||||
self.instance = ({'id': 1,
|
||||
'name': 'fake',
|
||||
'project_id': 'test',
|
||||
'key_name': None,
|
||||
'host': 'test',
|
||||
'launch_index': 1,
|
||||
'instance_type': {'name': 'm1.tiny'},
|
||||
'reservation_id': 'r-xxxxxxxx',
|
||||
'user_data': '',
|
||||
'image_ref': 7,
|
||||
'vcpus': 1,
|
||||
'fixed_ips': [],
|
||||
'root_device_name': '/dev/sda1',
|
||||
'info_cache': {'network_info': []},
|
||||
'hostname': 'test'})
|
||||
'uuid': 'b65cee2f-8c69-4aeb-be2f-f79742548fc2',
|
||||
'name': 'fake',
|
||||
'project_id': 'test',
|
||||
'key_name': None,
|
||||
'host': 'test',
|
||||
'launch_index': 1,
|
||||
'instance_type': {'name': 'm1.tiny'},
|
||||
'reservation_id': 'r-xxxxxxxx',
|
||||
'user_data': '',
|
||||
'image_ref': 7,
|
||||
'vcpus': 1,
|
||||
'fixed_ips': [],
|
||||
'root_device_name': '/dev/sda1',
|
||||
'info_cache': {'network_info': []},
|
||||
'hostname': 'test'})
|
||||
|
||||
def fake_get_floating_ips_by_fixed_address(self, context, fixed_ip):
|
||||
return ['1.2.3.4', '5.6.7.8']
|
||||
@ -144,11 +145,13 @@ class MetadataTestCase(test.TestCase):
|
||||
"""Make sure that _get_instance_mapping works"""
|
||||
ctxt = None
|
||||
instance_ref0 = {'id': 0,
|
||||
'uuid': 'e5fe5518-0288-4fa3-b0c4-c79764101b85',
|
||||
'root_device_name': None}
|
||||
instance_ref1 = {'id': 0,
|
||||
'uuid': 'b65cee2f-8c69-4aeb-be2f-f79742548fc2',
|
||||
'root_device_name': '/dev/sda1'}
|
||||
|
||||
def fake_bdm_get(ctxt, id):
|
||||
def fake_bdm_get(ctxt, uuid):
|
||||
return [{'volume_id': 87654321,
|
||||
'snapshot_id': None,
|
||||
'no_device': None,
|
||||
|
Loading…
Reference in New Issue
Block a user