cmd: Remove 'nova-manage db null_instance_uuid_scan'
Change I2aae01ed235f1257b0b3ddc6aee4efc7be38eb6e indicated that this command was no longer necessary and could be removed. In hindsight, it's been unnecessary since Liberty, which introduced a blocking migration requiring this script be run, and it could have been deleted years ago. No time like the present though. Change-Id: I532c7918a8e2c887f29d2f0e1e33b80f2b3a7507 Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
parent
726e2fd03b
commit
2d4eff0ef7
@ -230,9 +230,6 @@ Nova Database
|
||||
arguments are not provided, 2 if an invalid date is provided, 3 if no
|
||||
data was deleted, 4 if the list of cells cannot be obtained.
|
||||
|
||||
``nova-manage db null_instance_uuid_scan [--delete]``
|
||||
Lists and optionally deletes database records where instance_uuid is NULL.
|
||||
|
||||
``nova-manage db online_data_migrations [--max-count]``
|
||||
Perform data migration to update all live data.
|
||||
|
||||
|
@ -463,35 +463,6 @@ Error: %s""") % str(e))
|
||||
else:
|
||||
return 3
|
||||
|
||||
@args('--delete', action='store_true', dest='delete',
|
||||
help='If specified, automatically delete any records found where '
|
||||
'instance_uuid is NULL.')
|
||||
def null_instance_uuid_scan(self, delete=False):
|
||||
"""Lists and optionally deletes database records where
|
||||
instance_uuid is NULL.
|
||||
"""
|
||||
hits = migration.db_null_instance_uuid_scan(delete)
|
||||
records_found = False
|
||||
for table_name, records in hits.items():
|
||||
# Don't print anything for 0 hits
|
||||
if records:
|
||||
records_found = True
|
||||
if delete:
|
||||
print(_("Deleted %(records)d records "
|
||||
"from table '%(table_name)s'.") %
|
||||
{'records': records, 'table_name': table_name})
|
||||
else:
|
||||
print(_("There are %(records)d records in the "
|
||||
"'%(table_name)s' table where the uuid or "
|
||||
"instance_uuid column is NULL. Run this "
|
||||
"command again with the --delete option after you "
|
||||
"have backed up any necessary data.") %
|
||||
{'records': records, 'table_name': table_name})
|
||||
# check to see if we didn't find anything
|
||||
if not records_found:
|
||||
print(_('There were no records found where '
|
||||
'instance_uuid was NULL.'))
|
||||
|
||||
def _run_migration(self, ctxt, max_count):
|
||||
ran = 0
|
||||
exceptions = False
|
||||
|
@ -34,23 +34,3 @@ def db_version(database='main', context=None):
|
||||
def db_initial_version(database='main'):
|
||||
"""The starting version for the database."""
|
||||
return IMPL.db_initial_version(database=database)
|
||||
|
||||
|
||||
def db_null_instance_uuid_scan(delete=False):
|
||||
"""Utility for scanning the database to look for NULL instance uuid rows.
|
||||
|
||||
Scans the backing nova database to look for table entries where
|
||||
instances.uuid or instance_uuid columns are NULL (except for the
|
||||
fixed_ips table since that can contain NULL instance_uuid entries by
|
||||
design). Dumps the tables that have NULL instance_uuid entries or
|
||||
optionally deletes them based on usage.
|
||||
|
||||
This tool is meant to be used in conjunction with the 267 database
|
||||
migration script to detect and optionally cleanup NULL instance_uuid
|
||||
records.
|
||||
|
||||
:param delete: If true, delete NULL instance_uuid records found, else
|
||||
just query to see if they exist for reporting.
|
||||
:returns: dict of table name to number of hits for NULL instance_uuid rows.
|
||||
"""
|
||||
return IMPL.db_null_instance_uuid_scan(delete=delete)
|
||||
|
@ -19,7 +19,6 @@ import os
|
||||
from migrate import exceptions as versioning_exceptions
|
||||
from migrate.versioning import api as versioning_api
|
||||
from migrate.versioning.repository import Repository
|
||||
from oslo_db.sqlalchemy import utils as db_utils
|
||||
from oslo_log import log as logging
|
||||
import sqlalchemy
|
||||
from sqlalchemy.sql import null
|
||||
@ -159,38 +158,6 @@ def _process_null_records(table, col_name, check_fkeys, delete=False):
|
||||
return records
|
||||
|
||||
|
||||
def db_null_instance_uuid_scan(delete=False):
|
||||
"""Scans the database for NULL instance_uuid records.
|
||||
|
||||
:param delete: If true, delete NULL instance_uuid records found, else
|
||||
just query to see if they exist for reporting.
|
||||
:returns: dict of table name to number of hits for NULL instance_uuid rows.
|
||||
"""
|
||||
engine = get_engine()
|
||||
meta = sqlalchemy.MetaData(bind=engine)
|
||||
# NOTE(mriedem): We're going to load up all of the tables so we can find
|
||||
# any with an instance_uuid column since those may be foreign keys back
|
||||
# to the instances table and we want to cleanup those records first. We
|
||||
# have to do this explicitly because the foreign keys in nova aren't
|
||||
# defined with cascading deletes.
|
||||
meta.reflect(engine)
|
||||
# Keep track of all of the tables that had hits in the query.
|
||||
processed = {}
|
||||
for table in reversed(meta.sorted_tables):
|
||||
# Ignore the fixed_ips table by design.
|
||||
if table.name not in ('fixed_ips', 'shadow_fixed_ips'):
|
||||
processed[table.name] = _process_null_records(
|
||||
table, 'instance_uuid', check_fkeys=True, delete=delete)
|
||||
|
||||
# Now process the *instances tables.
|
||||
for table_name in ('instances', 'shadow_instances'):
|
||||
table = db_utils.get_table(engine, table_name)
|
||||
processed[table.name] = _process_null_records(
|
||||
table, 'uuid', check_fkeys=False, delete=delete)
|
||||
|
||||
return processed
|
||||
|
||||
|
||||
def db_version_control(version=None, database='main', context=None):
|
||||
repository = _find_migrate_repo(database)
|
||||
versioning_api.version_control(get_engine(database, context=context),
|
||||
|
@ -30,7 +30,6 @@ from nova.cmd import manage
|
||||
from nova import conf
|
||||
from nova import context
|
||||
from nova.db import api as db
|
||||
from nova.db import migration
|
||||
from nova.db.sqlalchemy import migration as sqla_migration
|
||||
from nova import exception
|
||||
from nova import objects
|
||||
@ -584,32 +583,6 @@ Cell %s: 456
|
||||
self.assertEqual(4, ret)
|
||||
self.assertIn('Unable to get cell list', self.output.getvalue())
|
||||
|
||||
@mock.patch.object(migration, 'db_null_instance_uuid_scan',
|
||||
return_value={'foo': 0})
|
||||
def test_null_instance_uuid_scan_no_records_found(self, mock_scan):
|
||||
self.commands.null_instance_uuid_scan()
|
||||
self.assertIn("There were no records found", self.output.getvalue())
|
||||
|
||||
@mock.patch.object(migration, 'db_null_instance_uuid_scan',
|
||||
return_value={'foo': 1, 'bar': 0})
|
||||
def _test_null_instance_uuid_scan(self, mock_scan, delete):
|
||||
self.commands.null_instance_uuid_scan(delete)
|
||||
output = self.output.getvalue()
|
||||
|
||||
if delete:
|
||||
self.assertIn("Deleted 1 records from table 'foo'.", output)
|
||||
self.assertNotIn("Deleted 0 records from table 'bar'.", output)
|
||||
else:
|
||||
self.assertIn("1 records in the 'foo' table", output)
|
||||
self.assertNotIn("0 records in the 'bar' table", output)
|
||||
self.assertNotIn("There were no records found", output)
|
||||
|
||||
def test_null_instance_uuid_scan_readonly(self):
|
||||
self._test_null_instance_uuid_scan(delete=False)
|
||||
|
||||
def test_null_instance_uuid_scan_delete(self):
|
||||
self._test_null_instance_uuid_scan(delete=True)
|
||||
|
||||
@mock.patch.object(sqla_migration, 'db_version', return_value=2)
|
||||
def test_version(self, sqla_migrate):
|
||||
self.commands.version()
|
||||
|
@ -15,7 +15,6 @@
|
||||
import importlib
|
||||
|
||||
from migrate import exceptions as versioning_exceptions
|
||||
from migrate import UniqueConstraint
|
||||
from migrate.versioning import api as versioning_api
|
||||
import mock
|
||||
from oslo_db.sqlalchemy import utils as db_utils
|
||||
@ -32,71 +31,6 @@ from nova import test
|
||||
from nova.tests import fixtures as nova_fixtures
|
||||
|
||||
|
||||
class TestNullInstanceUuidScanDB(test.TestCase):
|
||||
|
||||
# NOTE(mriedem): Copied from the 267 database migration.
|
||||
def downgrade(self, migrate_engine):
|
||||
UniqueConstraint('uuid',
|
||||
table=db_utils.get_table(migrate_engine, 'instances'),
|
||||
name='uniq_instances0uuid').drop()
|
||||
for table_name in ('instances', 'shadow_instances'):
|
||||
table = db_utils.get_table(migrate_engine, table_name)
|
||||
table.columns.uuid.alter(nullable=True)
|
||||
|
||||
def setUp(self):
|
||||
super(TestNullInstanceUuidScanDB, self).setUp()
|
||||
|
||||
self.engine = db_api.get_engine()
|
||||
# When this test runs, we've already run the schema migration to make
|
||||
# instances.uuid non-nullable, so we have to alter the table here
|
||||
# so we can test against a real database.
|
||||
self.downgrade(self.engine)
|
||||
# Now create fake entries in the fixed_ips, consoles and
|
||||
# instances table where (instance_)uuid is None for testing.
|
||||
for table_name in ('fixed_ips', 'instances', 'consoles'):
|
||||
table = db_utils.get_table(self.engine, table_name)
|
||||
fake_record = {'id': 1}
|
||||
table.insert().execute(fake_record)
|
||||
|
||||
def test_db_null_instance_uuid_scan_readonly(self):
|
||||
results = migration.db_null_instance_uuid_scan(delete=False)
|
||||
self.assertEqual(1, results.get('instances'))
|
||||
self.assertEqual(1, results.get('consoles'))
|
||||
# The fixed_ips table should be ignored.
|
||||
self.assertNotIn('fixed_ips', results)
|
||||
# Now pick a random table with an instance_uuid column and show it's
|
||||
# in the results but with 0 hits.
|
||||
self.assertEqual(0, results.get('instance_info_caches'))
|
||||
# Make sure nothing was deleted.
|
||||
for table_name in ('fixed_ips', 'instances', 'consoles'):
|
||||
table = db_utils.get_table(self.engine, table_name)
|
||||
record = table.select(table.c.id == 1).execute().first()
|
||||
self.assertIsNotNone(record)
|
||||
|
||||
def test_db_null_instance_uuid_scan_delete(self):
|
||||
results = migration.db_null_instance_uuid_scan(delete=True)
|
||||
self.assertEqual(1, results.get('instances'))
|
||||
self.assertEqual(1, results.get('consoles'))
|
||||
# The fixed_ips table should be ignored.
|
||||
self.assertNotIn('fixed_ips', results)
|
||||
# Now pick a random table with an instance_uuid column and show it's
|
||||
# in the results but with 0 hits.
|
||||
self.assertEqual(0, results.get('instance_info_caches'))
|
||||
# Make sure fixed_ips wasn't touched, but instances and instance_faults
|
||||
# records were deleted.
|
||||
fixed_ips = db_utils.get_table(self.engine, 'fixed_ips')
|
||||
record = fixed_ips.select(fixed_ips.c.id == 1).execute().first()
|
||||
self.assertIsNotNone(record)
|
||||
|
||||
consoles = db_utils.get_table(self.engine, 'consoles')
|
||||
record = consoles.select(consoles.c.id == 1).execute().first()
|
||||
self.assertIsNone(record)
|
||||
|
||||
instances = db_utils.get_table(self.engine, 'instances')
|
||||
record = instances.select(instances.c.id == 1).execute().first()
|
||||
self.assertIsNone(record)
|
||||
|
||||
|
||||
@mock.patch.object(migration, 'db_version', return_value=2)
|
||||
@mock.patch.object(migration, '_find_migrate_repo', return_value='repo')
|
||||
@mock.patch.object(versioning_api, 'upgrade')
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
upgrade:
|
||||
- |
|
||||
The ``nova-manage db null_instance_uuid_scan`` command has been removed.
|
||||
A blocking migration has been in place since the 12.0.0 (Liberty) release
|
||||
making this check unnecessary.
|
Loading…
x
Reference in New Issue
Block a user