Skip to content

Commit 713b653

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Add --sleep option for archive_deleted_rows --until-complete"
2 parents 7a0ed9e + fc77ce1 commit 713b653

File tree

4 files changed

+49
-11
lines changed

4 files changed

+49
-11
lines changed

doc/source/cli/nova-manage.rst

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ db archive_deleted_rows
227227
228228
nova-manage db archive_deleted_rows [--max_rows <rows>] [--verbose]
229229
[--until-complete] [--before <date>] [--purge] [--all-cells] [--task-log]
230+
[--sleep]
230231
231232
Move deleted rows from production tables to shadow tables. Note that the
232233
corresponding rows in the ``instance_mappings``, ``request_specs`` and
@@ -240,7 +241,7 @@ stopping at 0, or use the :option:`--until-complete` option.
240241

241242
.. versionchanged:: 24.0.0 (Xena)
242243

243-
Added :option:`--task-log` option.
244+
Added :option:`--task-log`, :option:`--sleep` options.
244245

245246
.. rubric:: Options
246247

@@ -295,7 +296,12 @@ stopping at 0, or use the :option:`--until-complete` option.
295296
record data via the `/os-instance_usage_audit_log`__ API (example:
296297
Telemetry).
297298

298-
.. __: https://docs.openstack.org/api-ref/compute/#server-usage-audit-log-os-instance-usage-audit-log
299+
.. __: https://docs.openstack.org/api-ref/compute/#server-usage-audit-log-os-instance-usage-audit-log
300+
301+
.. option:: --sleep
302+
303+
The amount of time in seconds to sleep between batches when
304+
:option:`--until-complete` is used. Defaults to 0.
299305

300306
.. rubric:: Return codes
301307

nova/cmd/manage.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import os
2727
import re
2828
import sys
29+
import time
2930
import traceback
3031
from urllib import parse as urlparse
3132

@@ -249,9 +250,14 @@ def version(self):
249250
'``--before`` option to avoid races for those consuming '
250251
'``task_log`` record data via the '
251252
'``/os-instance_usage_audit_log`` API (example: Telemetry).'))
252-
def archive_deleted_rows(self, max_rows=1000, verbose=False,
253-
until_complete=False, purge=False,
254-
before=None, all_cells=False, task_log=False):
253+
@args('--sleep', type=int, metavar='<seconds>', dest='sleep',
254+
help='The amount of time in seconds to sleep between batches when '
255+
'``--until-complete`` is used. Defaults to 0.')
256+
def archive_deleted_rows(
257+
self, max_rows=1000, verbose=False,
258+
until_complete=False, purge=False,
259+
before=None, all_cells=False, task_log=False, sleep=0,
260+
):
255261
"""Move deleted rows from production tables to shadow tables.
256262
257263
Returns 0 if nothing was archived, 1 if some number of rows were
@@ -344,7 +350,8 @@ def sort_func(item):
344350
verbose,
345351
before_date,
346352
cell_name,
347-
task_log)
353+
task_log,
354+
sleep)
348355
except KeyboardInterrupt:
349356
interrupt = True
350357
break
@@ -377,8 +384,10 @@ def sort_func(item):
377384
# NOTE(danms): Return nonzero if we archived something
378385
return int(bool(table_to_rows_archived))
379386

380-
def _do_archive(self, table_to_rows_archived, cctxt, max_rows,
381-
until_complete, verbose, before_date, cell_name, task_log):
387+
def _do_archive(
388+
self, table_to_rows_archived, cctxt, max_rows,
389+
until_complete, verbose, before_date, cell_name, task_log, sleep,
390+
):
382391
"""Helper function for archiving deleted rows for a cell.
383392
384393
This will archive deleted rows for a cell database and remove the
@@ -398,6 +407,8 @@ def _do_archive(self, table_to_rows_archived, cctxt, max_rows,
398407
:param cell_name: Name of the cell or None if not archiving across all
399408
cells
400409
:param task_log: Whether to archive task_log table rows
410+
:param sleep: The amount of time in seconds to sleep between batches
411+
when ``until_complete`` is True.
401412
"""
402413
ctxt = context.get_admin_context()
403414
while True:
@@ -437,6 +448,8 @@ def _do_archive(self, table_to_rows_archived, cctxt, max_rows,
437448
break
438449
if verbose:
439450
sys.stdout.write('.')
451+
# Optionally sleep between batches to throttle the archiving.
452+
time.sleep(sleep)
440453
return total_rows_archived
441454

442455
@args('--before', metavar='<before>', dest='before',

nova/tests/unit/cmd/test_manage.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -315,17 +315,20 @@ def test_archive_deleted_rows_verbose(self):
315315
# Tests that we get table output.
316316
self._test_archive_deleted_rows(verbose=True)
317317

318+
@mock.patch('time.sleep')
318319
@mock.patch.object(db, 'archive_deleted_rows')
319320
@mock.patch.object(objects.CellMappingList, 'get_all')
320321
def test_archive_deleted_rows_until_complete(self, mock_get_all,
321-
mock_db_archive,
322-
verbose=False):
322+
mock_db_archive, mock_sleep,
323+
verbose=False,
324+
sleep=0):
323325
mock_db_archive.side_effect = [
324326
({'instances': 10, 'instance_extra': 5}, list(), 15),
325327
({'instances': 5, 'instance_faults': 1}, list(), 6),
326328
({}, list(), 0)]
327329
result = self.commands.archive_deleted_rows(20, verbose=verbose,
328-
until_complete=True)
330+
until_complete=True,
331+
sleep=sleep)
329332
self.assertEqual(1, result)
330333
if verbose:
331334
expected = """\
@@ -353,10 +356,15 @@ def test_archive_deleted_rows_until_complete(self, mock_get_all,
353356
test.MatchType(context.RequestContext), 20, before=None,
354357
task_log=False),
355358
])
359+
self.assertEqual(2, mock_sleep.call_count)
360+
mock_sleep.assert_has_calls([mock.call(sleep), mock.call(sleep)])
356361

357362
def test_archive_deleted_rows_until_complete_quiet(self):
358363
self.test_archive_deleted_rows_until_complete(verbose=False)
359364

365+
def test_archive_deleted_rows_until_complete_sleep(self):
366+
self.test_archive_deleted_rows_until_complete(sleep=30)
367+
360368
@mock.patch('nova.db.main.api.purge_shadow_tables')
361369
@mock.patch.object(db, 'archive_deleted_rows')
362370
@mock.patch.object(objects.CellMappingList, 'get_all')
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
features:
3+
- |
4+
A ``--sleep`` option has been added to the ``nova-manage db
5+
archive_deleted_rows`` CLI. When this command is run with the
6+
``--until-complete`` option, the process will archive rows in batches
7+
in a tight loop, which can cause problems in busy environments where
8+
the aggressive archiving interferes with other requests trying to write
9+
to the database. The ``--sleep`` option can be used to specify a time to
10+
sleep between batches of rows while archiving with ``--until-complete``,
11+
allowing the process to be throttled.

0 commit comments

Comments
 (0)