Add online migration to store keypairs with instances
This migrates instances to have embedded keypairs. Related to blueprint cells-keypairs-api-db Change-Id: I73378ace8cdde230b2204747230df37529284b16
This commit is contained in:
parent
f3a6a46fa3
commit
119f2c513d
@ -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):
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user