resource_providers, allocations and inventories models

Add migration and models for resource_providers, allocations
and inventories tables which will track availability and
consumption of generic resources.

Note that this also adds the uuid column to the compute_nodes table,
which is required for the later modeling. It's squashed in here
because it's part of this line of work, required for later, and
because fewer migrations == bettersauce.

Co-Authored-By: Dan Smith <dansmith@redhat.com>
Partially-Implements: blueprint resource-providers
Change-Id: Id77ec737201881ecba5233439d2a7c173471fcfa
This commit is contained in:
Chris Dent 2016-02-02 22:25:57 +00:00 committed by Dan Smith
parent 0fd6afdab7
commit c5707a97fd
4 changed files with 171 additions and 1 deletions

View File

@ -0,0 +1,84 @@
# 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.
"""Database migrations for resource-providers."""
from migrate import UniqueConstraint
from sqlalchemy import Column
from sqlalchemy import Float
from sqlalchemy import Index
from sqlalchemy import Integer
from sqlalchemy import MetaData
from sqlalchemy import String
from sqlalchemy import Table
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
resource_providers = Table(
'resource_providers', meta,
Column('id', Integer, primary_key=True, nullable=False),
Column('uuid', String(36), nullable=False),
UniqueConstraint('uuid', name='uniq_resource_providers0uuid'),
mysql_engine='InnoDB',
mysql_charset='latin1'
)
# NOTE(mriedem): DB2 creates an index when a unique constraint is created
# so trying to add a second index on the name column will fail with error
# SQL0605W, so omit the index in the case of DB2.
if migrate_engine.name != 'ibm_db_sa':
Index('resource_providers_uuid_idx', resource_providers.c.uuid)
inventories = Table(
'inventories', meta,
Column('id', Integer, primary_key=True, nullable=False),
Column('resource_provider_id', Integer, nullable=False),
Column('resource_class_id', Integer, nullable=False),
Column('total', Integer, nullable=False),
Column('reserved', Integer, nullable=False),
Column('min_unit', Integer, nullable=False),
Column('max_unit', Integer, nullable=False),
Column('step_size', Integer, nullable=False),
Column('allocation_ratio', Float, nullable=False),
mysql_engine='InnoDB',
mysql_charset='latin1'
)
Index('inventories_resource_provider_id_idx',
inventories.c.resource_provider_id)
Index('inventories_resource_class_id_idx',
inventories.c.resource_class_id)
allocations = Table(
'allocations', meta,
Column('id', Integer, primary_key=True, nullable=False),
Column('resource_provider_id', Integer, nullable=False),
Column('consumer_id', String(36), nullable=False),
Column('resource_class_id', Integer, nullable=False),
Column('used', Integer, nullable=False),
mysql_engine='InnoDB',
mysql_charset='latin1'
)
Index('allocations_resource_provider_class_id_idx',
allocations.c.resource_provider_id,
allocations.c.resource_class_id)
Index('allocations_consumer_id_idx', allocations.c.consumer_id)
Index('allocations_resource_class_id_idx',
allocations.c.resource_class_id)
for table in [resource_providers, inventories, allocations]:
table.create(checkfirst=True)
for table_name in ('', 'shadow_'):
uuid_column = Column('uuid', String(36))
compute_nodes = Table('%scompute_nodes' % table_name, meta)
compute_nodes.create_column(uuid_column)

View File

