mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Circuit.status (#3569)
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
from rest_framework import serializers
|
||||
from taggit_serializer.serializers import TaggitSerializer, TagListSerializerField
|
||||
|
||||
from circuits.constants import CIRCUIT_STATUS_CHOICES
|
||||
from circuits.choices import CircuitStatusChoices
|
||||
from circuits.models import Provider, Circuit, CircuitTermination, CircuitType
|
||||
from dcim.api.nested_serializers import NestedCableSerializer, NestedSiteSerializer
|
||||
from dcim.api.serializers import ConnectedEndpointSerializer
|
||||
@ -41,7 +41,7 @@ class CircuitTypeSerializer(ValidatedModelSerializer):
|
||||
|
||||
class CircuitSerializer(TaggitSerializer, CustomFieldModelSerializer):
|
||||
provider = NestedProviderSerializer()
|
||||
status = ChoiceField(choices=CIRCUIT_STATUS_CHOICES, required=False)
|
||||
status = ChoiceField(choices=CircuitStatusChoices, required=False)
|
||||
type = NestedCircuitTypeSerializer()
|
||||
tenant = NestedTenantSerializer(required=False, allow_null=True)
|
||||
tags = TagListSerializerField(required=False)
|
||||
|
29
netbox/circuits/choices.py
Normal file
29
netbox/circuits/choices.py
Normal file
@ -0,0 +1,29 @@
|
||||
from utilities.choices import ChoiceSet
|
||||
|
||||
|
||||
class CircuitStatusChoices(ChoiceSet):
|
||||
|
||||
STATUS_DEPROVISIONING = 'deprovisioning'
|
||||
STATUS_ACTIVE = 'active'
|
||||
STATUS_PLANNED = 'planned'
|
||||
STATUS_PROVISIONING = 'provisioning'
|
||||
STATUS_OFFLINE = 'offline'
|
||||
STATUS_DECOMMISSIONED = 'decommissioned'
|
||||
|
||||
CHOICES = (
|
||||
(STATUS_PLANNED, 'Planned'),
|
||||
(STATUS_PROVISIONING, 'Provisioning'),
|
||||
(STATUS_ACTIVE, 'Active'),
|
||||
(STATUS_OFFLINE, 'Offline'),
|
||||
(STATUS_DEPROVISIONING, 'Deprovisioning'),
|
||||
(STATUS_DECOMMISSIONED, 'Decommissioned'),
|
||||
)
|
||||
|
||||
LEGACY_MAP = {
|
||||
STATUS_DEPROVISIONING: 0,
|
||||
STATUS_ACTIVE: 1,
|
||||
STATUS_PLANNED: 2,
|
||||
STATUS_PROVISIONING: 3,
|
||||
STATUS_OFFLINE: 4,
|
||||
STATUS_DECOMMISSIONED: 5,
|
||||
}
|
@ -1,19 +1,3 @@
|
||||
# Circuit statuses
|
||||
CIRCUIT_STATUS_DEPROVISIONING = 0
|
||||
CIRCUIT_STATUS_ACTIVE = 1
|
||||
CIRCUIT_STATUS_PLANNED = 2
|
||||
CIRCUIT_STATUS_PROVISIONING = 3
|
||||
CIRCUIT_STATUS_OFFLINE = 4
|
||||
CIRCUIT_STATUS_DECOMMISSIONED = 5
|
||||
CIRCUIT_STATUS_CHOICES = [
|
||||
[CIRCUIT_STATUS_PLANNED, 'Planned'],
|
||||
[CIRCUIT_STATUS_PROVISIONING, 'Provisioning'],
|
||||
[CIRCUIT_STATUS_ACTIVE, 'Active'],
|
||||
[CIRCUIT_STATUS_OFFLINE, 'Offline'],
|
||||
[CIRCUIT_STATUS_DEPROVISIONING, 'Deprovisioning'],
|
||||
[CIRCUIT_STATUS_DECOMMISSIONED, 'Decommissioned'],
|
||||
]
|
||||
|
||||
# CircuitTermination sides
|
||||
TERM_SIDE_A = 'A'
|
||||
TERM_SIDE_Z = 'Z'
|
||||
|
@ -5,6 +5,7 @@ from dcim.models import Region, Site
|
||||
from extras.filters import CustomFieldFilterSet
|
||||
from tenancy.filtersets import TenancyFilterSet
|
||||
from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter, TreeNodeMultipleChoiceFilter
|
||||
from .choices import *
|
||||
from .constants import *
|
||||
from .models import Circuit, CircuitTermination, CircuitType, Provider
|
||||
|
||||
@ -84,7 +85,7 @@ class CircuitFilter(CustomFieldFilterSet, TenancyFilterSet):
|
||||
label='Circuit type (slug)',
|
||||
)
|
||||
status = django_filters.MultipleChoiceFilter(
|
||||
choices=CIRCUIT_STATUS_CHOICES,
|
||||
choices=CircuitStatusChoices,
|
||||
null_value=None
|
||||
)
|
||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||
|
@ -9,6 +9,7 @@ from utilities.forms import (
|
||||
APISelect, APISelectMultiple, add_blank_choice, BootstrapMixin, CommentField, CSVChoiceField,
|
||||
FilterChoiceField, SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple
|
||||
)
|
||||
from .choices import CircuitStatusChoices
|
||||
from .constants import *
|
||||
from .models import Circuit, CircuitTermination, CircuitType, Provider
|
||||
|
||||
@ -194,7 +195,7 @@ class CircuitCSVForm(forms.ModelForm):
|
||||
}
|
||||
)
|
||||
status = CSVChoiceField(
|
||||
choices=CIRCUIT_STATUS_CHOICES,
|
||||
choices=CircuitStatusChoices,
|
||||
required=False,
|
||||
help_text='Operational status'
|
||||
)
|
||||
@ -235,7 +236,7 @@ class CircuitBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEdit
|
||||
)
|
||||
)
|
||||
status = forms.ChoiceField(
|
||||
choices=add_blank_choice(CIRCUIT_STATUS_CHOICES),
|
||||
choices=add_blank_choice(CircuitStatusChoices),
|
||||
required=False,
|
||||
initial='',
|
||||
widget=StaticSelect2()
|
||||
@ -292,7 +293,7 @@ class CircuitFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
|
||||
)
|
||||
)
|
||||
status = forms.MultipleChoiceField(
|
||||
choices=CIRCUIT_STATUS_CHOICES,
|
||||
choices=CircuitStatusChoices,
|
||||
required=False,
|
||||
widget=StaticSelect2Multiple()
|
||||
)
|
||||
|
37
netbox/circuits/migrations/0016_circuit_status_slug.py
Normal file
37
netbox/circuits/migrations/0016_circuit_status_slug.py
Normal file
@ -0,0 +1,37 @@
|
||||
# Generated by Django 2.2.6 on 2019-11-07 03:36
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
CIRCUIT_STATUS_CHOICES = (
|
||||
(0, 'deprovisioning'),
|
||||
(1, 'active'),
|
||||
(2, 'planned'),
|
||||
(3, 'provisioning'),
|
||||
(4, 'offline'),
|
||||
(5, 'decommissioned')
|
||||
)
|
||||
|
||||
|
||||
def circuit_status_to_slug(apps, schema_editor):
|
||||
Circuit = apps.get_model('circuits', 'Circuit')
|
||||
for id, slug in CIRCUIT_STATUS_CHOICES:
|
||||
Circuit.objects.filter(status=str(id)).update(status=slug)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('circuits', '0015_custom_tag_models'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='circuit',
|
||||
name='status',
|
||||
field=models.CharField(default='active', max_length=50),
|
||||
),
|
||||
migrations.RunPython(
|
||||
code=circuit_status_to_slug
|
||||
)
|
||||
]
|
@ -9,6 +9,7 @@ from dcim.models import CableTermination
|
||||
from extras.models import CustomFieldModel, ObjectChange, TaggedItem
|
||||
from utilities.models import ChangeLoggedModel
|
||||
from utilities.utils import serialize_object
|
||||
from .choices import *
|
||||
from .constants import *
|
||||
|
||||
|
||||
@ -132,9 +133,10 @@ class Circuit(ChangeLoggedModel, CustomFieldModel):
|
||||
on_delete=models.PROTECT,
|
||||
related_name='circuits'
|
||||
)
|
||||
status = models.PositiveSmallIntegerField(
|
||||
choices=CIRCUIT_STATUS_CHOICES,
|
||||
default=CIRCUIT_STATUS_ACTIVE
|
||||
status = models.CharField(
|
||||
max_length=50,
|
||||
choices=CircuitStatusChoices,
|
||||
default=CircuitStatusChoices.STATUS_ACTIVE
|
||||
)
|
||||
tenant = models.ForeignKey(
|
||||
to='tenancy.Tenant',
|
||||
@ -171,6 +173,15 @@ class Circuit(ChangeLoggedModel, CustomFieldModel):
|
||||
'cid', 'provider', 'type', 'status', 'tenant', 'install_date', 'commit_rate', 'description', 'comments',
|
||||
]
|
||||
|
||||
STATUS_CLASS_MAP = {
|
||||
CircuitStatusChoices.STATUS_DEPROVISIONING: 'warning',
|
||||
CircuitStatusChoices.STATUS_ACTIVE: 'success',
|
||||
CircuitStatusChoices.STATUS_PLANNED: 'info',
|
||||
CircuitStatusChoices.STATUS_PROVISIONING: 'primary',
|
||||
CircuitStatusChoices.STATUS_OFFLINE: 'danger',
|
||||
CircuitStatusChoices.STATUS_DECOMMISSIONED: 'default',
|
||||
}
|
||||
|
||||
class Meta:
|
||||
ordering = ['provider', 'cid']
|
||||
unique_together = ['provider', 'cid']
|
||||
@ -195,7 +206,7 @@ class Circuit(ChangeLoggedModel, CustomFieldModel):
|
||||
)
|
||||
|
||||
def get_status_class(self):
|
||||
return STATUS_CLASSES[self.status]
|
||||
return self.STATUS_CLASS_MAP.get(self.status)
|
||||
|
||||
def _get_termination(self, side):
|
||||
for ct in self.terminations.all():
|
||||
|
@ -1,9 +1,10 @@
|
||||
from django.urls import reverse
|
||||
from rest_framework import status
|
||||
|
||||
from circuits.constants import CIRCUIT_STATUS_ACTIVE, TERM_SIDE_A, TERM_SIDE_Z
|
||||
from circuits.choices import CircuitStatusChoices
|
||||
from circuits.constants import TERM_SIDE_A, TERM_SIDE_Z
|
||||
from circuits.models import Circuit, CircuitTermination, CircuitType, Provider
|
||||
from dcim.models import Device, DeviceRole, DeviceType, Interface, Manufacturer, Site
|
||||
from dcim.models import Site
|
||||
from extras.constants import GRAPH_TYPE_PROVIDER
|
||||
from extras.models import Graph
|
||||
from utilities.testing import APITestCase
|
||||
@ -250,7 +251,7 @@ class CircuitTest(APITestCase):
|
||||
'cid': 'TEST0004',
|
||||
'provider': self.provider1.pk,
|
||||
'type': self.circuittype1.pk,
|
||||
'status': CIRCUIT_STATUS_ACTIVE,
|
||||
'status': CircuitStatusChoices.STATUS_ACTIVE,
|
||||
}
|
||||
|
||||
url = reverse('circuits-api:circuit-list')
|
||||
@ -270,19 +271,19 @@ class CircuitTest(APITestCase):
|
||||
'cid': 'TEST0004',
|
||||
'provider': self.provider1.pk,
|
||||
'type': self.circuittype1.pk,
|
||||
'status': CIRCUIT_STATUS_ACTIVE,
|
||||
'status': CircuitStatusChoices.STATUS_ACTIVE,
|
||||
},
|
||||
{
|
||||
'cid': 'TEST0005',
|
||||
'provider': self.provider1.pk,
|
||||
'type': self.circuittype1.pk,
|
||||
'status': CIRCUIT_STATUS_ACTIVE,
|
||||
'status': CircuitStatusChoices.STATUS_ACTIVE,
|
||||
},
|
||||
{
|
||||
'cid': 'TEST0006',
|
||||
'provider': self.provider1.pk,
|
||||
'type': self.circuittype1.pk,
|
||||
'status': CIRCUIT_STATUS_ACTIVE,
|
||||
'status': CircuitStatusChoices.STATUS_ACTIVE,
|
||||
},
|
||||
]
|
||||
|
||||
|
@ -3,7 +3,7 @@ class ChoiceSetMeta(type):
|
||||
Metaclass for ChoiceSet
|
||||
"""
|
||||
def __call__(cls, *args, **kwargs):
|
||||
# Django will check if a choices value is callable, and if so assume that it returns an iterable
|
||||
# Django will check if a 'choices' value is callable, and if so assume that it returns an iterable
|
||||
return getattr(cls, 'CHOICES', ())
|
||||
|
||||
def __iter__(cls):
|
||||
|
Reference in New Issue
Block a user