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:
parent
0fd6afdab7
commit
c5707a97fd
|
@ -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)
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue