Parcourir la source

Merge branch 'develop' into api2

Conflicts:
	netbox/dcim/api/views.py
Jeremy Stretch il y a 8 ans
Parent
commit
02e89d77bb

+ 72 - 84
netbox/dcim/forms.py

@@ -82,7 +82,7 @@ class RegionForm(BootstrapMixin, forms.ModelForm):
 #
 #
 
 
 class SiteForm(BootstrapMixin, CustomFieldForm):
 class SiteForm(BootstrapMixin, CustomFieldForm):
-    region = TreeNodeChoiceField(queryset=Region.objects.all())
+    region = TreeNodeChoiceField(queryset=Region.objects.all(), required=False)
     slug = SlugField()
     slug = SlugField()
     comments = CommentField()
     comments = CommentField()
 
 
@@ -934,28 +934,29 @@ class ConsolePortConnectionForm(BootstrapMixin, forms.ModelForm):
         if not self.instance.pk:
         if not self.instance.pk:
             raise RuntimeError("ConsolePortConnectionForm must be initialized with an existing ConsolePort instance.")
             raise RuntimeError("ConsolePortConnectionForm must be initialized with an existing ConsolePort instance.")
 
 
-        self.initial['site'] = self.instance.device.site
-        self.fields['rack'].queryset = Rack.objects.filter(site=self.instance.device.site)
-        self.fields['cs_port'].required = True
-        self.fields['connection_status'].choices = CONNECTION_STATUS_CHOICES
-
-        # Initialize console server choices
-        if self.is_bound and self.data.get('rack'):
-            self.fields['console_server'].queryset = Device.objects.filter(rack=self.data['rack'],
-                                                                           device_type__is_console_server=True)
-        elif self.initial.get('rack'):
-            self.fields['console_server'].queryset = Device.objects.filter(rack=self.initial['rack'],
-                                                                           device_type__is_console_server=True)
+        # Initialize rack choices if site is set
+        if self.initial.get('site'):
+            self.fields['rack'].queryset = Rack.objects.filter(site=self.initial['site'])
         else:
         else:
-            self.fields['console_server'].queryset = Device.objects.filter(site=self.instance.device.site,
-                                                                           rack__isnull=True,
-                                                                           device_type__is_console_server=True)
+            self.fields['rack'].choices = []
 
 
-        # Initialize CS port choices
-        if self.is_bound:
-            self.fields['cs_port'].queryset = ConsoleServerPort.objects.filter(device__pk=self.data['console_server'])
-        elif self.initial.get('console_server', None):
-            self.fields['cs_port'].queryset = ConsoleServerPort.objects.filter(device__pk=self.initial['console_server'])
+        # Initialize console_server choices if rack or site is set
+        if self.initial.get('rack'):
+            self.fields['console_server'].queryset = Device.objects.filter(
+                rack=self.initial['rack'], device_type__is_console_server=True
+            )
+        elif self.initial.get('site'):
+            self.fields['console_server'].queryset = Device.objects.filter(
+                site=self.initial['site'], rack__isnull=True, device_type__is_console_server=True
+            )
+        else:
+            self.fields['console_server'].choices = []
+
+        # Initialize CS port choices if console_server is set
+        if self.initial.get('console_server'):
+            self.fields['cs_port'].queryset = ConsoleServerPort.objects.filter(
+                device=self.initial['console_server']
+            )
         else:
         else:
             self.fields['cs_port'].choices = []
             self.fields['cs_port'].choices = []
 
 
@@ -1033,27 +1034,27 @@ class ConsoleServerPortConnectionForm(BootstrapMixin, forms.Form):
             'connection_status': 'Status',
             'connection_status': 'Status',
         }
         }
 
 
-    def __init__(self, consoleserverport, *args, **kwargs):
+    def __init__(self, *args, **kwargs):
 
 
         super(ConsoleServerPortConnectionForm, self).__init__(*args, **kwargs)
         super(ConsoleServerPortConnectionForm, self).__init__(*args, **kwargs)
 
 
-        self.initial['site'] = consoleserverport.device.site
-        self.fields['rack'].queryset = Rack.objects.filter(site=consoleserverport.device.site)
+        # Initialize rack choices if site is set
+        if self.initial.get('site'):
+            self.fields['rack'].queryset = Rack.objects.filter(site=self.initial['site'])
+        else:
+            self.fields['rack'].choices = []
 
 
-        # Initialize device choices
-        if self.is_bound and self.data.get('rack'):
-            self.fields['device'].queryset = Device.objects.filter(rack=self.data['rack'])
-        elif self.initial.get('rack', None):
+        # Initialize device choices if rack or site is set
+        if self.initial.get('rack'):
             self.fields['device'].queryset = Device.objects.filter(rack=self.initial['rack'])
             self.fields['device'].queryset = Device.objects.filter(rack=self.initial['rack'])
