Merge "Improve the performance of migration 186"

This commit is contained in:
Jenkins
2013-06-13 05:35:56 +00:00
committed by Gerrit Code Review
2 changed files with 81 additions and 66 deletions
@@ -52,10 +52,11 @@ def strip_dev(device_name):
def upgrade(migrate_engine):
meta = MetaData(bind=migrate_engine)
for table in ('block_device_mapping', 'shadow_block_device_mapping'):
block_device_mapping = Table(table,
meta, autoload=True)
tables = [Table(table, meta, autoload=True)
for table in
('block_device_mapping', 'shadow_block_device_mapping')]
for block_device_mapping in tables:
source_type = Column('source_type', String(255))
destination_type = Column('destination_type', String(255))
guest_format = Column('guest_format', String(255))
@@ -75,8 +76,9 @@ def upgrade(migrate_engine):
device_name = block_device_mapping.c.device_name
device_name.alter(nullable=True)
_upgrade_bdm_v2(meta, block_device_mapping)
_upgrade_bdm_v2(meta, *tables)
for block_device_mapping in tables:
virtual_name = block_device_mapping.c.virtual_name
virtual_name.drop()
@@ -104,7 +106,7 @@ def downgrade(migrate_engine):
block_device_mapping.c.image_id.drop()
def _upgrade_bdm_v2(meta, bdm_table):
def _upgrade_bdm_v2(meta, bdm_table, bdm_shadow_table):
# Rows needed to do the upgrade
_bdm_rows_v1 = ('id', 'device_name', 'virtual_name',
'snapshot_id', 'volume_id', 'instance_uuid')
@@ -112,6 +114,8 @@ def _upgrade_bdm_v2(meta, bdm_table):
_bdm_rows_v2 = ('id', 'source_type', 'destination_type', 'guest_format',
'device_type', 'disk_bus', 'boot_index', 'image_id')
_instance_cols = ('uuid', 'image_ref', 'root_device_name')
def _get_columns(table, names):
return [getattr(table.c, name) for name in names]
@@ -126,85 +130,92 @@ def _upgrade_bdm_v2(meta, bdm_table):
instance_table = Table('instances', meta, autoload=True)
instance_shadow_table = Table('shadow_instances', meta, autoload=True)
for instance in itertools.chain(
instance_table.select().execute().fetchall(),
instance_shadow_table.select().execute().fetchall()):
# Get all the bdms for an instance
bdm_q = select(_get_columns(bdm_table, _bdm_rows_v1)).where(
bdm_table.c.instance_uuid == instance.uuid)
live_q = select(_get_columns(instance_table, _instance_cols) +
_get_columns(bdm_table, _bdm_rows_v1),
from_obj=instance_table.join(bdm_table,
instance_table.c.uuid == bdm_table.c.instance_uuid))
bdms_v1 = [val for val in bdm_q.execute().fetchall()]
bdms_v2 = []
image_bdm = None
live_on_shadow_q = select(_get_columns(instance_table, _instance_cols) +
_get_columns(bdm_shadow_table, _bdm_rows_v1),
from_obj=instance_table.join(bdm_shadow_table,
instance_table.c.uuid ==
bdm_shadow_table.c.instance_uuid))
for bdm in bdms_v1:
bdm_v2 = _default_bdm()
# Copy over some fields we'll need
bdm_v2['id'] = bdm['id']
bdm_v2['device_name'] = bdm['device_name']
shadow_q = select(_get_columns(instance_shadow_table, _instance_cols) +
_get_columns(bdm_shadow_table, _bdm_rows_v1),
from_obj=instance_shadow_table.join(bdm_shadow_table,
instance_shadow_table.c.uuid ==
bdm_shadow_table.c.instance_uuid))
virt_name = bdm.virtual_name
if _is_swap_or_ephemeral(virt_name):
bdm_v2['source_type'] = 'blank'
instance_image_dict = {}
if virt_name == 'swap':
bdm_v2['guest_format'] = 'swap'
else:
bdm_v2['guest_format'] = CONF.default_ephemeral_format
for ((instance_uuid, instance_image_ref, instance_root_device,
bdm_id, device_name, virtual_name, snapshot_id, volume_id,
_), is_shadow) in itertools.chain(
((data, False) for data in live_q.execute().fetchall()),
((data, True) for data in live_on_shadow_q.execute().fetchall()),
((data, True) for data in shadow_q.execute().fetchall())):
bdms_v2.append(bdm_v2)
elif bdm.snapshot_id:
bdm_v2['source_type'] = 'snapshot'
bdm_v2['destination_type'] = 'volume'
bdms_v2.append(bdm_v2)
elif bdm.volume_id:
bdm_v2['source_type'] = 'volume'
bdm_v2['destination_type'] = 'volume'
bdms_v2.append(bdm_v2)
else: # Log a warning that the bdm is not as expected
LOG.warn("Got an unexpected block device %s"
"that cannot be converted to v2 format" % bdm)
if instance.image_ref:
if instance_image_ref and instance_uuid not in instance_image_dict:
image_bdm = _default_bdm()
image_bdm['source_type'] = 'image'
image_bdm['instance_uuid'] = instance.uuid
image_bdm['image_id'] = instance.image_ref
image_bdm['instance_uuid'] = instance_uuid
image_bdm['image_id'] = instance_image_ref
image_bdm['boot_index'] = 0
instance_image_dict[instance_uuid] = image_bdm
bdm_v2 = _default_bdm()
# Copy over some fields we'll need
bdm_v2['id'] = bdm_id
bdm_v2['device_name'] = device_name
virt_name = virtual_name
if _is_swap_or_ephemeral(virt_name):
bdm_v2['source_type'] = 'blank'
if virt_name == 'swap':
bdm_v2['guest_format'] = 'swap'
else:
bdm_v2['guest_format'] = CONF.default_ephemeral_format
elif snapshot_id:
bdm_v2['source_type'] = 'snapshot'
bdm_v2['destination_type'] = 'volume'
elif volume_id:
bdm_v2['source_type'] = 'volume'
bdm_v2['destination_type'] = 'volume'
else: # Log a warning that the bdm is not as expected
LOG.warn("Got an unexpected block device %s"
"that cannot be converted to v2 format")
# NOTE (ndipanov): Mark only the image or the bootable volume
# with boot index, as we don't support it yet.
# Also, make sure that instances started with
# the old syntax of specifying an image *and*
# a bootable volume still have consistend data.
bootable = [bdm for bdm in bdms_v2
if strip_dev(bdm['device_name']) ==
strip_dev(instance.root_device_name)
and bdm['source_type'] != 'blank']
bootable = ((strip_dev(device_name) ==
strip_dev(instance_root_device))
and bdm_v2['source_type'] != 'blank')
if len(bootable) > 1:
LOG.warn("Found inconsistent block device data for "
"instance %s - non-unique bootable device."
% instance.uuid)
if bootable:
bootable[0]['boot_index'] = 0
elif instance.image_ref:
image_bdm['boot_index'] = 0
else:
LOG.warn("No bootable device found for instance %s."
% instance.uuid)
bdm_v2['boot_index'] = 0
if instance_uuid in instance_image_dict:
instance_image_dict[instance_uuid]['boot_index'] = -1
# Update the DB
if image_bdm:
bdm_table.insert().values(**image_bdm).execute()
my_table = bdm_table
if is_shadow:
my_table = bdm_shadow_table
for bdm in bdms_v2:
bdm_table.update().where(
bdm_table.c.id == bdm['id']
).values(**bdm).execute()
my_table.update().where(
my_table.c.id == bdm_id
).values(**bdm_v2).execute()
# Create image bdms
for instance_uuid, image_bdm in instance_image_dict.iteritems():
bdm_table.insert().values(**image_bdm).execute()
def _downgrade_bdm_v2(meta, bdm_table):
+4
View File
@@ -1523,6 +1523,10 @@ class TestNovaMigrations(BaseMigrationTestCase, CommonTestsMixIn):
for q in instance_qs
)
self.assertEqual(len(bdm_1s), 3)
self.assertEqual(len(bdm_2s), 2)
self.assertEqual(len(bdm_3s), 4)
# Instance 1
self.assertEqual(bdm_1s[0].source_type, 'volume')
self.assertEqual(bdm_1s[0].destination_type, 'volume')