summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Smith <dansmith@redhat.com>2015-04-22 09:02:03 -0700
committerDan Smith <dansmith@redhat.com>2015-04-23 06:53:21 -0700
commita2872a9262985bd0ee2c6df4f7593947e0516406 (patch)
tree9ad1c96d3900f2eab1126b2709e1a73bb2179fd1
parenta0efbbcfc701563473e0dc42ca5b6b4b57ca7d5a (diff)
downloadnova-a2872a9262985bd0ee2c6df4f7593947e0516406.tar.gz
Fix migrate_flavor_data() to catch instances with no instance_extra rows
The way the query was being performed previously, we would not see any instances that didn't have a row in instance_extra. This could happen if an instance hasn't been touched for several releases, or if the data set is old. The fix is a simple change to use outerjoin instead of join. This patch includes a test that ensures that instances with no instance_extra rows are included in the migration. If we query an instance without such a row, we create it before doing a save on the instance. Closes-Bug: #1447132 Change-Id: I2620a8a4338f5c493350f26cdba3e41f3cb28de7 (cherry picked from commit 92714accc49e85579f406de10ef8b3b510277037)
-rw-r--r--nova/db/sqlalchemy/api.py7
-rw-r--r--nova/tests/unit/db/test_db_api.py25
2 files changed, 31 insertions, 1 deletions
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index fc35a5faee..64c6724e64 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -6041,7 +6041,7 @@ def migrate_flavor_data(context, max_count, flavor_cache):
from nova import objects
query = _instance_get_all_query(context, joins=['extra', 'extra.flavor']).\
- join(models.Instance.extra).\
+ outerjoin(models.Instance.extra).\
filter(models.InstanceExtra.flavor.is_(None))
if max_count is not None:
instances = query.limit(max_count)
@@ -6069,6 +6069,11 @@ def migrate_flavor_data(context, max_count, flavor_cache):
_augment_flavors_to_migrate(instance, flavor_cache)
if instance.obj_what_changed():
+ if db_instance.get('extra') is None:
+ _instance_extra_create(context,
+ {'instance_uuid': db_instance['uuid']})
+ LOG.debug(
+ 'Created instance_extra for %s' % db_instance['uuid'])
instance.save(expected_task_state=[None])
count_hit += 1
diff --git a/nova/tests/unit/db/test_db_api.py b/nova/tests/unit/db/test_db_api.py
index 8fc8d540fe..7cc9c94a52 100644
--- a/nova/tests/unit/db/test_db_api.py
+++ b/nova/tests/unit/db/test_db_api.py
@@ -7629,6 +7629,31 @@ class FlavorMigrationTestCase(test.TestCase):
self.assertEqual(3, match)
self.assertEqual(0, done)
+ def test_migrate_flavor_gets_missing_extra_rows(self):
+ ctxt = context.get_admin_context()
+ flavor = flavors.get_default_flavor()
+ sysmeta = flavors.save_flavor_info({}, flavor)
+ values1 = {'uuid': str(stdlib_uuid.uuid4()),
+ 'system_metadata': sysmeta,
+ 'extra': {'flavor': None},
+ }
+ db.instance_create(ctxt, values1)
+ values2 = {'uuid': str(stdlib_uuid.uuid4()),
+ 'system_metadata': sysmeta,
+ }
+ inst2 = db.instance_create(ctxt, values2)
+ sqlalchemy_api.model_query(ctxt, models.InstanceExtra).\
+ filter_by(instance_uuid=inst2.uuid).delete()
+
+ self.assertIsNone(db.instance_extra_get_by_instance_uuid(
+ ctxt, inst2.uuid))
+ match, done = db.migrate_flavor_data(ctxt, None, {})
+ self.assertEqual(2, match)
+ self.assertEqual(2, done)
+ extra = db.instance_extra_get_by_instance_uuid(ctxt, inst2.uuid)
+ self.assertIsNotNone(extra)
+ self.assertIsNotNone(extra.flavor)
+
class ArchiveTestCase(test.TestCase):