+        elif self.initial.get('site'):
+            self.fields['device'].queryset = Device.objects.filter(site=self.initial['site'], rack__isnull=True)
         else:
         else:
-            self.fields['device'].queryset = Device.objects.filter(site=consoleserverport.device.site,
-                                                                   rack__isnull=True)
+            self.fields['device'].choices = []
 
 
-        # Initialize port choices
-        if self.is_bound:
-            self.fields['port'].queryset = ConsolePort.objects.filter(device__pk=self.data['device'])
-        elif self.initial.get('device', None):
-            self.fields['port'].queryset = ConsolePort.objects.filter(device_pk=self.initial['device'])
+        # Initialize port choices if device is set
+        if self.initial.get('device'):
+            self.fields['port'].queryset = ConsolePort.objects.filter(device=self.initial['device'])
         else:
         else:
             self.fields['port'].choices = []
             self.fields['port'].choices = []
 
 
@@ -1201,28 +1202,27 @@ class PowerPortConnectionForm(BootstrapMixin, forms.ModelForm):
         if not self.instance.pk:
         if not self.instance.pk:
             raise RuntimeError("PowerPortConnectionForm must be initialized with an existing PowerPort instance.")
             raise RuntimeError("PowerPortConnectionForm must be initialized with an existing PowerPort instance.")
 
 
-        self.initial['site'] = self.instance.device.site
-        self.fields['rack'].queryset = Rack.objects.filter(site=self.instance.device.site)
-        self.fields['power_outlet'].required = True
-        self.fields['connection_status'].choices = CONNECTION_STATUS_CHOICES
-
-        # Initialize PDU choices
-        if self.is_bound and self.data.get('rack'):
-            self.fields['pdu'].queryset = Device.objects.filter(rack=self.data['rack'],
-                                                                device_type__is_pdu=True)
-        elif self.initial.get('rack', None):
-            self.fields['pdu'].queryset = Device.objects.filter(rack=self.initial['rack'],
-                                                                device_type__is_pdu=True)
+        # Initialize rack choices if site is set
+        if self.initial.get('site'):
+            self.fields['rack'].queryset = Rack.objects.filter(site=self.initial['site'])
+        else:
+            self.fields['rack'].choices = []
+
+        # Initialize pdu choices if rack or site is set
+        if self.initial.get('rack'):
+            self.fields['pdu'].queryset = Device.objects.filter(
+                rack=self.initial['rack'], device_type__is_pdu=True
+            )
+        elif self.initial.get('site'):
+            self.fields['pdu'].queryset = Device.objects.filter(
+                site=self.initial['site'], rack__isnull=True, device_type__is_pdu=True
+            )
         else:
         else:
-            self.fields['pdu'].queryset = Device.objects.filter(site=self.instance.device.site,
-                                                                rack__isnull=True,
-                                                                device_type__is_pdu=True)
+            self.fields['pdu'].choices = []
 
 
-        # Initialize power outlet choices
-        if self.is_bound:
-            self.fields['power_outlet'].queryset = PowerOutlet.objects.filter(device__pk=self.data['pdu'])
-        elif self.initial.get('pdu', None):
-            self.fields['power_outlet'].queryset = PowerOutlet.objects.filter(device__pk=self.initial['pdu'])
+        # Initialize power outlet choices if pdu is set
+        if self.initial.get('pdu'):
+            self.fields['power_outlet'].queryset = PowerOutlet.objects.filter(device=self.initial['pdu'])
         else:
         else:
             self.fields['power_outlet'].choices = []
             self.fields['power_outlet'].choices = []
 
 
@@ -1300,27 +1300,27 @@ class PowerOutletConnectionForm(BootstrapMixin, forms.Form):
             'connection_status': 'Status',
             'connection_status': 'Status',
         }
         }
 
 
-    def __init__(self, poweroutlet, *args, **kwargs):
+    def __init__(self, *args, **kwargs):
 
 
         super(PowerOutletConnectionForm, self).__init__(*args, **kwargs)
         super(PowerOutletConnectionForm, self).__init__(*args, **kwargs)
 
 
