Merge branch 'develop' into develop-2.3

This commit is contained in:
Jeremy Stretch
2018-02-06 14:58:11 -05:00
62 changed files with 571 additions and 515 deletions

View File

@@ -57,7 +57,7 @@ class VRFCSVForm(forms.ModelForm):
class Meta:
model = VRF
fields = ['name', 'rd', 'tenant', 'enforce_unique', 'description']
fields = VRF.csv_headers
help_texts = {
'name': 'VRF name',
}
@@ -102,7 +102,7 @@ class RIRCSVForm(forms.ModelForm):
class Meta:
model = RIR
fields = ['name', 'slug', 'is_private']
fields = RIR.csv_headers
help_texts = {
'name': 'RIR name',
}
@@ -144,7 +144,7 @@ class AggregateCSVForm(forms.ModelForm):
class Meta:
model = Aggregate
fields = ['prefix', 'rir', 'date_added', 'description']
fields = Aggregate.csv_headers
class AggregateBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
@@ -185,7 +185,7 @@ class RoleCSVForm(forms.ModelForm):
class Meta:
model = Role
fields = ['name', 'slug']
fields = Role.csv_headers
help_texts = {
'name': 'Role name',
}
@@ -299,9 +299,7 @@ class PrefixCSVForm(forms.ModelForm):
class Meta:
model = Prefix
fields = [
'prefix', 'vrf', 'tenant', 'site', 'vlan_group', 'vlan_vid', 'status', 'role', 'is_pool', 'description',
]
fields = Prefix.csv_headers
def clean(self):
@@ -609,10 +607,7 @@ class IPAddressCSVForm(forms.ModelForm):
class Meta:
model = IPAddress
fields = [
'address', 'vrf', 'tenant', 'status', 'role', 'device', 'virtual_machine', 'interface_name', 'is_primary',
'description',
]
fields = IPAddress.csv_headers
def clean(self):
@@ -759,7 +754,7 @@ class VLANGroupCSVForm(forms.ModelForm):
class Meta:
model = VLANGroup
fields = ['site', 'name', 'slug']
fields = VLANGroup.csv_headers
help_texts = {
'name': 'Name of VLAN group',
}
@@ -849,7 +844,7 @@ class VLANCSVForm(forms.ModelForm):
class Meta:
model = VLAN
fields = ['site', 'group_name', 'vid', 'name', 'tenant', 'status', 'role', 'description']
fields = VLAN.csv_headers
help_texts = {
'vid': 'Numeric VLAN ID (1-4095)',
'name': 'VLAN name',

View File

@@ -14,7 +14,6 @@ from dcim.models import Interface
from extras.models import CustomFieldModel, CustomFieldValue
from tenancy.models import Tenant
from utilities.models import CreatedUpdatedModel
from utilities.utils import csv_format
from .constants import *
from .fields import IPNetworkField, IPAddressField
from .querysets import PrefixQuerySet
@@ -49,13 +48,13 @@ class VRF(CreatedUpdatedModel, CustomFieldModel):
return reverse('ipam:vrf', args=[self.pk])
def to_csv(self):
return csv_format([
return (
self.name,
self.rd,
self.tenant.name if self.tenant else None,
self.enforce_unique,
self.description,
])
)
@property
def display_name(self):
@@ -75,6 +74,8 @@ class RIR(models.Model):
is_private = models.BooleanField(default=False, verbose_name='Private',
help_text='IP space managed by this RIR is considered private')
csv_headers = ['name', 'slug', 'is_private']
class Meta:
ordering = ['name']
verbose_name = 'RIR'
@@ -86,6 +87,13 @@ class RIR(models.Model):
def get_absolute_url(self):
return "{}?rir={}".format(reverse('ipam:aggregate_list'), self.slug)
def to_csv(self):
return (
self.name,
self.slug,
self.is_private,
)
@python_2_unicode_compatible
class Aggregate(CreatedUpdatedModel, CustomFieldModel):
@@ -147,12 +155,12 @@ class Aggregate(CreatedUpdatedModel, CustomFieldModel):
super(Aggregate, self).save(*args, **kwargs)
def to_csv(self):
return csv_format([
return (
self.prefix,
self.rir.name,
self.date_added.isoformat() if self.date_added else None,
self.date_added,
self.description,
])
)
def get_utilization(self):
"""
@@ -173,19 +181,20 @@ class Role(models.Model):
slug = models.SlugField(unique=True)
weight = models.PositiveSmallIntegerField(default=1000)
csv_headers = ['name', 'slug', 'weight']
class Meta:
ordering = ['weight', 'name']
def __str__(self):
return self.name
@property
def count_prefixes(self):
return self.prefixes.count()
@property
def count_vlans(self):
return self.vlans.count()
def to_csv(self):
return (
self.name,
self.slug,
self.weight,
)
@python_2_unicode_compatible
@@ -262,7 +271,7 @@ class Prefix(CreatedUpdatedModel, CustomFieldModel):
super(Prefix, self).save(*args, **kwargs)
def to_csv(self):
return csv_format([
return (
self.prefix,
self.vrf.rd if self.vrf else None,
self.tenant.name if self.tenant else None,
@@ -273,7 +282,7 @@ class Prefix(CreatedUpdatedModel, CustomFieldModel):
self.role.name if self.role else None,
self.is_pool,
self.description,
])
)
def get_status_class(self):
return STATUS_CHOICE_CLASSES[self.status]
@@ -461,7 +470,7 @@ class IPAddress(CreatedUpdatedModel, CustomFieldModel):
else:
is_primary = False
return csv_format([
return (
self.address,
self.vrf.rd if self.vrf else None,
self.tenant.name if self.tenant else None,
@@ -472,7 +481,7 @@ class IPAddress(CreatedUpdatedModel, CustomFieldModel):
self.interface.name if self.interface else None,
is_primary,
self.description,
])
)
@property
def device(self):
@@ -502,6 +511,8 @@ class VLANGroup(models.Model):
slug = models.SlugField()
site = models.ForeignKey('dcim.Site', related_name='vlan_groups', on_delete=models.PROTECT, blank=True, null=True)
csv_headers = ['name', 'slug', 'site']
class Meta:
ordering = ['site', 'name']
unique_together = [
@@ -517,6 +528,13 @@ class VLANGroup(models.Model):
def get_absolute_url(self):
return "{}?group_id={}".format(reverse('ipam:vlan_list'), self.pk)
def to_csv(self):
return (
self.name,
self.slug,
self.site.name if self.site else None,
)
def get_next_available_vid(self):
"""
Return the first available VLAN ID (1-4094) in the group.
@@ -577,7 +595,7 @@ class VLAN(CreatedUpdatedModel, CustomFieldModel):
})
def to_csv(self):
return csv_format([
return (
self.site.name if self.site else None,
self.group.name if self.group else None,
self.vid,
@@ -586,7 +604,7 @@ class VLAN(CreatedUpdatedModel, CustomFieldModel):
self.get_status_display(),
self.role.name if self.role else None,
self.description,
])
)
@property
def display_name(self):

