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

1"""Run the NetBox application tasks required after installing or upgrading NetBox. 

2 

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""" 

9 

10import os 

11import subprocess 

12 

13from django.conf import settings 

14from django.core.management import call_command 

15from django.core.management.base import BaseCommand 

16 

17 

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 

25 

26 

27class Command(BaseCommand): 

28 help = "Run the NetBox application tasks required after installing or upgrading NetBox." 

29 

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).") 

44 

45 def handle(self, *args, **options): 

46 out, style = self.stdout, self.style 

47 out.write(style.SUCCESS("Running NetBox upgrade tasks...")) 

48 

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) 

55 

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) 

62 

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) 

78 

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) 

85 

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) 

92 

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) 

99 

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) 

106 

107 out.write(style.SUCCESS("Finished NetBox upgrade tasks."))