Warn the user about orphaned extra records during keypair migration

Operators who have manually deleted Instance records with FK constraints
disabled may have orphaned InstanceExtra records which will prevent the
keypair migration from running. Normally, this violation of the data
model would be something that earns no sympathy. However, that solution
was (incorrectly) offered up as a workaround in bug 1511466 and multiple
deployments have broken their data as a result. Since the experience
is a unhelpful error message and a blocked migration, this patch attempts
to at least highlight the problem, even though it is on the operator to
actually fix the problem.

Change-Id: I0c8bf2c495a98c412eb93e19f832948a779bca11
Related-Bug: #1684861
(cherry picked from commit 2cee5bb4d1)
This commit is contained in:
Dan Smith 2017-04-20 09:12:45 -07:00 committed by Lee Yarwood
parent 47774935ac
commit 593e708114
2 changed files with 19 additions and 1 deletions

View File

@ -1384,6 +1384,12 @@ def _migrate_instance_keypairs(ctxt, count):
count_all = len(db_extras)
count_hit = 0
for db_extra in db_extras:
if db_extra.instance is None:
LOG.error(
('Instance %(uuid)s has been purged, but an instance_extra '
'record remains for it. Unable to migrate.'),
{'uuid': db_extra.instance_uuid})
continue
key_name = db_extra.instance.key_name
keypairs = objects.KeyPairList(objects=[])
if key_name:

View File

@ -1973,8 +1973,20 @@ class TestInstanceObjectMisc(test.TestCase):
key_name='missingkey')
inst3.create()
inst4 = objects.Instance(context=ctxt,
user_id=ctxt.user_id,
project_id=ctxt.project_id,
key_name='missingkey')
inst4.create()
inst4.destroy()
# NOTE(danms): Add an orphaned instance_extra record for
# a totally invalid instance to make sure we don't explode.
# See bug 1684861 for more information.
db.instance_extra_update_by_uuid(ctxt, 'foo', {})
hit, done = instance.migrate_instance_keypairs(ctxt, 10)
self.assertEqual(2, hit)
self.assertEqual(3, hit)
self.assertEqual(2, done)
db_extra = db.instance_extra_get_by_instance_uuid(
ctxt, inst1.uuid, ['keypairs'])