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

Merge branch 'develop' into feature

jeremystretch 4 лет назад
Родитель
Сommit
d0fbbbfb37

+ 1 - 1
.github/workflows/stale.yml

@@ -8,7 +8,7 @@ jobs:
   stale:
   stale:
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     steps:
     steps:
-      - uses: actions/stale@v3
+      - uses: actions/stale@v4
         with:
         with:
           close-issue-message: >
           close-issue-message: >
             This issue has been automatically closed due to lack of activity. In an
             This issue has been automatically closed due to lack of activity. In an

BIN
docs/media/installation/netbox_application_stack.png


+ 14 - 0
docs/release-notes/version-2.11.md

@@ -1,5 +1,19 @@
 # NetBox v2.11
 # NetBox v2.11
 
 
+## v2.11.11 (FUTURE)
+
+### Enhancements
+
+* [#6883](https://github.com/netbox-community/netbox/issues/6883) - Add C21 & C22 power types
+
+### Bug Fixes
+
+* [#6740](https://github.com/netbox-community/netbox/issues/6740) - Add import button to VM interfaces list
+* [#6892](https://github.com/netbox-community/netbox/issues/6892) - Fix validation of unit ranges when creating a rack reservation
+* [#6902](https://github.com/netbox-community/netbox/issues/6902) - Populate device field when cloning device components
+
+---
+
 ## v2.11.10 (2021-07-28)
 ## v2.11.10 (2021-07-28)
 
 
 ### Enhancements
 ### Enhancements

+ 17 - 1
docs/rest-api/filtering.md

@@ -69,6 +69,12 @@ Numeric based fields (ASN, VLAN ID, etc) support these lookup expressions:
 | `gt` | Greater than |
 | `gt` | Greater than |
 | `gte` | Greater than or equal to |
 | `gte` | Greater than or equal to |
 
 
+Here is an example of a numeric field lookup expression that will return all VLANs with a VLAN ID greater than 900:
+
+```no-highlight
+GET /api/ipam/vlans/?vid__gt=900
+```
+
 ### String Fields
 ### String Fields
 
 
 String based (char) fields (Name, Address, etc) support these lookup expressions:
 String based (char) fields (Name, Address, etc) support these lookup expressions:
@@ -86,7 +92,17 @@ String based (char) fields (Name, Address, etc) support these lookup expressions
 | `nie` | Inverse exact match (case-insensitive) |
 | `nie` | Inverse exact match (case-insensitive) |
 | `empty` | Is empty (boolean) |
 | `empty` | Is empty (boolean) |
 
 
+Here is an example of a lookup expression on a string field that will return all devices with `switch` in the name:
+
+```no-highlight
+GET /api/dcim/devices/?name__ic=switch
+```
+
 ### Foreign Keys & Other Fields
 ### Foreign Keys & Other Fields
 
 
 Certain other fields, namely foreign key relationships support just the negation
 Certain other fields, namely foreign key relationships support just the negation
-expression: `n`.
+expression: `n`. Here is an example of a lookup expression on a foreign key, it would return all the VLANs that don't have a VLAN Group ID of 3203:
+
+```no-highlight
+GET /api/ipam/vlans/?group_id__n=3203
+```

+ 4 - 0
netbox/dcim/choices.py

@@ -252,6 +252,7 @@ class PowerPortTypeChoices(ChoiceSet):
     TYPE_IEC_C14 = 'iec-60320-c14'
     TYPE_IEC_C14 = 'iec-60320-c14'
     TYPE_IEC_C16 = 'iec-60320-c16'
     TYPE_IEC_C16 = 'iec-60320-c16'
     TYPE_IEC_C20 = 'iec-60320-c20'
     TYPE_IEC_C20 = 'iec-60320-c20'
+    TYPE_IEC_C22 = 'iec-60320-c22'
     # IEC 60309
     # IEC 60309
     TYPE_IEC_PNE4H = 'iec-60309-p-n-e-4h'
     TYPE_IEC_PNE4H = 'iec-60309-p-n-e-4h'
     TYPE_IEC_PNE6H = 'iec-60309-p-n-e-6h'
     TYPE_IEC_PNE6H = 'iec-60309-p-n-e-6h'
@@ -351,6 +352,7 @@ class PowerPortTypeChoices(ChoiceSet):
             (TYPE_IEC_C14, 'C14'),
             (TYPE_IEC_C14, 'C14'),
             (TYPE_IEC_C16, 'C16'),
             (TYPE_IEC_C16, 'C16'),
             (TYPE_IEC_C20, 'C20'),
             (TYPE_IEC_C20, 'C20'),
+            (TYPE_IEC_C22, 'C22'),
         )),
         )),
         ('IEC 60309', (
         ('IEC 60309', (
             (TYPE_IEC_PNE4H, 'P+N+E 4H'),
             (TYPE_IEC_PNE4H, 'P+N+E 4H'),
@@ -467,6 +469,7 @@ class PowerOutletTypeChoices(ChoiceSet):
     TYPE_IEC_C13 = 'iec-60320-c13'
     TYPE_IEC_C13 = 'iec-60320-c13'
     TYPE_IEC_C15 = 'iec-60320-c15'
     TYPE_IEC_C15 = 'iec-60320-c15'
     TYPE_IEC_C19 = 'iec-60320-c19'
     TYPE_IEC_C19 = 'iec-60320-c19'
+    TYPE_IEC_C21 = 'iec-60320-c21'
     # IEC 60309
     # IEC 60309
     TYPE_IEC_PNE4H = 'iec-60309-p-n-e-4h'
     TYPE_IEC_PNE4H = 'iec-60309-p-n-e-4h'
     TYPE_IEC_PNE6H = 'iec-60309-p-n-e-6h'
     TYPE_IEC_PNE6H = 'iec-60309-p-n-e-6h'
@@ -558,6 +561,7 @@ class PowerOutletTypeChoices(ChoiceSet):
             (TYPE_IEC_C13, 'C13'),
             (TYPE_IEC_C13, 'C13'),
             (TYPE_IEC_C15, 'C15'),
             (TYPE_IEC_C15, 'C15'),
             (TYPE_IEC_C19, 'C19'),
             (TYPE_IEC_C19, 'C19'),
+            (TYPE_IEC_C21, 'C21'),
         )),
         )),
         ('IEC 60309', (
         ('IEC 60309', (
             (TYPE_IEC_PNE4H, 'P+N+E 4H'),
             (TYPE_IEC_PNE4H, 'P+N+E 4H'),

+ 17 - 0
netbox/dcim/models/device_components.py

@@ -237,6 +237,8 @@ class ConsolePort(ComponentModel, CableTermination, PathEndpoint):
         help_text='Port speed in bits per second'
         help_text='Port speed in bits per second'
     )
     )
 
 
+    clone_fields = ['device', 'type', 'speed']
+
     class Meta:
     class Meta:
         ordering = ('device', '_name')
         ordering = ('device', '_name')
         unique_together = ('device', 'name')
         unique_together = ('device', 'name')
@@ -267,6 +269,8 @@ class ConsoleServerPort(ComponentModel, CableTermination, PathEndpoint):
         help_text='Port speed in bits per second'
         help_text='Port speed in bits per second'
     )
     )
 
 
