mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-25 18:08:38 -06:00
commit
4e64e1ea95
@ -112,6 +112,9 @@ Generate a random secret key of at least 50 alphanumeric characters. This key mu
|
|||||||
|
|
||||||
You may use the script located at `netbox/generate_secret_key.py` to generate a suitable key.
|
You may use the script located at `netbox/generate_secret_key.py` to generate a suitable key.
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
In the case of a highly available installation with multiple web servers, `SECRET_KEY` must be identical among all servers in order to maintain a persistent user session state.
|
||||||
|
|
||||||
# Run Database Migrations
|
# Run Database Migrations
|
||||||
|
|
||||||
Before NetBox can run, we need to install the database schema. This is done by running `./manage.py migrate` from the `netbox` directory (`/opt/netbox/netbox/` in our example):
|
Before NetBox can run, we need to install the database schema. This is done by running `./manage.py migrate` from the `netbox` directory (`/opt/netbox/netbox/` in our example):
|
||||||
|
@ -1,9 +1,40 @@
|
|||||||
import django_filters
|
import django_filters
|
||||||
|
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
from dcim.models import Site
|
from dcim.models import Site
|
||||||
from .models import Provider, Circuit, CircuitType
|
from .models import Provider, Circuit, CircuitType
|
||||||
|
|
||||||
|
|
||||||
|
class ProviderFilter(django_filters.FilterSet):
|
||||||
|
q = django_filters.MethodFilter(
|
||||||
|
action='search',
|
||||||
|
label='Search',
|
||||||
|
)
|
||||||
|
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
|
name='circuits__site',
|
||||||
|
queryset=Site.objects.all(),
|
||||||
|
label='Site',
|
||||||
|
)
|
||||||
|
site = django_filters.ModelMultipleChoiceFilter(
|
||||||
|
name='circuits__site',
|
||||||
|
queryset=Site.objects.all(),
|
||||||
|
to_field_name='slug',
|
||||||
|
label='Site (slug)',
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Provider
|
||||||
|
fields = ['q', 'name', 'account', 'asn']
|
||||||
|
|
||||||
|
def search(self, queryset, value):
|
||||||
|
value = value.strip()
|
||||||
|
return queryset.filter(
|
||||||
|
Q(name__icontains=value) |
|
||||||
|
Q(account__icontains=value)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class CircuitFilter(django_filters.FilterSet):
|
class CircuitFilter(django_filters.FilterSet):
|
||||||
q = django_filters.MethodFilter(
|
q = django_filters.MethodFilter(
|
||||||
action='search',
|
action='search',
|
||||||
|
@ -59,6 +59,16 @@ class ProviderBulkDeleteForm(ConfirmationForm):
|
|||||||
pk = forms.ModelMultipleChoiceField(queryset=Provider.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(queryset=Provider.objects.all(), widget=forms.MultipleHiddenInput)
|
||||||
|
|
||||||
|
|
||||||
|
def provider_site_choices():
|
||||||
|
site_choices = Site.objects.all()
|
||||||
|
return [(s.slug, s.name) for s in site_choices]
|
||||||
|
|
||||||
|
|
||||||
|
class ProviderFilterForm(forms.Form, BootstrapMixin):
|
||||||
|
site = forms.MultipleChoiceField(required=False, choices=provider_site_choices,
|
||||||
|
widget=forms.SelectMultiple(attrs={'size': 8}))
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Circuit types
|
# Circuit types
|
||||||
#
|
#
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.7 on 2016-07-13 19:24
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import dcim.fields
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('circuits', '0002_auto_20160622_1821'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='provider',
|
||||||
|
name='asn',
|
||||||
|
field=dcim.fields.ASNField(blank=True, null=True, verbose_name=b'ASN'),
|
||||||
|
),
|
||||||
|
]
|
@ -1,6 +1,7 @@
|
|||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
from dcim.fields import ASNField
|
||||||
from dcim.models import Site, Interface
|
from dcim.models import Site, Interface
|
||||||
from utilities.models import CreatedUpdatedModel
|
from utilities.models import CreatedUpdatedModel
|
||||||
|
|
||||||
@ -12,7 +13,7 @@ class Provider(CreatedUpdatedModel):
|
|||||||
"""
|
"""
|
||||||
name = models.CharField(max_length=50, unique=True)
|
name = models.CharField(max_length=50, unique=True)
|
||||||
slug = models.SlugField(unique=True)
|
slug = models.SlugField(unique=True)
|
||||||
asn = models.PositiveIntegerField(blank=True, null=True, verbose_name='ASN')
|
asn = ASNField(blank=True, null=True, verbose_name='ASN')
|
||||||
account = models.CharField(max_length=30, blank=True, verbose_name='Account number')
|
account = models.CharField(max_length=30, blank=True, verbose_name='Account number')
|
||||||
portal_url = models.URLField(blank=True, verbose_name='Portal')
|
portal_url = models.URLField(blank=True, verbose_name='Portal')
|
||||||
noc_contact = models.TextField(blank=True, verbose_name='NOC contact')
|
noc_contact = models.TextField(blank=True, verbose_name='NOC contact')
|
||||||
|
@ -16,6 +16,8 @@ from .models import Circuit, CircuitType, Provider
|
|||||||
|
|
||||||
class ProviderListView(ObjectListView):
|
class ProviderListView(ObjectListView):
|
||||||
queryset = Provider.objects.annotate(count_circuits=Count('circuits'))
|
queryset = Provider.objects.annotate(count_circuits=Count('circuits'))
|
||||||
|
filter = filters.ProviderFilter
|
||||||
|
filter_form = forms.ProviderFilterForm
|
||||||
table = tables.ProviderTable
|
table = tables.ProviderTable
|
||||||
edit_permissions = ['circuits.change_provider', 'circuits.delete_provider']
|
edit_permissions = ['circuits.change_provider', 'circuits.delete_provider']
|
||||||
template_name = 'circuits/provider_list.html'
|
template_name = 'circuits/provider_list.html'
|
||||||
|
@ -1,11 +1,20 @@
|
|||||||
from netaddr import EUI, mac_unix_expanded
|
from netaddr import EUI, mac_unix_expanded
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
from django.core.validators import MinValueValidator, MaxValueValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from .formfields import MACAddressFormField
|
from .formfields import MACAddressFormField
|
||||||
|
|
||||||
|
|
||||||
|
class ASNField(models.BigIntegerField):
|
||||||
|
description = "32-bit ASN field"
|
||||||
|
default_validators = [
|
||||||
|
MinValueValidator(1),
|
||||||
|
MaxValueValidator(4294967295),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class mac_unix_expanded_uppercase(mac_unix_expanded):
|
class mac_unix_expanded_uppercase(mac_unix_expanded):
|
||||||
word_fmt = '%.2X'
|
word_fmt = '%.2X'
|
||||||
|
|
||||||
|
@ -122,6 +122,11 @@ class DeviceFilter(django_filters.FilterSet):
|
|||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
label='Site name (slug)',
|
label='Site name (slug)',
|
||||||
)
|
)
|
||||||
|
rack_group_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
|
name='rack__group',
|
||||||
|
queryset=RackGroup.objects.all(),
|
||||||
|
label='Rack group (ID)',
|
||||||
|
)
|
||||||
rack_id = django_filters.ModelMultipleChoiceFilter(
|
rack_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
name='rack',
|
name='rack',
|
||||||
queryset=Rack.objects.all(),
|
queryset=Rack.objects.all(),
|
||||||
|
@ -186,7 +186,7 @@ def rack_group_choices():
|
|||||||
class RackFilterForm(forms.Form, BootstrapMixin):
|
class RackFilterForm(forms.Form, BootstrapMixin):
|
||||||
site = forms.MultipleChoiceField(required=False, choices=rack_site_choices,
|
site = forms.MultipleChoiceField(required=False, choices=rack_site_choices,
|
||||||
widget=forms.SelectMultiple(attrs={'size': 8}))
|
widget=forms.SelectMultiple(attrs={'size': 8}))
|
||||||
group_id = forms.MultipleChoiceField(required=False, choices=rack_group_choices,
|
group_id = forms.MultipleChoiceField(required=False, choices=rack_group_choices, label='Rack Group',
|
||||||
widget=forms.SelectMultiple(attrs={'size': 8}))
|
widget=forms.SelectMultiple(attrs={'size': 8}))
|
||||||
|
|
||||||
|
|
||||||
@ -502,6 +502,11 @@ def device_site_choices():
|
|||||||
return [(s.slug, '{} ({})'.format(s.name, s.device_count)) for s in site_choices]
|
return [(s.slug, '{} ({})'.format(s.name, s.device_count)) for s in site_choices]
|
||||||
|
|
||||||
|
|
||||||
|
def device_rack_group_choices():
|
||||||
|
group_choices = RackGroup.objects.select_related('site').annotate(device_count=Count('racks__devices'))
|
||||||
|
return [(g.pk, '{} ({})'.format(g, g.device_count)) for g in group_choices]
|
||||||
|
|
||||||
|
|
||||||
def device_role_choices():
|
def device_role_choices():
|
||||||
role_choices = DeviceRole.objects.annotate(device_count=Count('devices'))
|
role_choices = DeviceRole.objects.annotate(device_count=Count('devices'))
|
||||||
return [(r.slug, '{} ({})'.format(r.name, r.device_count)) for r in role_choices]
|
return [(r.slug, '{} ({})'.format(r.name, r.device_count)) for r in role_choices]
|
||||||
@ -520,6 +525,8 @@ def device_platform_choices():
|
|||||||
class DeviceFilterForm(forms.Form, BootstrapMixin):
|
class DeviceFilterForm(forms.Form, BootstrapMixin):
|
||||||
site = forms.MultipleChoiceField(required=False, choices=device_site_choices,
|
site = forms.MultipleChoiceField(required=False, choices=device_site_choices,
|
||||||
widget=forms.SelectMultiple(attrs={'size': 8}))
|
widget=forms.SelectMultiple(attrs={'size': 8}))
|
||||||
|
rack_group_id = forms.MultipleChoiceField(required=False, choices=device_rack_group_choices, label='Rack Group',
|
||||||
|
widget=forms.SelectMultiple(attrs={'size': 8}))
|
||||||
role = forms.MultipleChoiceField(required=False, choices=device_role_choices,
|
role = forms.MultipleChoiceField(required=False, choices=device_role_choices,
|
||||||
widget=forms.SelectMultiple(attrs={'size': 8}))
|
widget=forms.SelectMultiple(attrs={'size': 8}))
|
||||||
device_type_id = forms.MultipleChoiceField(required=False, choices=device_type_choices, label='Type',
|
device_type_id = forms.MultipleChoiceField(required=False, choices=device_type_choices, label='Type',
|
||||||
|
21
netbox/dcim/migrations/0009_site_32bit_asn_support.py
Normal file
21
netbox/dcim/migrations/0009_site_32bit_asn_support.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.7 on 2016-07-13 19:24
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import dcim.fields
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('dcim', '0008_device_remove_primary_ip'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='site',
|
||||||
|
name='asn',
|
||||||
|
field=dcim.fields.ASNField(blank=True, null=True, verbose_name=b'ASN'),
|
||||||
|
),
|
||||||
|
]
|
@ -11,7 +11,7 @@ from extras.rpc import RPC_CLIENTS
|
|||||||
from utilities.fields import NullableCharField
|
from utilities.fields import NullableCharField
|
||||||
from utilities.models import CreatedUpdatedModel
|
from utilities.models import CreatedUpdatedModel
|
||||||
|
|
||||||
from .fields import MACAddressField
|
from .fields import ASNField, MACAddressField
|
||||||
|
|
||||||
RACK_FACE_FRONT = 0
|
RACK_FACE_FRONT = 0
|
||||||
RACK_FACE_REAR = 1
|
RACK_FACE_REAR = 1
|
||||||
@ -145,7 +145,7 @@ class Site(CreatedUpdatedModel):
|
|||||||
name = models.CharField(max_length=50, unique=True)
|
name = models.CharField(max_length=50, unique=True)
|
||||||
slug = models.SlugField(unique=True)
|
slug = models.SlugField(unique=True)
|
||||||
facility = models.CharField(max_length=50, blank=True)
|
facility = models.CharField(max_length=50, blank=True)
|
||||||
asn = models.PositiveIntegerField(blank=True, null=True, verbose_name='ASN')
|
asn = ASNField(blank=True, null=True, verbose_name='ASN')
|
||||||
physical_address = models.CharField(max_length=200, blank=True)
|
physical_address = models.CharField(max_length=200, blank=True)
|
||||||
shipping_address = models.CharField(max_length=200, blank=True)
|
shipping_address = models.CharField(max_length=200, blank=True)
|
||||||
comments = models.TextField(blank=True)
|
comments = models.TextField(blank=True)
|
||||||
|
@ -273,7 +273,10 @@ def devicetype(request, pk):
|
|||||||
poweroutlet_table = tables.PowerOutletTemplateTable(
|
poweroutlet_table = tables.PowerOutletTemplateTable(
|
||||||
natsorted(PowerOutletTemplate.objects.filter(device_type=devicetype), key=attrgetter('name'))
|
natsorted(PowerOutletTemplate.objects.filter(device_type=devicetype), key=attrgetter('name'))
|
||||||
)
|
)
|
||||||
interface_table = tables.InterfaceTemplateTable(InterfaceTemplate.objects.filter(device_type=devicetype))
|
mgmt_interface_table = tables.InterfaceTemplateTable(InterfaceTemplate.objects.filter(device_type=devicetype,
|
||||||
|
mgmt_only=True))
|
||||||
|
interface_table = tables.InterfaceTemplateTable(InterfaceTemplate.objects.filter(device_type=devicetype,
|
||||||
|
mgmt_only=False))
|
||||||
devicebay_table = tables.DeviceBayTemplateTable(
|
devicebay_table = tables.DeviceBayTemplateTable(
|
||||||
natsorted(DeviceBayTemplate.objects.filter(device_type=devicetype), key=attrgetter('name'))
|
natsorted(DeviceBayTemplate.objects.filter(device_type=devicetype), key=attrgetter('name'))
|
||||||
)
|
)
|
||||||
@ -282,6 +285,7 @@ def devicetype(request, pk):
|
|||||||
consoleserverport_table.base_columns['pk'].visible = True
|
consoleserverport_table.base_columns['pk'].visible = True
|
||||||
powerport_table.base_columns['pk'].visible = True
|
powerport_table.base_columns['pk'].visible = True
|
||||||
poweroutlet_table.base_columns['pk'].visible = True
|
poweroutlet_table.base_columns['pk'].visible = True
|
||||||
|
mgmt_interface_table.base_columns['pk'].visible = True
|
||||||
interface_table.base_columns['pk'].visible = True
|
interface_table.base_columns['pk'].visible = True
|
||||||
devicebay_table.base_columns['pk'].visible = True
|
devicebay_table.base_columns['pk'].visible = True
|
||||||
|
|
||||||
@ -291,6 +295,7 @@ def devicetype(request, pk):
|
|||||||
'consoleserverport_table': consoleserverport_table,
|
'consoleserverport_table': consoleserverport_table,
|
||||||
'powerport_table': powerport_table,
|
'powerport_table': powerport_table,
|
||||||
'poweroutlet_table': poweroutlet_table,
|
'poweroutlet_table': poweroutlet_table,
|
||||||
|
'mgmt_interface_table': mgmt_interface_table,
|
||||||
'interface_table': interface_table,
|
'interface_table': interface_table,
|
||||||
'devicebay_table': devicebay_table,
|
'devicebay_table': devicebay_table,
|
||||||
})
|
})
|
||||||
@ -348,7 +353,7 @@ class ComponentTemplateCreateView(View):
|
|||||||
return render(request, 'dcim/component_template_add.html', {
|
return render(request, 'dcim/component_template_add.html', {
|
||||||
'devicetype': devicetype,
|
'devicetype': devicetype,
|
||||||
'component_type': self.model._meta.verbose_name,
|
'component_type': self.model._meta.verbose_name,
|
||||||
'form': self.form(),
|
'form': self.form(initial=request.GET),
|
||||||
'cancel_url': reverse('dcim:devicetype', kwargs={'pk': devicetype.pk}),
|
'cancel_url': reverse('dcim:devicetype', kwargs={'pk': devicetype.pk}),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ except ImportError:
|
|||||||
"the documentation.")
|
"the documentation.")
|
||||||
|
|
||||||
|
|
||||||
VERSION = '1.2.1'
|
VERSION = '1.2.2'
|
||||||
|
|
||||||
# Import local configuration
|
# Import local configuration
|
||||||
for setting in ['ALLOWED_HOSTS', 'DATABASE', 'SECRET_KEY']:
|
for setting in ['ALLOWED_HOSTS', 'DATABASE', 'SECRET_KEY']:
|
||||||
@ -138,7 +138,6 @@ TEMPLATES = [
|
|||||||
'django.contrib.auth.context_processors.auth',
|
'django.contrib.auth.context_processors.auth',
|
||||||
'django.contrib.messages.context_processors.messages',
|
'django.contrib.messages.context_processors.messages',
|
||||||
'utilities.context_processors.settings',
|
'utilities.context_processors.settings',
|
||||||
'django.core.context_processors.request',
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
html {
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
html, body {
|
html, body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
||||||
// "Select all" checkbox in a table header
|
// "Select all" checkbox in a table header
|
||||||
$('th input:checkbox').click(function (event) {
|
$('th input:checkbox[name=_all]').click(function (event) {
|
||||||
$(this).parents('table').find('td input:checkbox').prop('checked', $(this).prop('checked'));
|
$(this).parents('table').find('td input:checkbox').prop('checked', $(this).prop('checked'));
|
||||||
});
|
});
|
||||||
|
// Uncheck the "select all" checkbox if an item is unchecked
|
||||||
|
$('input:checkbox[name=pk]').click(function (event) {
|
||||||
|
if (!$(this).attr('checked')) {
|
||||||
|
$(this).parents('table').find('input:checkbox[name=_all]').prop('checked', false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Slugify
|
// Slugify
|
||||||
function slugify(s, num_chars) {
|
function slugify(s, num_chars) {
|
||||||
|
@ -14,8 +14,28 @@
|
|||||||
</div>
|
</div>
|
||||||
<h1>Providers</h1>
|
<h1>Providers</h1>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-9">
|
||||||
{% include 'utilities/obj_table.html' with bulk_edit_url='circuits:provider_bulk_edit' bulk_delete_url='circuits:provider_bulk_delete' %}
|
{% include 'utilities/obj_table.html' with bulk_edit_url='circuits:provider_bulk_edit' bulk_delete_url='circuits:provider_bulk_delete' %}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<strong>Search</strong>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<form action="{% url 'circuits:provider_list' %}" method="get">
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" name="q" class="form-control" placeholder="Name" {% if request.GET.q %}value="{{ request.GET.q }}" {% endif %}/>
|
||||||
|
<span class="input-group-btn">
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% include 'inc/filter_panel.html' %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
|
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
|
||||||
<strong>Search</strong>
|
<strong>Search</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
<table class="table table-hover panel-body">
|
<table class="table table-hover panel-body">
|
||||||
<tr>
|
<tr>
|
||||||
<td>Manufacturer</td>
|
<td>Manufacturer</td>
|
||||||
<td>{{ devicetype.manufacturer }}</td>
|
<td><a href="{% url 'dcim:devicetype_list' %}?manufacturer={{ devicetype.manufacturer.slug }}">{{ devicetype.manufacturer }}</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Model Name</td>
|
<td>Model Name</td>
|
||||||
@ -54,7 +54,13 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Full Depth</td>
|
<td>Full Depth</td>
|
||||||
<td>{{ devicetype.is_full_depth|yesno|capfirst }}</td>
|
<td>
|
||||||
|
{% if devicetype.is_full_depth %}
|
||||||
|
<i class="glyphicon glyphicon-ok text-success" title="Yes"></i>
|
||||||
|
{% else %}
|
||||||
|
<i class="glyphicon glyphicon-remove text-danger" title="No"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
@ -64,21 +70,70 @@
|
|||||||
</div>
|
</div>
|
||||||
<table class="table table-hover panel-body">
|
<table class="table table-hover panel-body">
|
||||||
<tr>
|
<tr>
|
||||||
<td>Is a Console Server</td>
|
<td class="text-right">
|
||||||
<td>{{ devicetype.is_console_server|yesno|capfirst }}</td>
|
{% if devicetype.is_console_server %}
|
||||||
|
<i class="glyphicon glyphicon-ok text-success" title="Yes"></i>
|
||||||
|
{% else %}
|
||||||
|
<i class="glyphicon glyphicon-remove text-danger" title="No"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong>Console Server</strong><br />
|
||||||
|
<small class="text-muted">This device {% if devicetype.is_console_server %}has{% else %}does not have{% endif %} console server ports</small>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Is a PDU</td>
|
<td class="text-right">
|
||||||
<td>{{ devicetype.is_pdu|yesno|capfirst }}</td>
|
{% if devicetype.is_pdu %}
|
||||||
|
<i class="glyphicon glyphicon-ok text-success" title="Yes"></i>
|
||||||
|
{% else %}
|
||||||
|
<i class="glyphicon glyphicon-remove text-danger" title="No"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong>PDU</strong><br />
|
||||||
|
<small class="text-muted">This device {% if devicetype.is_pdu %}has{% else %}does not have{% endif %} power outlets</small>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Is a Network Device</td>
|
<td class="text-right">
|
||||||
<td>{{ devicetype.is_network_device|yesno|capfirst }}</td>
|
{% if devicetype.is_network_device %}
|
||||||
|
<i class="glyphicon glyphicon-ok text-success" title="Yes"></i>
|
||||||
|
{% else %}
|
||||||
|
<i class="glyphicon glyphicon-remove text-danger" title="No"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong>Network Device</strong><br />
|
||||||
|
<small class="text-muted">This device {% if devicetype.is_network_device %}has{% else %}does not have{% endif %} non-management network interfaces</small>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="text-right">
|
||||||
|
{% if devicetype.subdevice_role == True %}
|
||||||
|
<label class="label label-primary">Parent</label>
|
||||||
|
{% elif devicetype.subdevice_role == False %}
|
||||||
|
<label class="label label-info">Child</label>
|
||||||
|
{% else %}
|
||||||
|
<label class="label label-default">None</label>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong>Parent/Child</strong><br />
|
||||||
|
{% if devicetype.subdevice_role == True %}
|
||||||
|
<small class="text-muted">This device has device bays for mounting child devices</small>
|
||||||
|
{% elif devicetype.subdevice_role == False %}
|
||||||
|
<small class="text-muted">This device can only be mounted in a parent device</small>
|
||||||
|
{% else %}
|
||||||
|
<small class="text-muted">This device does not have device bays</small>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{% include 'dcim/inc/devicetype_component_table.html' with table=consoleport_table title='Console Ports' add_url='dcim:devicetype_add_consoleport' delete_url='dcim:devicetype_delete_consoleport' %}
|
{% include 'dcim/inc/devicetype_component_table.html' with table=consoleport_table title='Console Ports' add_url='dcim:devicetype_add_consoleport' delete_url='dcim:devicetype_delete_consoleport' %}
|
||||||
{% include 'dcim/inc/devicetype_component_table.html' with table=powerport_table title='Power Ports' add_url='dcim:devicetype_add_powerport' delete_url='dcim:devicetype_delete_powerport' %}
|
{% include 'dcim/inc/devicetype_component_table.html' with table=powerport_table title='Power Ports' add_url='dcim:devicetype_add_powerport' delete_url='dcim:devicetype_delete_powerport' %}
|
||||||
|
{% include 'dcim/inc/devicetype_component_table.html' with table=mgmt_interface_table title='Management Interfaces' add_url='dcim:devicetype_add_interface' add_url_extra='?mgmt_only=1' delete_url='dcim:devicetype_delete_interface' %}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
{% if devicetype.is_parent_device %}
|
{% if devicetype.is_parent_device %}
|
||||||
|
@ -4,7 +4,10 @@
|
|||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<a href="{% url add_url pk=devicetype.pk %}" class="btn btn-primary btn-xs pull-right"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add {{ title }}</a>
|
<a href="{% url add_url pk=devicetype.pk %}{{ add_url_extra }}" class="btn btn-primary btn-xs pull-right">
|
||||||
|
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
|
||||||
|
Add {{ title }}
|
||||||
|
</a>
|
||||||
<strong>{{ title }}</strong>
|
<strong>{{ title }}</strong>
|
||||||
</div>
|
</div>
|
||||||
{% render_table table 'table.html' %}
|
{% render_table table 'table.html' %}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
|
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
|
||||||
<strong>Search</strong>
|
<strong>Search</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
|
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
|
||||||
<strong>Search</strong>
|
<strong>Search</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
|
<span class="glyphicon glyphicon-filter" aria-hidden="true"></span>
|
||||||
<strong>Filter</strong>
|
<strong>Filter</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
|
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
|
||||||
<strong>Search</strong>
|
<strong>Search</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
|
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
|
||||||
<strong>Search</strong>
|
<strong>Search</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
|
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
|
||||||
<strong>Search by ID</strong>
|
<strong>Search by ID</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
Loading…
Reference in New Issue
Block a user