View File

@@ -37,6 +37,14 @@ UTILIZATION_GRAPH = """
{% if record.pk %}{% utilization_graph record.get_utilization %}{% else %}—{% endif %}
"""
ROLE_PREFIX_COUNT = """
<a href="{% url 'ipam:prefix_list' %}?role={{ record.slug }}">{{ value }}</a>
"""
ROLE_VLAN_COUNT = """
<a href="{% url 'ipam:vlan_list' %}?role={{ record.slug }}">{{ value }}</a>
"""
ROLE_ACTIONS = """
{% if perms.ipam.change_role %}
<a href="{% url 'ipam:role_edit' slug=record.slug %}" class="btn btn-xs btn-warning"><i class="glyphicon glyphicon-pencil" aria-hidden="true"></i></a>
@@ -220,10 +228,18 @@ class AggregateDetailTable(AggregateTable):
class RoleTable(BaseTable):
pk = ToggleColumn()
name = tables.Column(verbose_name='Name')
prefix_count = tables.Column(accessor=Accessor('count_prefixes'), orderable=False, verbose_name='Prefixes')
vlan_count = tables.Column(accessor=Accessor('count_vlans'), orderable=False, verbose_name='VLANs')
slug = tables.Column(verbose_name='Slug')
prefix_count = tables.TemplateColumn(
accessor=Accessor('prefixes.count'),
template_code=ROLE_PREFIX_COUNT,
orderable=False,
verbose_name='Prefixes'
)
vlan_count = tables.TemplateColumn(
accessor=Accessor('vlans.count'),
template_code=ROLE_VLAN_COUNT,
orderable=False,
verbose_name='VLANs'
)
actions = tables.TemplateColumn(template_code=ROLE_ACTIONS, attrs={'td': {'class': 'text-right'}}, verbose_name='')
class Meta(BaseTable.Meta):