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

Closes #7120: Add termination_date field to Circuit

jeremystretch 3 лет назад
Родитель
Сommit
341615668b

+ 1 - 1
docs/models/circuits/circuit.md

@@ -13,7 +13,7 @@ Each circuit is also assigned one of the following operational statuses:
 * Deprovisioning
 * Decommissioned
 
-Circuits also have optional fields for annotating their installation date and commit rate, and may be assigned to NetBox tenants.
+Circuits also have optional fields for annotating their installation and termination dates and commit rate, and may be assigned to NetBox tenants.
 
 !!! note
     NetBox currently models only physical circuits: those which have exactly two endpoints. It is common to layer virtualized constructs (_virtual circuits_) such as MPLS or EVPN tunnels on top of these, however NetBox does not yet support virtual circuit modeling.

+ 3 - 0
docs/release-notes/version-3.3.md

@@ -18,6 +18,7 @@
 * [#1202](https://github.com/netbox-community/netbox/issues/1202) - Support overlapping assignment of NAT IP addresses
 * [#4350](https://github.com/netbox-community/netbox/issues/4350) - Illustrate reservations vertically alongside rack elevations
 * [#5303](https://github.com/netbox-community/netbox/issues/5303) - A virtual machine may be assigned to a site and/or cluster
+* [#7120](https://github.com/netbox-community/netbox/issues/7120) - Add `termination_date` field to Circuit
 * [#7744](https://github.com/netbox-community/netbox/issues/7744) - Add `status` field to Location
 * [#8222](https://github.com/netbox-community/netbox/issues/8222) - Enable the assignment of a VM to a specific host device within a cluster
 * [#8471](https://github.com/netbox-community/netbox/issues/8471) - Add `status` field to Cluster
@@ -32,6 +33,8 @@
 
 ### REST API Changes
 
+* circuits.Circuit
+    * Added optional `termination_date` field
 * dcim.Device
     * The `position` field has been changed from an integer to a decimal
 * dcim.DeviceType

+ 3 - 3
netbox/circuits/api/serializers.py

@@ -92,9 +92,9 @@ class CircuitSerializer(NetBoxModelSerializer):
     class Meta:
         model = Circuit
         fields = [
-            'id', 'url', 'display', 'cid', 'provider', 'type', 'status', 'tenant', 'install_date', 'commit_rate',
-            'description', 'termination_a', 'termination_z', 'comments', 'tags', 'custom_fields', 'created',
-            'last_updated',
+            'id', 'url', 'display', 'cid', 'provider', 'type', 'status', 'tenant', 'install_date', 'termination_date',
+            'commit_rate', 'description', 'termination_a', 'termination_z', 'comments', 'tags', 'custom_fields',
+            'created', 'last_updated',
         ]
 
 

+ 1 - 1
netbox/circuits/filtersets.py

@@ -183,7 +183,7 @@ class CircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilte
 
     class Meta:
         model = Circuit
-        fields = ['id', 'cid', 'description', 'install_date', 'commit_rate']
+        fields = ['id', 'cid', 'description', 'install_date', 'termination_date', 'commit_rate']
 
     def search(self, queryset, name, value):
         if not value.strip():

+ 12 - 2
netbox/circuits/forms/bulk_edit.py

@@ -7,7 +7,7 @@ from ipam.models import ASN
 from netbox.forms import NetBoxModelBulkEditForm
 from tenancy.models import Tenant
 from utilities.forms import (
-    add_blank_choice, CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SmallTextarea,
+    add_blank_choice, CommentField, DatePicker, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SmallTextarea,
     StaticSelect,
 )
 
@@ -122,6 +122,14 @@ class CircuitBulkEditForm(NetBoxModelBulkEditForm):
         queryset=Tenant.objects.all(),
         required=False
     )
+    install_date = forms.DateField(
+        required=False,
+        widget=DatePicker()
+    )
+    termination_date = forms.DateField(
+        required=False,
+        widget=DatePicker()
+    )
     commit_rate = forms.IntegerField(
         required=False,
         label='Commit rate (Kbps)'
@@ -137,7 +145,9 @@ class CircuitBulkEditForm(NetBoxModelBulkEditForm):
 
     model = Circuit
     fieldsets = (
-        (None, ('type', 'provider', 'status', 'tenant', 'commit_rate', 'description')),
+        ('Circuit', ('provider', 'type', 'status', 'description')),
+        ('Service Parameters', ('install_date', 'termination_date', 'commit_rate')),
+        ('Tenancy', ('tenant',)),
     )
     nullable_fields = (
         'tenant', 'commit_rate', 'description', 'comments',

+ 2 - 1
netbox/circuits/forms/bulk_import.py

@@ -72,5 +72,6 @@ class CircuitCSVForm(NetBoxModelCSVForm):
     class Meta:
         model = Circuit
         fields = [
-            'cid', 'provider', 'type', 'status', 'tenant', 'install_date', 'commit_rate', 'description', 'comments',
+            'cid', 'provider', 'type', 'status', 'tenant', 'install_date', 'termination_date', 'commit_rate',
+            'description', 'comments',
         ]

+ 10 - 2
netbox/circuits/forms/filtersets.py

@@ -7,7 +7,7 @@ from dcim.models import Region, Site, SiteGroup
 from ipam.models import ASN
 from netbox.forms import NetBoxModelFilterSetForm
 from tenancy.forms import TenancyFilterForm, ContactModelFilterForm
-from utilities.forms import DynamicModelMultipleChoiceField, MultipleChoiceField, TagFilterField
+from utilities.forms import DatePicker, DynamicModelMultipleChoiceField, MultipleChoiceField, TagFilterField
 
 __all__ = (
     'CircuitFilterForm',
@@ -84,7 +84,7 @@ class CircuitFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFi
     fieldsets = (
         (None, ('q', 'tag')),
         ('Provider', ('provider_id', 'provider_network_id')),
-        ('Attributes', ('type_id', 'status', 'commit_rate')),
+        ('Attributes', ('type_id', 'status', 'install_date', 'termination_date', 'commit_rate')),
         ('Location', ('region_id', 'site_group_id', 'site_id')),
         ('Tenant', ('tenant_group_id', 'tenant_id')),
         ('Contacts', ('contact', 'contact_role', 'contact_group')),
@@ -130,6 +130,14 @@ class CircuitFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFi
         },
         label=_('Site')
     )
+    install_date = forms.DateField(
+        required=False,
+        widget=DatePicker
+    )
+    termination_date = forms.DateField(
+        required=False,
+        widget=DatePicker
+    )
     commit_rate = forms.IntegerField(
         required=False,
         min_value=0,

+ 5 - 3
netbox/circuits/forms/models.py

@@ -93,15 +93,16 @@ class CircuitForm(TenancyForm, NetBoxModelForm):
     comments = CommentField()
 
     fieldsets = (
-        ('Circuit', ('provider', 'cid', 'type', 'status', 'install_date', 'commit_rate', 'description', 'tags')),
+        ('Circuit', ('provider', 'cid', 'type', 'status', 'description', 'tags')),
+        ('Service Parameters', ('install_date', 'termination_date', 'commit_rate')),
         ('Tenancy', ('tenant_group', 'tenant')),
     )
 
     class Meta:
         model = Circuit
         fields = [
-            'cid', 'type', 'provider', 'status', 'install_date', 'commit_rate', 'description', 'tenant_group', 'tenant',
-            'comments', 'tags',
+            'cid', 'type', 'provider', 'status', 'install_date', 'termination_date', 'commit_rate', 'description',
+            'tenant_group', 'tenant', 'comments', 'tags',
         ]
         help_texts = {
             'cid': "Unique circuit ID",
@@ -110,6 +111,7 @@ class CircuitForm(TenancyForm, NetBoxModelForm):
         widgets = {
             'status': StaticSelect(),
             'install_date': DatePicker(),
+            'termination_date': DatePicker(),
             'commit_rate': SelectSpeedWidget(),
         }
 

+ 18 - 0
netbox/circuits/migrations/0036_circuit_termination_date.py

@@ -0,0 +1,18 @@
+# Generated by Django 4.0.5 on 2022-06-22 18:51
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('circuits', '0035_provider_asns'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='circuit',
+            name='termination_date',
+            field=models.DateField(blank=True, null=True),
+        ),
+    ]

+ 7 - 2
netbox/circuits/models/circuits.py

@@ -78,7 +78,12 @@ class Circuit(NetBoxModel):
     install_date = models.DateField(
         blank=True,
         null=True,
-        verbose_name='Date installed'
+        verbose_name='Installed'
+    )
+    termination_date = models.DateField(
+        blank=True,
+        null=True,
+        verbose_name='Terminates'
     )
     commit_rate = models.PositiveIntegerField(
         blank=True,
@@ -119,7 +124,7 @@ class Circuit(NetBoxModel):
     )
 
     clone_fields = [
-        'provider', 'type', 'status', 'tenant', 'install_date', 'commit_rate', 'description',
+        'provider', 'type', 'status', 'tenant', 'install_date', 'termination_date', 'commit_rate', 'description',
     ]
 
     class Meta:

+ 1 - 1
netbox/circuits/tables/circuits.py

@@ -70,7 +70,7 @@ class CircuitTable(NetBoxTable):
         model = Circuit
         fields = (
             'pk', 'id', 'cid', 'provider', 'type', 'status', 'tenant', 'termination_a', 'termination_z', 'install_date',
-            'commit_rate', 'description', 'comments', 'contacts', 'tags', 'created', 'last_updated',
+            'termination_date', 'commit_rate', 'description', 'comments', 'contacts', 'tags', 'created', 'last_updated',
         )
         default_columns = (
             'pk', 'cid', 'provider', 'type', 'status', 'tenant', 'termination_a', 'termination_z', 'description',

+ 10 - 6
netbox/circuits/tests/test_filtersets.py

@@ -208,12 +208,12 @@ class CircuitTestCase(TestCase, ChangeLoggedFilterSetTests):
         ProviderNetwork.objects.bulk_create(provider_networks)
 
         circuits = (
-            Circuit(provider=providers[0], tenant=tenants[0], type=circuit_types[0], cid='Test Circuit 1', install_date='2020-01-01', commit_rate=1000, status=CircuitStatusChoices.STATUS_ACTIVE, description='foobar1'),
-            Circuit(provider=providers[0], tenant=tenants[0], type=circuit_types[0], cid='Test Circuit 2', install_date='2020-01-02', commit_rate=2000, status=CircuitStatusChoices.STATUS_ACTIVE, description='foobar2'),
-            Circuit(provider=providers[0], tenant=tenants[1], type=circuit_types[0], cid='Test Circuit 3', install_date='2020-01-03', commit_rate=3000, status=CircuitStatusChoices.STATUS_PLANNED),
-            Circuit(provider=providers[1], tenant=tenants[1], type=circuit_types[1], cid='Test Circuit 4', install_date='2020-01-04', commit_rate=4000, status=CircuitStatusChoices.STATUS_PLANNED),
-            Circuit(provider=providers[1], tenant=tenants[2], type=circuit_types[1], cid='Test Circuit 5', install_date='2020-01-05', commit_rate=5000, status=CircuitStatusChoices.STATUS_OFFLINE),
-            Circuit(provider=providers[1], tenant=tenants[2], type=circuit_types[1], cid='Test Circuit 6', install_date='2020-01-06', commit_rate=6000, status=CircuitStatusChoices.STATUS_OFFLINE),
+            Circuit(provider=providers[0], tenant=tenants[0], type=circuit_types[0], cid='Test Circuit 1', install_date='2020-01-01', termination_date='2021-01-01', commit_rate=1000, status=CircuitStatusChoices.STATUS_ACTIVE, description='foobar1'),
+            Circuit(provider=providers[0], tenant=tenants[0], type=circuit_types[0], cid='Test Circuit 2', install_date='2020-01-02', termination_date='2021-01-02', commit_rate=2000, status=CircuitStatusChoices.STATUS_ACTIVE, description='foobar2'),
+            Circuit(provider=providers[0], tenant=tenants[1], type=circuit_types[0], cid='Test Circuit 3', install_date='2020-01-03', termination_date='2021-01-03', commit_rate=3000, status=CircuitStatusChoices.STATUS_PLANNED),
+            Circuit(provider=providers[1], tenant=tenants[1], type=circuit_types[1], cid='Test Circuit 4', install_date='2020-01-04', termination_date='2021-01-04', commit_rate=4000, status=CircuitStatusChoices.STATUS_PLANNED),
+            Circuit(provider=providers[1], tenant=tenants[2], type=circuit_types[1], cid='Test Circuit 5', install_date='2020-01-05', termination_date='2021-01-05', commit_rate=5000, status=CircuitStatusChoices.STATUS_OFFLINE),
+            Circuit(provider=providers[1], tenant=tenants[2], type=circuit_types[1], cid='Test Circuit 6', install_date='2020-01-06', termination_date='2021-01-06', commit_rate=6000, status=CircuitStatusChoices.STATUS_OFFLINE),
         )
         Circuit.objects.bulk_create(circuits)
 
@@ -235,6 +235,10 @@ class CircuitTestCase(TestCase, ChangeLoggedFilterSetTests):
         params = {'install_date': ['2020-01-01', '2020-01-02']}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
 
+    def test_termination_date(self):
+        params = {'termination_date': ['2021-01-01', '2021-01-02']}
+        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
+
     def test_commit_rate(self):
         params = {'commit_rate': ['1000', '2000']}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)

+ 1 - 0
netbox/circuits/tests/test_views.py

@@ -130,6 +130,7 @@ class CircuitTestCase(ViewTestCases.PrimaryObjectViewTestCase):
             'status': CircuitStatusChoices.STATUS_DECOMMISSIONED,
             'tenant': None,
             'install_date': datetime.date(2020, 1, 1),
+            'termination_date': datetime.date(2021, 1, 1),
             'commit_rate': 1000,
             'description': 'A new circuit',
             'comments': 'Some comments',

+ 4 - 0
netbox/templates/circuits/circuit.html

@@ -45,6 +45,10 @@
                         <th scope="row">Install Date</th>
                         <td>{{ object.install_date|annotated_date|placeholder }}</td>
                     </tr>
+                    <tr>
+                        <th scope="row">Termination Date</th>
+                        <td>{{ object.termination_date|annotated_date|placeholder }}</td>
+                    </tr>
                     <tr>
                         <th scope="row">Commit Rate</th>
                         <td>{{ object.commit_rate|humanize_speed|placeholder }}</td>