Merge "Add online migration to store keypairs with instances"

This commit is contained in:
Jenkins 2016-05-13 20:17:03 +00:00 committed by Gerrit Code Review
commit a4113da58b
3 changed files with 80 additions and 1 deletions

View File

@ -81,6 +81,7 @@ from nova import exception
from nova.i18n import _
from nova import objects
from nova.objects import flavor as flavor_obj
from nova.objects import instance as instance_obj
from nova import quota
from nova import rpc
from nova import utils
@ -725,6 +726,7 @@ class DbCommands(object):
db.aggregate_uuids_online_data_migration,
flavor_obj.migrate_flavors,
flavor_obj.migrate_flavor_reset_autoincrement,
instance_obj.migrate_instance_keypairs,
)
def __init__(self):

View File

@ -20,13 +20,16 @@ from oslo_log import log as logging
from oslo_serialization import jsonutils
from oslo_utils import timeutils
from oslo_utils import versionutils
from sqlalchemy.orm import joinedload
from nova.cells import opts as cells_opts
from nova.cells import rpcapi as cells_rpcapi
from nova.cells import utils as cells_utils
from nova import db
from nova.db.sqlalchemy import api as db_api
from nova.db.sqlalchemy import models
from nova import exception
from nova.i18n import _LE
from nova.i18n import _LE, _LW
from nova import notifications
from nova import objects
from nova.objects import base
@ -1260,3 +1263,38 @@ class InstanceList(base.ObjectListBase, base.NovaObject):
instance.obj_reset_changes(['fault'])
return faults_by_uuid.keys()
@db_api.main_context_manager.writer
def _migrate_instance_keypairs(ctxt, count):
db_extras = ctxt.session.query(models.InstanceExtra).\
options(joinedload('instance')).\
filter_by(keypairs=None).\
filter_by(deleted=0).\
limit(count).\
all()
count_all = len(db_extras)
count_hit = 0
for db_extra in db_extras:
key_name = db_extra.instance.key_name
keypairs = objects.KeyPairList(objects=[])
if key_name:
try:
key = objects.KeyPair.get_by_name(ctxt,
db_extra.instance.user_id,
key_name)
keypairs.objects.append(key)
except exception.KeypairNotFound:
LOG.warning(
_LW('Instance %(uuid)s keypair %(keyname)s not found'),
{'uuid': db_extra.instance_uuid, 'keyname': key_name})
db_extra.keypairs = jsonutils.dumps(keypairs.obj_to_primitive())
db_extra.save(ctxt.session)
count_hit += 1
return count_all, count_hit
def migrate_instance_keypairs(ctxt, count):
return _migrate_instance_keypairs(ctxt, count)

View File

@ -23,6 +23,7 @@ from oslo_utils import timeutils
from nova.cells import rpcapi as cells_rpcapi
from nova.compute import flavors
from nova import context
from nova import db
from nova import exception
from nova.network import model as network_model
@ -1731,3 +1732,41 @@ class TestInstanceObjectMisc(test.TestCase):
self.assertEqual(['metadata', 'extra', 'extra.numa_topology'],
instance._expected_cols(['metadata',
'numa_topology']))
def test_migrate_instance_keypairs(self):
ctxt = context.RequestContext('foo', 'bar')
key = objects.KeyPair(context=ctxt,
user_id=ctxt.user_id,
name='testkey',
public_key='keydata',
type='ssh')
key.create()
inst1 = objects.Instance(context=ctxt,
user_id=ctxt.user_id,
project_id=ctxt.project_id,
key_name='testkey')
inst1.create()
inst2 = objects.Instance(context=ctxt,
user_id=ctxt.user_id,
project_id=ctxt.project_id,
key_name='testkey',
keypairs=objects.KeyPairList(
objects=[key]))
inst2.create()
inst3 = objects.Instance(context=ctxt,
user_id=ctxt.user_id,
project_id=ctxt.project_id,
key_name='missingkey')
inst3.create()
hit, done = instance.migrate_instance_keypairs(ctxt, 10)
self.assertEqual(2, hit)
self.assertEqual(2, done)
db_extra = db.instance_extra_get_by_instance_uuid(
ctxt, inst1.uuid, ['keypairs'])
self.assertIsNotNone(db_extra.keypairs)
db_extra = db.instance_extra_get_by_instance_uuid(
ctxt, inst3.uuid, ['keypairs'])
obj = base.NovaObject.obj_from_primitive(
jsonutils.loads(db_extra['keypairs']))
self.assertEqual([], obj.objects)