+    clone_fields = ['device', 'type', 'speed']
+
     class Meta:
     class Meta:
         ordering = ('device', '_name')
         ordering = ('device', '_name')
         unique_together = ('device', 'name')
         unique_together = ('device', 'name')
@@ -303,6 +307,8 @@ class PowerPort(ComponentModel, CableTermination, PathEndpoint):
         help_text="Allocated power draw (watts)"
         help_text="Allocated power draw (watts)"
     )
     )
 
 
+    clone_fields = ['device', 'maximum_draw', 'allocated_draw']
+
     class Meta:
     class Meta:
         ordering = ('device', '_name')
         ordering = ('device', '_name')
         unique_together = ('device', 'name')
         unique_together = ('device', 'name')
@@ -399,6 +405,8 @@ class PowerOutlet(ComponentModel, CableTermination, PathEndpoint):
         help_text="Phase (for three-phase feeds)"
         help_text="Phase (for three-phase feeds)"
     )
     )
 
 
+    clone_fields = ['device', 'type', 'power_port', 'feed_leg']
+
     class Meta:
     class Meta:
         ordering = ('device', '_name')
         ordering = ('device', '_name')
         unique_together = ('device', 'name')
         unique_together = ('device', 'name')
@@ -525,6 +533,8 @@ class Interface(ComponentModel, BaseInterface, CableTermination, PathEndpoint):
         related_query_name='interface'
         related_query_name='interface'
     )
     )
 
 
