Coverage for core/management/commands/upgrade.py: 0%
55 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 18:35 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 18:35 +0000
1"""Run the NetBox application tasks required after installing or upgrading NetBox.
3The command runs the NetBox application-level tasks that prepare the database and
4static assets after the package and configuration are already in place - for both a
5fresh installation and an upgrade. It does not perform host or bootstrap work
6(creating the virtual environment, installing packages, configuring services); that
7stays in upgrade.sh and the documented pip steps.
8"""
10import os
11import subprocess
13from django.conf import settings
14from django.core.management import call_command
15from django.core.management.base import BaseCommand
18def _docs_source_root():
19 # mkdocs.yml sits beside the application root in a checkout. Wheels ship the
20 # pre-rendered site instead of the sources: no mkdocs.yml, the build is skipped.
21 candidate = os.path.dirname(settings.BASE_DIR)
22 if os.path.isfile(os.path.join(candidate, 'mkdocs.yml')):
23 return candidate
24 return None
27class Command(BaseCommand):
28 help = "Run the NetBox application tasks required after installing or upgrading NetBox."
30 def add_arguments(self, parser):
31 parser.add_argument('--no-input', action='store_true', dest='no_input',
32 help="Do not prompt for user input.")
33 parser.add_argument('--readonly', action='store_true', dest='readonly',
34 help="Skip all tasks that modify the database or filesystem "
35 "(no migrations, no static collection).")
36 parser.add_argument('--skip-migrations', action='store_true', dest='skip_migrations',
37 help="Skip applying database migrations.")
38 parser.add_argument('--skip-static', action='store_true', dest='skip_static',
39 help="Skip collecting static files.")
40 parser.add_argument('--skip-reindex', action='store_true', dest='skip_reindex',
41 help="Skip rebuilding the search index.")
42 parser.add_argument('--build-docs', action='store_true', dest='build_docs',
43 help="Build the local documentation (requires the documentation source tree).")
45 def handle(self, *args, **options):
46 out, style = self.stdout, self.style
47 out.write(style.SUCCESS("Running NetBox upgrade tasks..."))
49 # Database migrations (writes to the database)
50 if options['skip_migrations'] or options['readonly']:
51 out.write("Skipping database migrations.")
52 else:
53 out.write("Applying database migrations...")
54 call_command('migrate', interactive=not options['no_input'], stdout=out)
56 # Missing cable paths (writes to the database)
57 if options['readonly']:
58 out.write("Skipping cable path check.")
59 else:
60 out.write("Checking for missing cable paths...")
61 call_command('trace_paths', no_input=options['no_input'], stdout=out)
63 # Documentation (filesystem; needs the documentation source tree)
64 if options['readonly'] and options['build_docs']:
65 out.write("Skipping documentation build.")
66 elif options['build_docs']:
67 docs_root = _docs_source_root()
68 if docs_root is None:
69 out.write(style.WARNING(
70 "Skipping documentation build; the documentation source tree is not available "
71 "in this installation."
72 ))
73 else:
74 out.write("Building documentation...")
75 # -c cleans the cache; -s (strict) is deliberately omitted so a docs
76 # warning cannot abort an instance upgrade.
77 subprocess.run(['zensical', 'build', '-c'], cwd=docs_root, check=True)
79 # Static files (filesystem)
80 if options['skip_static'] or options['readonly']:
81 out.write("Skipping static file collection.")
82 else:
83 out.write("Collecting static files...")
84 call_command('collectstatic', interactive=not options['no_input'], stdout=out)
86 # Stale content types (writes to the database)
87 if options['readonly']:
88 out.write("Skipping stale content type removal.")
89 else:
90 out.write("Removing stale content types...")
91 call_command('remove_stale_contenttypes', interactive=not options['no_input'], stdout=out)
93 # Search index (writes to the database)
94 if options['skip_reindex'] or options['readonly']:
95 out.write("Skipping search index rebuild.")
96 else:
97 out.write("Rebuilding the search index (lazily)...")
98 call_command('reindex', lazy=True, stdout=out)
100 # Expired sessions (writes to the database)
101 if options['readonly']:
102 out.write("Skipping expired session cleanup.")
103 else:
104 out.write("Clearing expired sessions...")
105 call_command('clearsessions', stdout=out)
107 out.write(style.SUCCESS("Finished NetBox upgrade tasks."))