Просмотр исходного кода

Introduce retrace_paths management command

Jeremy Stretch 5 лет назад
Родитель
Сommit
105c0fd3d2

+ 0 - 0
netbox/dcim/management/__init__.py


+ 0 - 0
netbox/dcim/management/commands/__init__.py


+ 67 - 0
netbox/dcim/management/commands/retrace_paths.py

@@ -0,0 +1,67 @@
+from django.contrib.contenttypes.models import ContentType
+from django.core.management.base import BaseCommand
+from django.core.management.color import no_style
+from django.db import connection
+from django.db.models import Q
+
+from dcim.models import CablePath, Interface
+from dcim.signals import create_cablepaths
+
+ENDPOINT_MODELS = (
+    'circuits.CircuitTermination',
+    'dcim.ConsolePort',
+    'dcim.ConsoleServerPort',
+    'dcim.Interface',
+    'dcim.PowerOutlet',
+    'dcim.PowerPort',
+)
+
+
+class Command(BaseCommand):
+    help = "Recalculate natural ordering values for the specified models"
+
+    def add_arguments(self, parser):
+        parser.add_argument(
+            'args', metavar='app_label.ModelName', nargs='*',
+            help='One or more specific models (each prefixed with its app_label) to retrace',
+        )
+
+    def _get_content_types(self, model_names):
+        q = Q()
+        for model_name in model_names:
+            app_label, model = model_name.split('.')
+            q |= Q(app_label=app_label, model=model)
+        return ContentType.objects.filter(q)
+
+    def handle(self, *model_names, **options):
+        # Determine the models for which we're retracing all paths
+        origin_types = self._get_content_types(model_names or ENDPOINT_MODELS)
+        self.stdout.write(f"Retracing paths for models: {', '.join([str(ct) for ct in origin_types])}")
+
+        # Delete all existing CablePath instances
+        self.stdout.write(f"Deleting existing cable paths...")
+        deleted_count, _ = CablePath.objects.filter(origin_type__in=origin_types).delete()
+        self.stdout.write((self.style.SUCCESS(f'  Deleted {deleted_count} paths')))
+
+        # Reset the SQL sequence. Can do this only if deleting _all_ CablePaths.
+        if not CablePath.objects.count():
+            self.stdout.write(f'Resetting database sequence for CablePath...')
+            sequence_sql = connection.ops.sequence_reset_sql(no_style(), [CablePath])
+            with connection.cursor() as cursor:
+                for sql in sequence_sql:
+                    cursor.execute(sql)
+                self.stdout.write(self.style.SUCCESS('  Success.'))
+
+        # Retrace interfaces
+        for ct in origin_types:
+            model = ct.model_class()
+            origins = model.objects.filter(cable__isnull=False)
+            print(f'Retracing {origins.count()} cabled {model._meta.verbose_name_plural}...')
+            i = 0
+            for i, obj in enumerate(origins, start=1):
+                create_cablepaths(obj)
+                if not i % 1000:
+                    self.stdout.write(f'  {i}')
+            self.stdout.write(self.style.SUCCESS(f'  Retraced {i} {model._meta.verbose_name_plural}'))
+
+        self.stdout.write(self.style.SUCCESS('Finished.'))