Set root_provider_id in the database
When nested resource provider feature was added in Rocky, root_provider_id column, which should be non-None value, is created in the resource provider DB. However, online data migration is only done implicitly via listing or showing resource providers. With this patch, executing the cli command `placement-manage db online_data_migrations` makes sure all the resource providers are ready for nested provider feature, that is, all the root_provider_ids in the DB have non-None value. Change-Id: I42a1afa69f379b095417f5eb106fe52ebff15017 Related-Bug:#1803925
This commit is contained in:
parent
80fa50187a
commit
c198326150
@ -100,6 +100,7 @@ Placement Database
|
|||||||
+---------------------------------------------+-------------+-----------+
|
+---------------------------------------------+-------------+-----------+
|
||||||
| Migration | Total Found | Completed |
|
| Migration | Total Found | Completed |
|
||||||
+---------------------------------------------+-------------+-----------+
|
+---------------------------------------------+-------------+-----------+
|
||||||
|
| set_root_provider_ids | 0 | 0 |
|
||||||
| create_incomplete_consumers | 2 | 2 |
|
| create_incomplete_consumers | 2 | 2 |
|
||||||
+---------------------------------------------+-------------+-----------+
|
+---------------------------------------------+-------------+-----------+
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ from placement import context
|
|||||||
from placement.db.sqlalchemy import migration
|
from placement.db.sqlalchemy import migration
|
||||||
from placement import db_api
|
from placement import db_api
|
||||||
from placement.i18n import _
|
from placement.i18n import _
|
||||||
|
from placement.objects import resource_provider as rp_obj
|
||||||
|
|
||||||
version_info = pbr.version.VersionInfo('openstack-placement')
|
version_info = pbr.version.VersionInfo('openstack-placement')
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
@ -44,6 +45,7 @@ online_migrations = (
|
|||||||
# have finished.
|
# have finished.
|
||||||
|
|
||||||
# Added in Stein
|
# Added in Stein
|
||||||
|
rp_obj.set_root_provider_ids,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -744,7 +744,8 @@ def _has_child_providers(context, rp_id):
|
|||||||
@db_api.placement_context_manager.writer
|
@db_api.placement_context_manager.writer
|
||||||
def _set_root_provider_id(context, rp_id, root_id):
|
def _set_root_provider_id(context, rp_id, root_id):
|
||||||
"""Simply sets the root_provider_id value for a provider identified by
|
"""Simply sets the root_provider_id value for a provider identified by
|
||||||
rp_id. Used in online data migration.
|
rp_id. Used in implicit online data migration via REST API getting
|
||||||
|
resource providers.
|
||||||
|
|
||||||
:param rp_id: Internal ID of the provider to update
|
:param rp_id: Internal ID of the provider to update
|
||||||
:param root_id: Value to set root provider to
|
:param root_id: Value to set root provider to
|
||||||
@ -754,6 +755,38 @@ def _set_root_provider_id(context, rp_id, root_id):
|
|||||||
context.session.execute(upd)
|
context.session.execute(upd)
|
||||||
|
|
||||||
|
|
||||||
|
@db_api.placement_context_manager.writer
|
||||||
|
def set_root_provider_ids(context, batch_size):
|
||||||
|
"""Simply sets the root_provider_id value for a provider identified by
|
||||||
|
rp_id. Used in explicit online data migration via CLI.
|
||||||
|
|
||||||
|
:param rp_id: Internal ID of the provider to update
|
||||||
|
:param root_id: Value to set root provider to
|
||||||
|
"""
|
||||||
|
# UPDATE resource_providers
|
||||||
|
# SET root_provider_id=resource_providers.id
|
||||||
|
# WHERE resource_providers.id
|
||||||
|
# IN (SELECT subq_1.id
|
||||||
|
# FROM (SELECT resource_providers.id AS id
|
||||||
|
# FROM resource_providers
|
||||||
|
# WHERE resource_providers.root_provider_id IS NULL
|
||||||
|
# LIMIT :param_1)
|
||||||
|
# AS subq_1)
|
||||||
|
|
||||||
|
subq_1 = context.session.query(_RP_TBL.c.id)
|
||||||
|
subq_1 = subq_1.filter(_RP_TBL.c.root_provider_id.is_(None))
|
||||||
|
subq_1 = subq_1.limit(batch_size)
|
||||||
|
subq_1 = sa.alias(subq_1.as_scalar(), name="subq_1")
|
||||||
|
|
||||||
|
subq_2 = sa.select([subq_1.c.id]).select_from(subq_1)
|
||||||
|
|
||||||
|
upd = _RP_TBL.update().where(_RP_TBL.c.id.in_(subq_2.as_scalar()))
|
||||||
|
upd = upd.values(root_provider_id=_RP_TBL.c.id)
|
||||||
|
res = context.session.execute(upd)
|
||||||
|
|
||||||
|
return res.rowcount, res.rowcount
|
||||||
|
|
||||||
|
|
||||||
ProviderIds = collections.namedtuple(
|
ProviderIds = collections.namedtuple(
|
||||||
'ProviderIds', 'id uuid parent_id parent_uuid root_id root_uuid')
|
'ProviderIds', 'id uuid parent_id parent_uuid root_id root_uuid')
|
||||||
|
|
||||||
|
@ -147,6 +147,78 @@ class ResourceProviderTestCase(tb.PlacementDbBaseTestCase):
|
|||||||
# Make sure the object root_provider_uuid is set on load
|
# Make sure the object root_provider_uuid is set on load
|
||||||
self.assertEqual(rp.root_provider_uuid, uuidsentinel.rp1)
|
self.assertEqual(rp.root_provider_uuid, uuidsentinel.rp1)
|
||||||
|
|
||||||
|
def test_set_root_provider(self):
|
||||||
|
"""Simulate old resource provider records in the database that has no
|
||||||
|
root_provider_uuid set and ensure the root_provider_uuid field in the
|
||||||
|
table is set to the provider's ID via set_root_provider_ids().
|
||||||
|
"""
|
||||||
|
# First, set up records for "old-style" resource providers with
|
||||||
|
# no root provider UUID.
|
||||||
|
rp_tbl = rp_obj._RP_TBL
|
||||||
|
conn = self.placement_db.get_engine().connect()
|
||||||
|
|
||||||
|
ins_stmt1 = rp_tbl.insert().values(
|
||||||
|
id=1,
|
||||||
|
uuid=uuidsentinel.rp1,
|
||||||
|
name='rp-1',
|
||||||
|
root_provider_id=None,
|
||||||
|
parent_provider_id=None,
|
||||||
|
generation=42,
|
||||||
|
)
|
||||||
|
ins_stmt2 = rp_tbl.insert().values(
|
||||||
|
id=2,
|
||||||
|
uuid=uuidsentinel.rp2,
|
||||||
|
name='rp-2',
|
||||||
|
root_provider_id=None,
|
||||||
|
parent_provider_id=None,
|
||||||
|
generation=42,
|
||||||
|
)
|
||||||
|
conn.execute(ins_stmt1)
|
||||||
|
conn.execute(ins_stmt2)
|
||||||
|
|
||||||
|
# Second, set up records for "new-style" resource providers
|
||||||
|
# in a tree
|
||||||
|
self._create_provider('root_rp')
|
||||||
|
self._create_provider('child_rp', parent=uuidsentinel.root_rp)
|
||||||
|
self._create_provider('grandchild_rp', parent=uuidsentinel.child_rp)
|
||||||
|
|
||||||
|
# Check rp_1 that it has no root provider id
|
||||||
|
sel_stmt = sa.select([rp_tbl.c.root_provider_id]).where(
|
||||||
|
rp_tbl.c.id == 1)
|
||||||
|
res = conn.execute(sel_stmt).fetchall()
|
||||||
|
self.assertIsNone(res[0][0])
|
||||||
|
# Check rp_2 that it has no root provider id
|
||||||
|
sel_stmt = sa.select([rp_tbl.c.root_provider_id]).where(
|
||||||
|
rp_tbl.c.id == 2)
|
||||||
|
res = conn.execute(sel_stmt).fetchall()
|
||||||
|
self.assertIsNone(res[0][0])
|
||||||
|
|
||||||
|
# Run set_root_provider_ids()
|
||||||
|
found, migrated = rp_obj.set_root_provider_ids(self.ctx, batch_size=10)
|
||||||
|
self.assertEqual(2, found)
|
||||||
|
self.assertEqual(2, migrated)
|
||||||
|
|
||||||
|
# Check rp_1 that it has got the root provider id
|
||||||
|
sel_stmt = sa.select([rp_tbl.c.root_provider_id]).where(
|
||||||
|
rp_tbl.c.id == 1)
|
||||||
|
res = conn.execute(sel_stmt).fetchall()
|
||||||
|
self.assertEqual(1, res[0][0])
|
||||||
|
# Check rp_2 that it has got the root provider id
|
||||||
|
sel_stmt = sa.select([rp_tbl.c.root_provider_id]).where(
|
||||||
|
rp_tbl.c.id == 2)
|
||||||
|
res = conn.execute(sel_stmt).fetchall()
|
||||||
|
self.assertEqual(2, res[0][0])
|
||||||
|
|
||||||
|
# Check the new-style providers remains in a tree,
|
||||||
|
# which means the root provider ids are not changed
|
||||||
|
rps = rp_obj.ResourceProviderList.get_all_by_filters(
|
||||||
|
self.ctx,
|
||||||
|
filters={
|
||||||
|
'in_tree': uuidsentinel.root_rp,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.assertEqual(3, len(rps))
|
||||||
|
|
||||||
def test_inherit_root_from_parent(self):
|
def test_inherit_root_from_parent(self):
|
||||||
"""Tests that if we update an existing provider's parent provider UUID,
|
"""Tests that if we update an existing provider's parent provider UUID,
|
||||||
that the root provider UUID of the updated provider is automatically
|
that the root provider UUID of the updated provider is automatically
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
A new online data migration has been added to populate missing
|
||||||
|
``root_provider_id`` in the resource_providers table. This can
|
||||||
|
be run during the normal placement-manage db online_data_migrations
|
||||||
|
routine. See the `Bug#1803925`_ for more details.
|
||||||
|
|
||||||
|
.. _Bug#1803925: https://bugs.launchpad.net/nova/+bug/1803925
|
||||||
|
|
Loading…
Reference in New Issue
Block a user