@ -123,6 +123,7 @@ class ComputeNode(BASE, NovaBase, models.SoftDeleteMixin):
# This field has to be set non-nullable in a later cycle (probably Lxxx)
# once we are sure that all compute nodes in production report it.
host = Column(String(255), nullable=True)
uuid = Column(String(36), nullable=True)
vcpus = Column(Integer, nullable=False)
memory_mb = Column(Integer, nullable=False)
local_gb = Column(Integer, nullable=False)
@ -1431,3 +1432,63 @@ class Tag(BASE, models.ModelBase):
'Instance.deleted == 0)',
foreign_keys=resource_id
)
class ResourceProvider(BASE, models.ModelBase):
"""Represents a mapping to a providers of resources."""
__tablename__ = "resource_providers"
__table_args__ = (
Index('resource_providers_uuid_idx', 'uuid'),
schema.UniqueConstraint('uuid',
name='uniq_resource_providers0uuid'),
)
id = Column(Integer, primary_key=True, nullable=False)
uuid = Column(String(36), nullable=False)
class Inventory(BASE, models.ModelBase):
"""Represents a quantity of available resource."""
__tablename__ = "inventories"
__table_args__ = (
Index('inventories_resource_provider_id_idx',
'resource_provider_id'),
Index('inventories_resource_class_id_idx',
'resource_class_id'),
)
id = Column(Integer, primary_key=True, nullable=False)
resource_provider_id = Column(Integer, nullable=False)
resource_class_id = Column(Integer, nullable=False)
total = Column(Integer, nullable=False)
reserved = Column(Integer, nullable=False)
min_unit = Column(Integer, nullable=False)
max_unit = Column(Integer, nullable=False)
step_size = Column(Integer, nullable=False)
allocation_ratio = Column(Float, nullable=False)
resource_provider = orm.relationship(
"ResourceProvider",
primaryjoin=('and_(Inventory.resource_provider_id == '
'ResourceProvider.id)'),
foreign_keys=resource_provider_id)
class Allocation(BASE, models.ModelBase):
"""A use of inventory."""
__tablename__ = "allocations"
__table_args__ = (
Index('allocations_resource_provider_class_id_idx',
'resource_provider_id', 'resource_class_id'),
Index('allocations_resource_class_id_idx',
'resource_class_id'),
Index('allocations_consumer_id_idx', 'consumer_id')
)
id = Column(Integer, primary_key=True, nullable=False)
resource_provider_id = Column(Integer, nullable=False)
consumer_id = Column(String(36), nullable=False)
resource_class_id = Column(Integer, nullable=False)
used = Column(Integer, nullable=False)

View File

@ -65,6 +65,7 @@ from nova.objects import fields
from nova import quota
from nova import test
from nova.tests.unit import matchers
from nova.tests import uuidsentinel
from nova import utils
CONF = cfg.CONF
@ -7305,6 +7306,7 @@ class ComputeNodeTestCase(test.TestCase, ModelsObjectComparatorMixin):
disabled=False)
self.service = db.service_create(self.ctxt, self.service_dict)
self.compute_node_dict = dict(vcpus=2, memory_mb=1024, local_gb=2048,
uuid=uuidsentinel.fake_compute_node,
vcpus_used=0, memory_mb_used=0,
local_gb_used=0, free_ram_mb=1024,
free_disk_gb=2048, hypervisor_type="xen",
@ -8344,7 +8346,11 @@ class ArchiveTestCase(test.TestCase, ModelsObjectComparatorMixin):
# NOTE(snikitin): migration 266 introduced a new table 'tags',
# which have no shadow table and it's
# completely OK, so we should skip it here
if table_name == 'tags':
# NOTE(cdent): migration 314 introduced three new
# ('resource_providers', 'allocations' and 'inventories')
# with no shadow table and it's OK, so skip.
if table_name in ['tags', 'resource_providers', 'allocations',
'inventories']:
continue
if table_name.startswith("shadow_"):
@ -8421,6 +8427,11 @@ class ArchiveTestCase(test.TestCase, ModelsObjectComparatorMixin):
def _test_archive_deleted_rows_for_one_uuid_table(self, tablename):
""":returns: 0 on success, 1 if no uuid column, 2 if insert failed."""
# NOTE(cdent): migration 314 adds the resource_providers
# table with a uuid column that does not archive, so skip.
skip_tables = ['resource_providers']
if tablename in skip_tables:
return 1
main_table = sqlalchemyutils.get_table(self.engine, tablename)
if not hasattr(main_table.c, "uuid"):
# Not a uuid table, so skip it.

View File

@ -819,6 +819,20 @@ class NovaMigrationsCheckers(test_migrations.ModelsMigrationsSync,
'ix_pci_devices_compute_node_id_parent_addr_deleted',
['compute_node_id', 'parent_addr', 'deleted'])
def _check_314(self, engine, data):
self.assertColumnExists(engine, 'inventories', 'resource_class_id')
self.assertColumnExists(engine, 'allocations', 'resource_class_id')
self.assertColumnExists(engine, 'resource_providers', 'id')
self.assertColumnExists(engine, 'resource_providers', 'uuid')
self.assertColumnExists(engine, 'compute_nodes', 'uuid')
self.assertColumnExists(engine, 'shadow_compute_nodes', 'uuid')
self.assertIndexMembers(engine, 'allocations',
'allocations_resource_provider_class_id_idx',
['resource_provider_id', 'resource_class_id'])
class TestNovaMigrationsSQLite(NovaMigrationsCheckers,
test_base.DbTestCase,