Skip to content

Commit fc77ce1

Browse files
melwittBalazs Gibizer
authored andcommitted
Add --sleep option for archive_deleted_rows --until-complete
Currently, when 'nova-manage db archive_deleted_rows' is run with the --until-complete option, the process will archive rows in batches in a tight loop, which can cause problems in busy environments where the aggressive archiving interferes with other requests trying to write to the database. This adds an option for users to specify an amount of time in seconds to sleep between batches of rows while archiving with --until-complete, allowing the process to be throttled. Closes-Bug: #1912579 Change-Id: I638b2fa78b81919373e607458e6f68a7983a79aa
1 parent 75f719e commit fc77ce1

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)