-        self.initial['site'] = poweroutlet.device.site
-        self.fields['rack'].queryset = Rack.objects.filter(site=poweroutlet.device.site)
+        # Initialize rack choices if site is set
+        if self.initial.get('site'):
+            self.fields['rack'].queryset = Rack.objects.filter(site=self.initial['site'])
+        else:
+            self.fields['rack'].choices = []
 
 
-        # Initialize device choices
-        if self.is_bound and self.data.get('rack'):
-            self.fields['device'].queryset = Device.objects.filter(rack=self.data['rack'])
-        elif self.initial.get('rack', None):
+        # Initialize device choices if rack or site is set
+        if self.initial.get('rack'):
             self.fields['device'].queryset = Device.objects.filter(rack=self.initial['rack'])
             self.fields['device'].queryset = Device.objects.filter(rack=self.initial['rack'])
+        elif self.initial.get('site'):
+            self.fields['device'].queryset = Device.objects.filter(site=self.initial['site'], rack__isnull=True)
         else:
         else:
-            self.fields['device'].queryset = Device.objects.filter(site=poweroutlet.device.site,
-                                                                   rack__isnull=True)
+            self.fields['device'].choices = []
 
 
-        # Initialize port choices
-        if self.is_bound:
-            self.fields['port'].queryset = PowerPort.objects.filter(device__pk=self.data['device'])
-        elif self.initial.get('device', None):
-            self.fields['port'].queryset = PowerPort.objects.filter(device_pk=self.initial['device'])
+        # Initialize port choices if device is set
+        if self.initial.get('device'):
+            self.fields['port'].queryset = PowerPort.objects.filter(device=self.initial['device'])
         else:
         else:
             self.fields['port'].choices = []
             self.fields['port'].choices = []
 
 
@@ -1468,19 +1468,13 @@ class InterfaceConnectionForm(BootstrapMixin, forms.ModelForm):
         ]
         ]
 
 
         # Initialize rack_b choices if site_b is set
         # Initialize rack_b choices if site_b is set
-        if self.is_bound and self.data.get('site_b'):
-            self.fields['rack_b'].queryset = Rack.objects.filter(site__pk=self.data['site_b'])
-        elif self.initial.get('site_b'):
+        if self.initial.get('site_b'):
             self.fields['rack_b'].queryset = Rack.objects.filter(site=self.initial['site_b'])
             self.fields['rack_b'].queryset = Rack.objects.filter(site=self.initial['site_b'])
         else:
         else:
             self.fields['rack_b'].choices = []
             self.fields['rack_b'].choices = []
 
 
         # Initialize device_b choices if rack_b or site_b is set
         # Initialize device_b choices if rack_b or site_b is set
-        if self.is_bound and self.data.get('rack_b'):
-            self.fields['device_b'].queryset = Device.objects.filter(rack__pk=self.data['rack_b'])
-        elif self.is_bound and self.data.get('site_b'):
-            self.fields['device_b'].queryset = Device.objects.filter(site__pk=self.data['site_b'], rack__isnull=True)
-        elif self.initial.get('rack_b'):
+        if self.initial.get('rack_b'):
             self.fields['device_b'].queryset = Device.objects.filter(rack=self.initial['rack_b'])
             self.fields['device_b'].queryset = Device.objects.filter(rack=self.initial['rack_b'])
         elif self.initial.get('site_b'):
         elif self.initial.get('site_b'):
             self.fields['device_b'].queryset = Device.objects.filter(site=self.initial['site_b'], rack__isnull=True)
             self.fields['device_b'].queryset = Device.objects.filter(site=self.initial['site_b'], rack__isnull=True)
@@ -1488,13 +1482,7 @@ class InterfaceConnectionForm(BootstrapMixin, forms.ModelForm):
             self.fields['device_b'].choices = []
             self.fields['device_b'].choices = []
 
 
         # Initialize interface_b choices if device_b is set
         # Initialize interface_b choices if device_b is set