+    clone_fields = ['device', 'parent', 'lag', 'type', 'mgmt_only']
+
     class Meta:
     class Meta:
         ordering = ('device', CollateAsChar('_name'))
         ordering = ('device', CollateAsChar('_name'))
         unique_together = ('device', 'name')
         unique_together = ('device', 'name')
@@ -641,6 +651,8 @@ class FrontPort(ComponentModel, CableTermination):
         ]
         ]
     )
     )
 
 
+    clone_fields = ['device', 'type']
+
     class Meta:
     class Meta:
         ordering = ('device', '_name')
         ordering = ('device', '_name')
         unique_together = (
         unique_together = (
@@ -687,6 +699,7 @@ class RearPort(ComponentModel, CableTermination):
             MaxValueValidator(REARPORT_POSITIONS_MAX)
             MaxValueValidator(REARPORT_POSITIONS_MAX)
         ]
         ]
     )
     )
+    clone_fields = ['device', 'type', 'positions']
 
 
     class Meta:
     class Meta:
         ordering = ('device', '_name')
         ordering = ('device', '_name')
@@ -724,6 +737,8 @@ class DeviceBay(ComponentModel):
         null=True
         null=True
     )
     )
 
 
+    clone_fields = ['device']
+
     class Meta:
     class Meta:
         ordering = ('device', '_name')
         ordering = ('device', '_name')
         unique_together = ('device', 'name')
         unique_together = ('device', 'name')
@@ -806,6 +821,8 @@ class InventoryItem(MPTTModel, ComponentModel):
 
 
     objects = TreeManager()
     objects = TreeManager()
 
 
+    clone_fields = ['device', 'parent', 'manufacturer', 'part_id']
+
     class Meta:
     class Meta:
         ordering = ('device__id', 'parent__id', '_name')
         ordering = ('device__id', 'parent__id', '_name')
         unique_together = ('device', 'parent', 'name')
         unique_together = ('device', 'parent', 'name')

+ 5 - 2
netbox/utilities/forms/utils.py

@@ -32,7 +32,10 @@ def parse_numeric_range(string, base=10):
             begin, end = dash_range.split('-')
             begin, end = dash_range.split('-')
         except ValueError:
         except ValueError:
             begin, end = dash_range, dash_range
             begin, end = dash_range, dash_range
-        begin, end = int(begin.strip(), base=base), int(end.strip(), base=base) + 1
+        try:
+            begin, end = int(begin.strip(), base=base), int(end.strip(), base=base) + 1
+        except ValueError:
+            raise forms.ValidationError(f'Range "{dash_range}" is invalid.')
         values.extend(range(begin, end))
         values.extend(range(begin, end))
     return list(set(values))
     return list(set(values))
 
 
@@ -64,7 +67,7 @@ def parse_alphanumeric_range(string):
             else:
             else:
                 # Not a valid range (more than a single character)
                 # Not a valid range (more than a single character)
                 if not len(begin) == len(end) == 1:
                 if not len(begin) == len(end) == 1:
-                    raise forms.ValidationError('Range "{}" is invalid.'.format(dash_range))
+                    raise forms.ValidationError(f'Range "{dash_range}" is invalid.')
                 for n in list(range(ord(begin), ord(end) + 1)):
                 for n in list(range(ord(begin), ord(end) + 1)):
                     values.append(chr(n))
                     values.append(chr(n))
     return values
     return values

+ 1 - 1
netbox/virtualization/views.py

@@ -409,7 +409,7 @@ class VMInterfaceListView(generic.ObjectListView):
     filterset = filtersets.VMInterfaceFilterSet
     filterset = filtersets.VMInterfaceFilterSet
     filterset_form = forms.VMInterfaceFilterForm
     filterset_form = forms.VMInterfaceFilterForm
     table = tables.VMInterfaceTable
     table = tables.VMInterfaceTable
-    action_buttons = ('export',)
+    action_buttons = ('import', 'export')
 
 
 
 
 class VMInterfaceView(generic.ObjectView):
 class VMInterfaceView(generic.ObjectView):