db: Add resources column in instance_extra table

This change adds a resources deferred-load column to instance_extra,
which will stores a list of resources for a given instance in the
form of a JSON blob.

Change-Id: I26d1fa8d0dc2fdf066f3a7017a74cda679d3efa1
Partially-Implements: blueprint virtual-persistent-memory
Co-Authored-By: He Jie Xu <hejie.xu@intel.com>
This commit is contained in:
LuyaoZhong 2019-08-26 12:32:53 +00:00
parent 5254153e76
commit 6a4d6ec786
5 changed files with 49 additions and 8 deletions

View File

@ -1777,7 +1777,7 @@ def instance_create(context, values):
'pci_requests': None,
'vcpu_model': None,
'trusted_certs': None,
'vpmems': None,
'resources': None,
})
instance_ref['extra'].update(values.pop('extra', {}))
instance_ref.update(values)
@ -3066,7 +3066,7 @@ def instance_extra_get_by_instance_uuid(context, instance_uuid,
filter_by(instance_uuid=instance_uuid)
if columns is None:
columns = ['numa_topology', 'pci_requests', 'flavor', 'vcpu_model',
'trusted_certs', 'vpmems', 'migration_context']
'trusted_certs', 'resources', 'migration_context']
for column in columns:
query = query.options(undefer(column))
instance_extra = query.first()

View File

@ -0,0 +1,31 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from sqlalchemy import Column
from sqlalchemy import MetaData
from sqlalchemy import Table
from sqlalchemy import Text
BASE_TABLE_NAME = 'instance_extra'
NEW_COLUMN_NAME = 'resources'
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
for prefix in ('', 'shadow_'):
table = Table(prefix + BASE_TABLE_NAME, meta, autoload=True)
new_column = Column(NEW_COLUMN_NAME, Text, nullable=True)
if not hasattr(table.c, NEW_COLUMN_NAME):
table.create_column(new_column)

View File

@ -391,7 +391,9 @@ class InstanceExtra(BASE, NovaBase, models.SoftDeleteMixin):
migration_context = orm.deferred(Column(Text))
keypairs = orm.deferred(Column(Text))
trusted_certs = orm.deferred(Column(Text))
vpmems = orm.deferred(Column(Text))
# NOTE(Luyao): 'vpmems' is still in the database
# and can be removed in the future release.
resources = orm.deferred(Column(Text))
instance = orm.relationship(Instance,
backref=orm.backref('extra',
uselist=False),

View File

@ -3372,7 +3372,7 @@ class InstanceExtraTestCase(test.TestCase):
db.instance_extra_update_by_uuid(self.ctxt, self.instance['uuid'],
{'numa_topology': 'changed',
'trusted_certs': "['123', 'foo']",
'vpmems': "['vpmem0', 'vpmem1']",
'resources': "['res0', 'res1']",
})
inst_extra = db.instance_extra_get_by_instance_uuid(
self.ctxt, self.instance['uuid'])
@ -3380,7 +3380,7 @@ class InstanceExtraTestCase(test.TestCase):
# NOTE(jackie-truong): trusted_certs is stored as a Text type in
# instance_extra and read as a list of strings
self.assertEqual("['123', 'foo']", inst_extra.trusted_certs)
self.assertEqual("['vpmem0', 'vpmem1']", inst_extra.vpmems)
self.assertEqual("['res0', 'res1']", inst_extra.resources)
def test_instance_extra_update_by_uuid_and_create(self):
@sqlalchemy_api.pick_context_manager_writer
@ -3405,13 +3405,14 @@ class InstanceExtraTestCase(test.TestCase):
def test_instance_extra_get_with_columns(self):
extra = db.instance_extra_get_by_instance_uuid(
self.ctxt, self.instance['uuid'],
columns=['numa_topology', 'vcpu_model', 'trusted_certs', 'vpmems'])
columns=['numa_topology', 'vcpu_model', 'trusted_certs',
'resources'])
self.assertRaises(SQLAlchemyError,
extra.__getitem__, 'pci_requests')
self.assertIn('numa_topology', extra)
self.assertIn('vcpu_model', extra)
self.assertIn('trusted_certs', extra)
self.assertIn('vpmems', extra)
self.assertIn('resources', extra)
class ServiceTestCase(test.TestCase, ModelsObjectComparatorMixin):

View File

@ -788,7 +788,10 @@ class NovaMigrationsCheckers(test_migrations.ModelsMigrationsSync,
def removed_column(element):
# Define a whitelist of columns that would be removed from the
# DB at a later release.
column_whitelist = {'instances': ['internal_id']}
# NOTE(Luyao) The vpmems column was added to the schema in train,
# and removed from the model in train.
column_whitelist = {'instances': ['internal_id'],
'instance_extra': ['vpmems']}
if element[0] != 'remove_column':
return False
@ -1048,6 +1051,10 @@ class NovaMigrationsCheckers(test_migrations.ModelsMigrationsSync,
self.assertColumnExists(
engine, '%smigrations' % prefix, 'project_id')
def _check_402(self, engine, data):
self.assertColumnExists(engine, 'instance_extra', 'resources')
self.assertColumnExists(engine, 'shadow_instance_extra', 'resources')
class TestNovaMigrationsSQLite(NovaMigrationsCheckers,
test_fixtures.OpportunisticDBTestMixin,