-        if self.is_bound:
-            device_b_interfaces = Interface.objects.filter(device=self.data['device_b']).exclude(
-                form_factor__in=VIRTUAL_IFACE_TYPES
-            ).select_related(
-                'circuit_termination', 'connected_as_a', 'connected_as_b'
-            )
-        elif self.initial.get('device_b'):
+        if self.initial.get('device_b'):
             device_b_interfaces = Interface.objects.filter(device=self.initial['device_b']).exclude(
             device_b_interfaces = Interface.objects.filter(device=self.initial['device_b']).exclude(
                 form_factor__in=VIRTUAL_IFACE_TYPES
                 form_factor__in=VIRTUAL_IFACE_TYPES
             ).select_related(
             ).select_related(

+ 1 - 1
netbox/dcim/models.py

@@ -293,7 +293,7 @@ class Site(CreatedUpdatedModel, CustomFieldModel):
 
 
     @property
     @property
     def count_devices(self):
     def count_devices(self):
-        return Device.objects.filter(rack__site=self).count()
+        return Device.objects.filter(site=self).count()
 
 
     @property
     @property
     def count_circuits(self):
     def count_circuits(self):

+ 21 - 7
netbox/dcim/views.py

@@ -171,7 +171,7 @@ def site(request, slug):
     site = get_object_or_404(Site.objects.select_related('region', 'tenant__group'), slug=slug)
     site = get_object_or_404(Site.objects.select_related('region', 'tenant__group'), slug=slug)
     stats = {
     stats = {
         'rack_count': Rack.objects.filter(site=site).count(),
         'rack_count': Rack.objects.filter(site=site).count(),
-        'device_count': Device.objects.filter(rack__site=site).count(),
+        'device_count': Device.objects.filter(site=site).count(),
         'prefix_count': Prefix.objects.filter(site=site).count(),
         'prefix_count': Prefix.objects.filter(site=site).count(),
         'vlan_count': VLAN.objects.filter(site=site).count(),
         'vlan_count': VLAN.objects.filter(site=site).count(),
         'circuit_count': Circuit.objects.filter(terminations__site=site).count(),
         'circuit_count': Circuit.objects.filter(terminations__site=site).count(),
@@ -844,7 +844,9 @@ def consoleport_connect(request, pk):
 
 
     else:
     else:
         form = forms.ConsolePortConnectionForm(instance=consoleport, initial={
         form = forms.ConsolePortConnectionForm(instance=consoleport, initial={
-            'rack': consoleport.device.rack,
+            'site': request.GET.get('site', consoleport.device.site),
+            'rack': request.GET.get('rack', None),
+            'console_server': request.GET.get('console_server', None),
             'connection_status': CONNECTION_STATUS_CONNECTED,
             'connection_status': CONNECTION_STATUS_CONNECTED,
         })
         })
 
 
@@ -927,7 +929,7 @@ def consoleserverport_connect(request, pk):
     consoleserverport = get_object_or_404(ConsoleServerPort, pk=pk)
     consoleserverport = get_object_or_404(ConsoleServerPort, pk=pk)
 
 
     if request.method == 'POST':
     if request.method == 'POST':
-        form = forms.ConsoleServerPortConnectionForm(consoleserverport, request.POST)
+        form = forms.ConsoleServerPortConnectionForm(request.POST)
         if form.is_valid():
         if form.is_valid():
             consoleport = form.cleaned_data['port']
             consoleport = form.cleaned_data['port']
             consoleport.cs_port = consoleserverport
             consoleport.cs_port = consoleserverport
@@ -942,7 +944,12 @@ def consoleserverport_connect(request, pk):
             return redirect('dcim:device', pk=consoleserverport.device.pk)
             return redirect('dcim:device', pk=consoleserverport.device.pk)
 
 
     else:
     else:
-        form = forms.ConsoleServerPortConnectionForm(consoleserverport, initial={'rack': consoleserverport.device.rack})
+        form = forms.ConsoleServerPortConnectionForm(initial={
+            'site': request.GET.get('site', consoleserverport.device.site),
+            'rack': request.GET.get('rack', None),
+            'device': request.GET.get('device', None),
+            'connection_status': CONNECTION_STATUS_CONNECTED,
+        })
 
 
     return render(request, 'dcim/consoleserverport_connect.html', {
     return render(request, 'dcim/consoleserverport_connect.html', {
         'consoleserverport': consoleserverport,
         'consoleserverport': consoleserverport,
@@ -1030,7 +1037,9 @@ def powerport_connect(request, pk):
 
 
     else:
     else:
         form = forms.PowerPortConnectionForm(instance=powerport, initial={
         form = forms.PowerPortConnectionForm(instance=powerport, initial={
-            'rack': powerport.device.rack,
+            'site': request.GET.get('site', powerport.device.site),
+            'rack': request.GET.get('rack', None),
+            'pdu': request.GET.get('pdu', None),
             'connection_status': CONNECTION_STATUS_CONNECTED,
             'connection_status': CONNECTION_STATUS_CONNECTED,
         })
         })
 
 
@@ -1113,7 +1122,7 @@ def poweroutlet_connect(request, pk):
     poweroutlet = get_object_or_404(PowerOutlet, pk=pk)
     poweroutlet = get_object_or_404(PowerOutlet, pk=pk)
 
 
     if request.method == 'POST':
     if request.method == 'POST':
-        form = forms.PowerOutletConnectionForm(poweroutlet, request.POST)
+        form = forms.PowerOutletConnectionForm(request.POST)
         if form.is_valid():
         if form.is_valid():
             powerport = form.cleaned_data['port']
             powerport = form.cleaned_data['port']
             powerport.power_outlet = poweroutlet
             powerport.power_outlet = poweroutlet
@@ -1128,7 +1137,12 @@ def poweroutlet_connect(request, pk):
             return redirect('dcim:device', pk=poweroutlet.device.pk)
             return redirect('dcim:device', pk=poweroutlet.device.pk)
 
 
     else:
     else:
-        form = forms.PowerOutletConnectionForm(poweroutlet, initial={'rack': poweroutlet.device.rack})
+        form = forms.PowerOutletConnectionForm(initial={
+            'site': request.GET.get('site', poweroutlet.device.site),
+            'rack': request.GET.get('rack', None),
+            'device': request.GET.get('device', None),
+            'connection_status': CONNECTION_STATUS_CONNECTED,
+        })
 
 
     return render(request, 'dcim/poweroutlet_connect.html', {
     return render(request, 'dcim/poweroutlet_connect.html', {
         'poweroutlet': poweroutlet,
         'poweroutlet': poweroutlet,

+ 1 - 1
netbox/extras/management/commands/run_inventory.py

@@ -49,7 +49,7 @@ class Command(BaseCommand):
                 self.stdout.write("Running inventory for these sites: {}".format(', '.join(site_names)))
                 self.stdout.write("Running inventory for these sites: {}".format(', '.join(site_names)))
             else:
             else:
                 raise CommandError("One or more sites specified but none found.")
                 raise CommandError("One or more sites specified but none found.")
-            device_list = device_list.filter(rack__site__in=sites)
+            device_list = device_list.filter(site__in=sites)
 
 
         # --name: Filter devices by name matching a regex
         # --name: Filter devices by name matching a regex
         if options['name']:
         if options['name']:

+ 6 - 4
netbox/ipam/forms.py

@@ -333,9 +333,11 @@ class IPAddressForm(BootstrapMixin, CustomFieldForm):
                 self.initial['nat_site'] = self.instance.nat_inside.interface.device.site.pk
                 self.initial['nat_site'] = self.instance.nat_inside.interface.device.site.pk
                 self.initial['nat_device'] = self.instance.nat_inside.interface.device.pk
                 self.initial['nat_device'] = self.instance.nat_inside.interface.device.pk
                 self.fields['nat_device'].queryset = Device.objects.filter(
                 self.fields['nat_device'].queryset = Device.objects.filter(
-                    rack__site=nat_inside.interface.device.site)
+                    site=nat_inside.interface.device.site
+                )
                 self.fields['nat_inside'].queryset = IPAddress.objects.filter(
                 self.fields['nat_inside'].queryset = IPAddress.objects.filter(
-                    interface__device=nat_inside.interface.device)
+                    interface__device=nat_inside.interface.device
+                )
             else:
             else:
                 self.fields['nat_inside'].queryset = IPAddress.objects.filter(pk=nat_inside.pk)
                 self.fields['nat_inside'].queryset = IPAddress.objects.filter(pk=nat_inside.pk)
 
 
@@ -343,9 +345,9 @@ class IPAddressForm(BootstrapMixin, CustomFieldForm):
 
 
             # Initialize nat_device choices if nat_site is set
             # Initialize nat_device choices if nat_site is set
             if self.is_bound and self.data.get('nat_site'):
             if self.is_bound and self.data.get('nat_site'):
-                self.fields['nat_device'].queryset = Device.objects.filter(rack__site__pk=self.data['nat_site'])
+                self.fields['nat_device'].queryset = Device.objects.filter(site__pk=self.data['nat_site'])
             elif self.initial.get('nat_site'):
             elif self.initial.get('nat_site'):
-                self.fields['nat_device'].queryset = Device.objects.filter(rack__site=self.initial['nat_site'])
+                self.fields['nat_device'].queryset = Device.objects.filter(site=self.initial['nat_site'])
             else:
             else:
                 self.fields['nat_device'].choices = []
                 self.fields['nat_device'].choices = []
 
 

+ 1 - 1
netbox/templates/circuits/provider.html

@@ -152,7 +152,7 @@
                         </td>
                         </td>
                         <td>
                         <td>
                             {% if c.tenant %}
                             {% if c.tenant %}
-                                <a href="{% url 'tenants:tenant' slug=c.tenant.slug %}">{{ c.tenant }}</a>
+                                <a href="{% url 'tenancy:tenant' slug=c.tenant.slug %}">{{ c.tenant }}</a>
                             {% else %}
                             {% else %}
                                 <span class="text-muted">&mdash;</span>
                                 <span class="text-muted">&mdash;</span>
                             {% endif %}
                             {% endif %}