mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-21 19:47:20 -06:00
commit
88239e0b0d
@ -1,12 +1,11 @@
|
|||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
**Debian/Ubuntu**
|
**Ubuntu**
|
||||||
|
|
||||||
Python 3:
|
Python 3:
|
||||||
|
|
||||||
```no-highlight
|
```no-highlight
|
||||||
# apt-get install -y python3 python3-dev python3-pip libxml2-dev libxslt1-dev libffi-dev graphviz libpq-dev libssl-dev zlib1g-dev
|
# apt-get install -y python3 python3-dev python3-pip libxml2-dev libxslt1-dev libffi-dev graphviz libpq-dev libssl-dev zlib1g-dev
|
||||||
# update-alternatives --install /usr/bin/python python /usr/bin/python3 1
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Python 2:
|
Python 2:
|
||||||
@ -15,7 +14,7 @@ Python 2:
|
|||||||
# apt-get install -y python2.7 python-dev python-pip libxml2-dev libxslt1-dev libffi-dev graphviz libpq-dev libssl-dev zlib1g-dev
|
# apt-get install -y python2.7 python-dev python-pip libxml2-dev libxslt1-dev libffi-dev graphviz libpq-dev libssl-dev zlib1g-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
**CentOS/RHEL**
|
**CentOS**
|
||||||
|
|
||||||
Python 3:
|
Python 3:
|
||||||
|
|
||||||
@ -57,13 +56,13 @@ Create the base directory for the NetBox installation. For this guide, we'll use
|
|||||||
|
|
||||||
If `git` is not already installed, install it:
|
If `git` is not already installed, install it:
|
||||||
|
|
||||||
**Debian/Ubuntu**
|
**Ubuntu**
|
||||||
|
|
||||||
```no-highlight
|
```no-highlight
|
||||||
# apt-get install -y git
|
# apt-get install -y git
|
||||||
```
|
```
|
||||||
|
|
||||||
**CentOS/RHEL**
|
**CentOS**
|
||||||
|
|
||||||
```no-highlight
|
```no-highlight
|
||||||
# yum install -y git
|
# yum install -y git
|
||||||
@ -150,11 +149,14 @@ You may use the script located at `netbox/generate_secret_key.py` to generate a
|
|||||||
|
|
||||||
# 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):
|
!!! warning
|
||||||
|
The examples on the rest of this page call the `python` executable, which will be Python2 on most systems. Replace this with `python3` if you're running NetBox on Python3.
|
||||||
|
|
||||||
|
Before NetBox can run, we need to install the database schema. This is done by running `python manage.py migrate` from the `netbox` directory (`/opt/netbox/netbox/` in our example):
|
||||||
|
|
||||||
```no-highlight
|
```no-highlight
|
||||||
# cd /opt/netbox/netbox/
|
# cd /opt/netbox/netbox/
|
||||||
# ./manage.py migrate
|
# python manage.py migrate
|
||||||
Operations to perform:
|
Operations to perform:
|
||||||
Apply all migrations: dcim, sessions, admin, ipam, utilities, auth, circuits, contenttypes, extras, secrets, users
|
Apply all migrations: dcim, sessions, admin, ipam, utilities, auth, circuits, contenttypes, extras, secrets, users
|
||||||
Running migrations:
|
Running migrations:
|
||||||
@ -172,7 +174,7 @@ If this step results in a PostgreSQL authentication error, ensure that the usern
|
|||||||
NetBox does not come with any predefined user accounts. You'll need to create a super user to be able to log into NetBox:
|
NetBox does not come with any predefined user accounts. You'll need to create a super user to be able to log into NetBox:
|
||||||
|
|
||||||
```no-highlight
|
```no-highlight
|
||||||
# ./manage.py createsuperuser
|
# python manage.py createsuperuser
|
||||||
Username: admin
|
Username: admin
|
||||||
Email address: admin@example.com
|
Email address: admin@example.com
|
||||||
Password:
|
Password:
|
||||||
@ -183,7 +185,7 @@ Superuser created successfully.
|
|||||||
# Collect Static Files
|
# Collect Static Files
|
||||||
|
|
||||||
```no-highlight
|
```no-highlight
|
||||||
# ./manage.py collectstatic --no-input
|
# python manage.py collectstatic --no-input
|
||||||
|
|
||||||
You have requested to collect static files at the destination
|
You have requested to collect static files at the destination
|
||||||
location as specified in your settings:
|
location as specified in your settings:
|
||||||
@ -204,7 +206,7 @@ NetBox ships with some initial data to help you get started: RIR definitions, co
|
|||||||
This step is optional. It's perfectly fine to start using NetBox without using this initial data if you'd rather create everything from scratch.
|
This step is optional. It's perfectly fine to start using NetBox without using this initial data if you'd rather create everything from scratch.
|
||||||
|
|
||||||
```no-highlight
|
```no-highlight
|
||||||
# ./manage.py loaddata initial_data
|
# python manage.py loaddata initial_data
|
||||||
Installed 43 object(s) from 4 fixture(s)
|
Installed 43 object(s) from 4 fixture(s)
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -213,7 +215,7 @@ Installed 43 object(s) from 4 fixture(s)
|
|||||||
At this point, NetBox should be able to run. We can verify this by starting a development instance:
|
At this point, NetBox should be able to run. We can verify this by starting a development instance:
|
||||||
|
|
||||||
```no-highlight
|
```no-highlight
|
||||||
# ./manage.py runserver 0.0.0.0:8000 --insecure
|
# python manage.py runserver 0.0.0.0:8000 --insecure
|
||||||
Performing system checks...
|
Performing system checks...
|
||||||
|
|
||||||
System check identified no issues (0 silenced).
|
System check identified no issues (0 silenced).
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
NetBox requires a PostgreSQL database to store data. (Please note that MySQL is not supported, as NetBox leverages PostgreSQL's built-in [network address types](https://www.postgresql.org/docs/9.1/static/datatype-net-types.html).)
|
NetBox requires a PostgreSQL database to store data. (Please note that MySQL is not supported, as NetBox leverages PostgreSQL's built-in [network address types](https://www.postgresql.org/docs/9.1/static/datatype-net-types.html).)
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
The installation instructions provided here have been tested to work on Ubuntu 16.04 and CentOS 6.9. The particular commands needed to install dependencies on other distributions may vary significantly. Unfortunately, this is outside the control of the NetBox maintainers. Please consult your distribution's documentation for assistance with any errors.
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
**Debian/Ubuntu**
|
**Ubuntu**
|
||||||
|
|
||||||
```no-highlight
|
```no-highlight
|
||||||
# apt-get update
|
# apt-get update
|
||||||
# apt-get install -y postgresql libpq-dev
|
# apt-get install -y postgresql libpq-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
**CentOS/RHEL**
|
**CentOS**
|
||||||
|
|
||||||
```no-highlight
|
```no-highlight
|
||||||
# yum install -y postgresql postgresql-server postgresql-devel
|
# yum install -y postgresql postgresql-server postgresql-devel
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
We'll set up a simple WSGI front end using [gunicorn](http://gunicorn.org/) for the purposes of this guide. For web servers, we provide example configurations for both [nginx](https://www.nginx.com/resources/wiki/) and [Apache](http://httpd.apache.org/docs/2.4). (You are of course free to use whichever combination of HTTP and WSGI services you'd like.) We'll also use [supervisord](http://supervisord.org/) to enable service persistence.
|
We'll set up a simple WSGI front end using [gunicorn](http://gunicorn.org/) for the purposes of this guide. For web servers, we provide example configurations for both [nginx](https://www.nginx.com/resources/wiki/) and [Apache](http://httpd.apache.org/docs/2.4). (You are of course free to use whichever combination of HTTP and WSGI services you'd like.) We'll also use [supervisord](http://supervisord.org/) to enable service persistence.
|
||||||
|
|
||||||
!!! info
|
!!! info
|
||||||
Only Debian/Ubuntu instructions are provided here, but the installation process for CentOS/RHEL does not differ much. Please consult the documentation for those distributions for details.
|
For the sake of brevity, only Ubuntu 16.04 instructions are provided here, but this sort of web server and WSGI configuration is not unique to NetBox. Please consult your distribution's documentation for assistance if needed.
|
||||||
|
|
||||||
```no-highlight
|
```no-highlight
|
||||||
# apt-get install -y gunicorn supervisor
|
# apt-get install -y gunicorn supervisor
|
||||||
|
@ -220,7 +220,7 @@ class CircuitTerminationForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelForm
|
|||||||
label='Interface',
|
label='Interface',
|
||||||
widget=APISelect(
|
widget=APISelect(
|
||||||
api_url='/api/dcim/interfaces/?device_id={{device}}&type=physical',
|
api_url='/api/dcim/interfaces/?device_id={{device}}&type=physical',
|
||||||
disabled_indicator='is_connected'
|
disabled_indicator='connection'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ urlpatterns = [
|
|||||||
|
|
||||||
# Providers
|
# Providers
|
||||||
url(r'^providers/$', views.ProviderListView.as_view(), name='provider_list'),
|
url(r'^providers/$', views.ProviderListView.as_view(), name='provider_list'),
|
||||||
url(r'^providers/add/$', views.ProviderEditView.as_view(), name='provider_add'),
|
url(r'^providers/add/$', views.ProviderCreateView.as_view(), name='provider_add'),
|
||||||
url(r'^providers/import/$', views.ProviderBulkImportView.as_view(), name='provider_import'),
|
url(r'^providers/import/$', views.ProviderBulkImportView.as_view(), name='provider_import'),
|
||||||
url(r'^providers/edit/$', views.ProviderBulkEditView.as_view(), name='provider_bulk_edit'),
|
url(r'^providers/edit/$', views.ProviderBulkEditView.as_view(), name='provider_bulk_edit'),
|
||||||
url(r'^providers/delete/$', views.ProviderBulkDeleteView.as_view(), name='provider_bulk_delete'),
|
url(r'^providers/delete/$', views.ProviderBulkDeleteView.as_view(), name='provider_bulk_delete'),
|
||||||
@ -20,13 +20,13 @@ urlpatterns = [
|
|||||||
|
|
||||||
# Circuit types
|
# Circuit types
|
||||||
url(r'^circuit-types/$', views.CircuitTypeListView.as_view(), name='circuittype_list'),
|
url(r'^circuit-types/$', views.CircuitTypeListView.as_view(), name='circuittype_list'),
|
||||||
url(r'^circuit-types/add/$', views.CircuitTypeEditView.as_view(), name='circuittype_add'),
|
url(r'^circuit-types/add/$', views.CircuitTypeCreateView.as_view(), name='circuittype_add'),
|
||||||
url(r'^circuit-types/delete/$', views.CircuitTypeBulkDeleteView.as_view(), name='circuittype_bulk_delete'),
|
url(r'^circuit-types/delete/$', views.CircuitTypeBulkDeleteView.as_view(), name='circuittype_bulk_delete'),
|
||||||
url(r'^circuit-types/(?P<slug>[\w-]+)/edit/$', views.CircuitTypeEditView.as_view(), name='circuittype_edit'),
|
url(r'^circuit-types/(?P<slug>[\w-]+)/edit/$', views.CircuitTypeEditView.as_view(), name='circuittype_edit'),
|
||||||
|
|
||||||
# Circuits
|
# Circuits
|
||||||
url(r'^circuits/$', views.CircuitListView.as_view(), name='circuit_list'),
|
url(r'^circuits/$', views.CircuitListView.as_view(), name='circuit_list'),
|
||||||
url(r'^circuits/add/$', views.CircuitEditView.as_view(), name='circuit_add'),
|
url(r'^circuits/add/$', views.CircuitCreateView.as_view(), name='circuit_add'),
|
||||||
url(r'^circuits/import/$', views.CircuitBulkImportView.as_view(), name='circuit_import'),
|
url(r'^circuits/import/$', views.CircuitBulkImportView.as_view(), name='circuit_import'),
|
||||||
url(r'^circuits/edit/$', views.CircuitBulkEditView.as_view(), name='circuit_bulk_edit'),
|
url(r'^circuits/edit/$', views.CircuitBulkEditView.as_view(), name='circuit_bulk_edit'),
|
||||||
url(r'^circuits/delete/$', views.CircuitBulkDeleteView.as_view(), name='circuit_bulk_delete'),
|
url(r'^circuits/delete/$', views.CircuitBulkDeleteView.as_view(), name='circuit_bulk_delete'),
|
||||||
@ -36,7 +36,7 @@ urlpatterns = [
|
|||||||
url(r'^circuits/(?P<pk>\d+)/terminations/swap/$', views.circuit_terminations_swap, name='circuit_terminations_swap'),
|
url(r'^circuits/(?P<pk>\d+)/terminations/swap/$', views.circuit_terminations_swap, name='circuit_terminations_swap'),
|
||||||
|
|
||||||
# Circuit terminations
|
# Circuit terminations
|
||||||
url(r'^circuits/(?P<circuit>\d+)/terminations/add/$', views.CircuitTerminationEditView.as_view(), name='circuittermination_add'),
|
url(r'^circuits/(?P<circuit>\d+)/terminations/add/$', views.CircuitTerminationCreateView.as_view(), name='circuittermination_add'),
|
||||||
url(r'^circuit-terminations/(?P<pk>\d+)/edit/$', views.CircuitTerminationEditView.as_view(), name='circuittermination_edit'),
|
url(r'^circuit-terminations/(?P<pk>\d+)/edit/$', views.CircuitTerminationEditView.as_view(), name='circuittermination_edit'),
|
||||||
url(r'^circuit-terminations/(?P<pk>\d+)/delete/$', views.CircuitTerminationDeleteView.as_view(), name='circuittermination_delete'),
|
url(r'^circuit-terminations/(?P<pk>\d+)/delete/$', views.CircuitTerminationDeleteView.as_view(), name='circuittermination_delete'),
|
||||||
|
|
||||||
|
@ -49,14 +49,18 @@ class ProviderView(View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class ProviderEditView(PermissionRequiredMixin, ObjectEditView):
|
class ProviderCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'circuits.change_provider'
|
permission_required = 'circuits.add_provider'
|
||||||
model = Provider
|
model = Provider
|
||||||
form_class = forms.ProviderForm
|
form_class = forms.ProviderForm
|
||||||
template_name = 'circuits/provider_edit.html'
|
template_name = 'circuits/provider_edit.html'
|
||||||
default_return_url = 'circuits:provider_list'
|
default_return_url = 'circuits:provider_list'
|
||||||
|
|
||||||
|
|
||||||
|
class ProviderEditView(ProviderCreateView):
|
||||||
|
permission_required = 'circuits.change_provider'
|
||||||
|
|
||||||
|
|
||||||
class ProviderDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
class ProviderDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||||
permission_required = 'circuits.delete_provider'
|
permission_required = 'circuits.delete_provider'
|
||||||
model = Provider
|
model = Provider
|
||||||
@ -96,8 +100,8 @@ class CircuitTypeListView(ObjectListView):
|
|||||||
template_name = 'circuits/circuittype_list.html'
|
template_name = 'circuits/circuittype_list.html'
|
||||||
|
|
||||||
|
|
||||||
class CircuitTypeEditView(PermissionRequiredMixin, ObjectEditView):
|
class CircuitTypeCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'circuits.change_circuittype'
|
permission_required = 'circuits.add_circuittype'
|
||||||
model = CircuitType
|
model = CircuitType
|
||||||
form_class = forms.CircuitTypeForm
|
form_class = forms.CircuitTypeForm
|
||||||
|
|
||||||
@ -105,6 +109,10 @@ class CircuitTypeEditView(PermissionRequiredMixin, ObjectEditView):
|
|||||||
return reverse('circuits:circuittype_list')
|
return reverse('circuits:circuittype_list')
|
||||||
|
|
||||||
|
|
||||||
|
class CircuitTypeEditView(CircuitTypeCreateView):
|
||||||
|
permission_required = 'circuits.change_circuittype'
|
||||||
|
|
||||||
|
|
||||||
class CircuitTypeBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
class CircuitTypeBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||||
permission_required = 'circuits.delete_circuittype'
|
permission_required = 'circuits.delete_circuittype'
|
||||||
cls = CircuitType
|
cls = CircuitType
|
||||||
@ -146,14 +154,18 @@ class CircuitView(View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class CircuitEditView(PermissionRequiredMixin, ObjectEditView):
|
class CircuitCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'circuits.change_circuit'
|
permission_required = 'circuits.add_circuit'
|
||||||
model = Circuit
|
model = Circuit
|
||||||
form_class = forms.CircuitForm
|
form_class = forms.CircuitForm
|
||||||
template_name = 'circuits/circuit_edit.html'
|
template_name = 'circuits/circuit_edit.html'
|
||||||
default_return_url = 'circuits:circuit_list'
|
default_return_url = 'circuits:circuit_list'
|
||||||
|
|
||||||
|
|
||||||
|
class CircuitEditView(CircuitCreateView):
|
||||||
|
permission_required = 'circuits.change_circuit'
|
||||||
|
|
||||||
|
|
||||||
class CircuitDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
class CircuitDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||||
permission_required = 'circuits.delete_circuit'
|
permission_required = 'circuits.delete_circuit'
|
||||||
model = Circuit
|
model = Circuit
|
||||||
@ -232,8 +244,8 @@ def circuit_terminations_swap(request, pk):
|
|||||||
# Circuit terminations
|
# Circuit terminations
|
||||||
#
|
#
|
||||||
|
|
||||||
class CircuitTerminationEditView(PermissionRequiredMixin, ObjectEditView):
|
class CircuitTerminationCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'circuits.change_circuittermination'
|
permission_required = 'circuits.add_circuittermination'
|
||||||
model = CircuitTermination
|
model = CircuitTermination
|
||||||
form_class = forms.CircuitTerminationForm
|
form_class = forms.CircuitTerminationForm
|
||||||
template_name = 'circuits/circuittermination_edit.html'
|
template_name = 'circuits/circuittermination_edit.html'
|
||||||
@ -247,6 +259,10 @@ class CircuitTerminationEditView(PermissionRequiredMixin, ObjectEditView):
|
|||||||
return obj.circuit.get_absolute_url()
|
return obj.circuit.get_absolute_url()
|
||||||
|
|
||||||
|
|
||||||
|
class CircuitTerminationEditView(CircuitTerminationCreateView):
|
||||||
|
permission_required = 'circuits.change_circuittermination'
|
||||||
|
|
||||||
|
|
||||||
class CircuitTerminationDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
class CircuitTerminationDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||||
permission_required = 'circuits.delete_circuittermination'
|
permission_required = 'circuits.delete_circuittermination'
|
||||||
model = CircuitTermination
|
model = CircuitTermination
|
||||||
|
@ -13,8 +13,8 @@ from tenancy.forms import TenancyForm
|
|||||||
from tenancy.models import Tenant
|
from tenancy.models import Tenant
|
||||||
from utilities.forms import (
|
from utilities.forms import (
|
||||||
APISelect, add_blank_choice, ArrayFieldSelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect,
|
APISelect, add_blank_choice, ArrayFieldSelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect,
|
||||||
ChainedFieldsMixin, ChainedModelChoiceField, CommentField, CSVChoiceField, ExpandableNameField, FilterChoiceField,
|
ChainedFieldsMixin, ChainedModelChoiceField, CommentField, ConfirmationForm, CSVChoiceField, ExpandableNameField,
|
||||||
FlexibleModelChoiceField, Livesearch, SelectWithDisabled, SmallTextarea, SlugField,
|
FilterChoiceField, FlexibleModelChoiceField, Livesearch, SelectWithDisabled, SmallTextarea, SlugField,
|
||||||
FilterTreeNodeMultipleChoiceField,
|
FilterTreeNodeMultipleChoiceField,
|
||||||
)
|
)
|
||||||
from .formfields import MACAddressFormField
|
from .formfields import MACAddressFormField
|
||||||
@ -1174,6 +1174,10 @@ class ConsoleServerPortConnectionForm(BootstrapMixin, ChainedFieldsMixin, forms.
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ConsoleServerPortBulkDisconnectForm(ConfirmationForm):
|
||||||
|
pk = forms.ModelMultipleChoiceField(queryset=ConsoleServerPort.objects.all(), widget=forms.MultipleHiddenInput)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Power ports
|
# Power ports
|
||||||
#
|
#
|
||||||
@ -1431,6 +1435,10 @@ class PowerOutletConnectionForm(BootstrapMixin, ChainedFieldsMixin, forms.Form):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PowerOutletBulkDisconnectForm(ConfirmationForm):
|
||||||
|
pk = forms.ModelMultipleChoiceField(queryset=PowerOutlet.objects.all(), widget=forms.MultipleHiddenInput)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Interfaces
|
# Interfaces
|
||||||
#
|
#
|
||||||
@ -1508,6 +1516,10 @@ class InterfaceBulkEditForm(BootstrapMixin, BulkEditForm):
|
|||||||
self.fields['lag'].choices = []
|
self.fields['lag'].choices = []
|
||||||
|
|
||||||
|
|
||||||
|
class InterfaceBulkDisconnectForm(ConfirmationForm):
|
||||||
|
pk = forms.ModelMultipleChoiceField(queryset=Interface.objects.all(), widget=forms.MultipleHiddenInput)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Interface connections
|
# Interface connections
|
||||||
#
|
#
|
||||||
@ -1594,9 +1606,10 @@ class InterfaceConnectionForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelFor
|
|||||||
]
|
]
|
||||||
|
|
||||||
# Mark connected interfaces as disabled
|
# Mark connected interfaces as disabled
|
||||||
self.fields['interface_b'].choices = [
|
if self.data.get('device_b'):
|
||||||
(iface.id, {'label': iface.name, 'disabled': iface.is_connected}) for iface in self.fields['interface_b'].queryset
|
self.fields['interface_b'].choices = [
|
||||||
]
|
(iface.id, {'label': iface.name, 'disabled': iface.is_connected}) for iface in self.fields['interface_b'].queryset
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class InterfaceConnectionCSVForm(forms.ModelForm):
|
class InterfaceConnectionCSVForm(forms.ModelForm):
|
||||||
|
@ -3,7 +3,7 @@ from __future__ import unicode_literals
|
|||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
|
|
||||||
from extras.views import ImageAttachmentEditView
|
from extras.views import ImageAttachmentEditView
|
||||||
from ipam.views import ServiceEditView
|
from ipam.views import ServiceCreateView
|
||||||
from secrets.views import secret_add
|
from secrets.views import secret_add
|
||||||
from .models import Device, Rack, Site
|
from .models import Device, Rack, Site
|
||||||
from . import views
|
from . import views
|
||||||
@ -14,13 +14,13 @@ urlpatterns = [
|
|||||||
|
|
||||||
# Regions
|
# Regions
|
||||||
url(r'^regions/$', views.RegionListView.as_view(), name='region_list'),
|
url(r'^regions/$', views.RegionListView.as_view(), name='region_list'),
|
||||||
url(r'^regions/add/$', views.RegionEditView.as_view(), name='region_add'),
|
url(r'^regions/add/$', views.RegionCreateView.as_view(), name='region_add'),
|
||||||
url(r'^regions/delete/$', views.RegionBulkDeleteView.as_view(), name='region_bulk_delete'),
|
url(r'^regions/delete/$', views.RegionBulkDeleteView.as_view(), name='region_bulk_delete'),
|
||||||
url(r'^regions/(?P<pk>\d+)/edit/$', views.RegionEditView.as_view(), name='region_edit'),
|
url(r'^regions/(?P<pk>\d+)/edit/$', views.RegionEditView.as_view(), name='region_edit'),
|
||||||
|
|
||||||
# Sites
|
# Sites
|
||||||
url(r'^sites/$', views.SiteListView.as_view(), name='site_list'),
|
url(r'^sites/$', views.SiteListView.as_view(), name='site_list'),
|
||||||
url(r'^sites/add/$', views.SiteEditView.as_view(), name='site_add'),
|
url(r'^sites/add/$', views.SiteCreateView.as_view(), name='site_add'),
|
||||||
url(r'^sites/import/$', views.SiteBulkImportView.as_view(), name='site_import'),
|
url(r'^sites/import/$', views.SiteBulkImportView.as_view(), name='site_import'),
|
||||||
url(r'^sites/edit/$', views.SiteBulkEditView.as_view(), name='site_bulk_edit'),
|
url(r'^sites/edit/$', views.SiteBulkEditView.as_view(), name='site_bulk_edit'),
|
||||||
url(r'^sites/(?P<slug>[\w-]+)/$', views.SiteView.as_view(), name='site'),
|
url(r'^sites/(?P<slug>[\w-]+)/$', views.SiteView.as_view(), name='site'),
|
||||||
@ -30,13 +30,13 @@ urlpatterns = [
|
|||||||
|
|
||||||
# Rack groups
|
# Rack groups
|
||||||
url(r'^rack-groups/$', views.RackGroupListView.as_view(), name='rackgroup_list'),
|
url(r'^rack-groups/$', views.RackGroupListView.as_view(), name='rackgroup_list'),
|
||||||
url(r'^rack-groups/add/$', views.RackGroupEditView.as_view(), name='rackgroup_add'),
|
url(r'^rack-groups/add/$', views.RackGroupCreateView.as_view(), name='rackgroup_add'),
|
||||||
url(r'^rack-groups/delete/$', views.RackGroupBulkDeleteView.as_view(), name='rackgroup_bulk_delete'),
|
url(r'^rack-groups/delete/$', views.RackGroupBulkDeleteView.as_view(), name='rackgroup_bulk_delete'),
|
||||||
url(r'^rack-groups/(?P<pk>\d+)/edit/$', views.RackGroupEditView.as_view(), name='rackgroup_edit'),
|
url(r'^rack-groups/(?P<pk>\d+)/edit/$', views.RackGroupEditView.as_view(), name='rackgroup_edit'),
|
||||||
|
|
||||||
# Rack roles
|
# Rack roles
|
||||||
url(r'^rack-roles/$', views.RackRoleListView.as_view(), name='rackrole_list'),
|
url(r'^rack-roles/$', views.RackRoleListView.as_view(), name='rackrole_list'),
|
||||||
url(r'^rack-roles/add/$', views.RackRoleEditView.as_view(), name='rackrole_add'),
|
url(r'^rack-roles/add/$', views.RackRoleCreateView.as_view(), name='rackrole_add'),
|
||||||
url(r'^rack-roles/delete/$', views.RackRoleBulkDeleteView.as_view(), name='rackrole_bulk_delete'),
|
url(r'^rack-roles/delete/$', views.RackRoleBulkDeleteView.as_view(), name='rackrole_bulk_delete'),
|
||||||
url(r'^rack-roles/(?P<pk>\d+)/edit/$', views.RackRoleEditView.as_view(), name='rackrole_edit'),
|
url(r'^rack-roles/(?P<pk>\d+)/edit/$', views.RackRoleEditView.as_view(), name='rackrole_edit'),
|
||||||
|
|
||||||
@ -56,18 +56,18 @@ urlpatterns = [
|
|||||||
url(r'^racks/(?P<pk>\d+)/$', views.RackView.as_view(), name='rack'),
|
url(r'^racks/(?P<pk>\d+)/$', views.RackView.as_view(), name='rack'),
|
||||||
url(r'^racks/(?P<pk>\d+)/edit/$', views.RackEditView.as_view(), name='rack_edit'),
|
url(r'^racks/(?P<pk>\d+)/edit/$', views.RackEditView.as_view(), name='rack_edit'),
|
||||||
url(r'^racks/(?P<pk>\d+)/delete/$', views.RackDeleteView.as_view(), name='rack_delete'),
|
url(r'^racks/(?P<pk>\d+)/delete/$', views.RackDeleteView.as_view(), name='rack_delete'),
|
||||||
url(r'^racks/(?P<rack>\d+)/reservations/add/$', views.RackReservationEditView.as_view(), name='rack_add_reservation'),
|
url(r'^racks/(?P<rack>\d+)/reservations/add/$', views.RackReservationCreateView.as_view(), name='rack_add_reservation'),
|
||||||
url(r'^racks/(?P<object_id>\d+)/images/add/$', ImageAttachmentEditView.as_view(), name='rack_add_image', kwargs={'model': Rack}),
|
url(r'^racks/(?P<object_id>\d+)/images/add/$', ImageAttachmentEditView.as_view(), name='rack_add_image', kwargs={'model': Rack}),
|
||||||
|
|
||||||
# Manufacturers
|
# Manufacturers
|
||||||
url(r'^manufacturers/$', views.ManufacturerListView.as_view(), name='manufacturer_list'),
|
url(r'^manufacturers/$', views.ManufacturerListView.as_view(), name='manufacturer_list'),
|
||||||
url(r'^manufacturers/add/$', views.ManufacturerEditView.as_view(), name='manufacturer_add'),
|
url(r'^manufacturers/add/$', views.ManufacturerCreateView.as_view(), name='manufacturer_add'),
|
||||||
url(r'^manufacturers/delete/$', views.ManufacturerBulkDeleteView.as_view(), name='manufacturer_bulk_delete'),
|
url(r'^manufacturers/delete/$', views.ManufacturerBulkDeleteView.as_view(), name='manufacturer_bulk_delete'),
|
||||||
url(r'^manufacturers/(?P<slug>[\w-]+)/edit/$', views.ManufacturerEditView.as_view(), name='manufacturer_edit'),
|
url(r'^manufacturers/(?P<slug>[\w-]+)/edit/$', views.ManufacturerEditView.as_view(), name='manufacturer_edit'),
|
||||||
|
|
||||||
# Device types
|
# Device types
|
||||||
url(r'^device-types/$', views.DeviceTypeListView.as_view(), name='devicetype_list'),
|
url(r'^device-types/$', views.DeviceTypeListView.as_view(), name='devicetype_list'),
|
||||||
url(r'^device-types/add/$', views.DeviceTypeEditView.as_view(), name='devicetype_add'),
|
url(r'^device-types/add/$', views.DeviceTypeCreateView.as_view(), name='devicetype_add'),
|
||||||
url(r'^device-types/edit/$', views.DeviceTypeBulkEditView.as_view(), name='devicetype_bulk_edit'),
|
url(r'^device-types/edit/$', views.DeviceTypeBulkEditView.as_view(), name='devicetype_bulk_edit'),
|
||||||
url(r'^device-types/delete/$', views.DeviceTypeBulkDeleteView.as_view(), name='devicetype_bulk_delete'),
|
url(r'^device-types/delete/$', views.DeviceTypeBulkDeleteView.as_view(), name='devicetype_bulk_delete'),
|
||||||
url(r'^device-types/(?P<pk>\d+)/$', views.DeviceTypeView.as_view(), name='devicetype'),
|
url(r'^device-types/(?P<pk>\d+)/$', views.DeviceTypeView.as_view(), name='devicetype'),
|
||||||
@ -75,45 +75,45 @@ urlpatterns = [
|
|||||||
url(r'^device-types/(?P<pk>\d+)/delete/$', views.DeviceTypeDeleteView.as_view(), name='devicetype_delete'),
|
url(r'^device-types/(?P<pk>\d+)/delete/$', views.DeviceTypeDeleteView.as_view(), name='devicetype_delete'),
|
||||||
|
|
||||||
# Console port templates
|
# Console port templates
|
||||||
url(r'^device-types/(?P<pk>\d+)/console-ports/add/$', views.ConsolePortTemplateAddView.as_view(), name='devicetype_add_consoleport'),
|
url(r'^device-types/(?P<pk>\d+)/console-ports/add/$', views.ConsolePortTemplateCreateView.as_view(), name='devicetype_add_consoleport'),
|
||||||
url(r'^device-types/(?P<pk>\d+)/console-ports/delete/$', views.ConsolePortTemplateBulkDeleteView.as_view(), name='devicetype_delete_consoleport'),
|
url(r'^device-types/(?P<pk>\d+)/console-ports/delete/$', views.ConsolePortTemplateBulkDeleteView.as_view(), name='devicetype_delete_consoleport'),
|
||||||
|
|
||||||
# Console server port templates
|
# Console server port templates
|
||||||
url(r'^device-types/(?P<pk>\d+)/console-server-ports/add/$', views.ConsoleServerPortTemplateAddView.as_view(), name='devicetype_add_consoleserverport'),
|
url(r'^device-types/(?P<pk>\d+)/console-server-ports/add/$', views.ConsoleServerPortTemplateCreateView.as_view(), name='devicetype_add_consoleserverport'),
|
||||||
url(r'^device-types/(?P<pk>\d+)/console-server-ports/delete/$', views.ConsoleServerPortTemplateBulkDeleteView.as_view(), name='devicetype_delete_consoleserverport'),
|
url(r'^device-types/(?P<pk>\d+)/console-server-ports/delete/$', views.ConsoleServerPortTemplateBulkDeleteView.as_view(), name='devicetype_delete_consoleserverport'),
|
||||||
|
|
||||||
# Power port templates
|
# Power port templates
|
||||||
url(r'^device-types/(?P<pk>\d+)/power-ports/add/$', views.PowerPortTemplateAddView.as_view(), name='devicetype_add_powerport'),
|
url(r'^device-types/(?P<pk>\d+)/power-ports/add/$', views.PowerPortTemplateCreateView.as_view(), name='devicetype_add_powerport'),
|
||||||
url(r'^device-types/(?P<pk>\d+)/power-ports/delete/$', views.PowerPortTemplateBulkDeleteView.as_view(), name='devicetype_delete_powerport'),
|
url(r'^device-types/(?P<pk>\d+)/power-ports/delete/$', views.PowerPortTemplateBulkDeleteView.as_view(), name='devicetype_delete_powerport'),
|
||||||
|
|
||||||
# Power outlet templates
|
# Power outlet templates
|
||||||
url(r'^device-types/(?P<pk>\d+)/power-outlets/add/$', views.PowerOutletTemplateAddView.as_view(), name='devicetype_add_poweroutlet'),
|
url(r'^device-types/(?P<pk>\d+)/power-outlets/add/$', views.PowerOutletTemplateCreateView.as_view(), name='devicetype_add_poweroutlet'),
|
||||||
url(r'^device-types/(?P<pk>\d+)/power-outlets/delete/$', views.PowerOutletTemplateBulkDeleteView.as_view(), name='devicetype_delete_poweroutlet'),
|
url(r'^device-types/(?P<pk>\d+)/power-outlets/delete/$', views.PowerOutletTemplateBulkDeleteView.as_view(), name='devicetype_delete_poweroutlet'),
|
||||||
|
|
||||||
# Interface templates
|
# Interface templates
|
||||||
url(r'^device-types/(?P<pk>\d+)/interfaces/add/$', views.InterfaceTemplateAddView.as_view(), name='devicetype_add_interface'),
|
url(r'^device-types/(?P<pk>\d+)/interfaces/add/$', views.InterfaceTemplateCreateView.as_view(), name='devicetype_add_interface'),
|
||||||
url(r'^device-types/(?P<pk>\d+)/interfaces/edit/$', views.InterfaceTemplateBulkEditView.as_view(), name='devicetype_bulkedit_interface'),
|
url(r'^device-types/(?P<pk>\d+)/interfaces/edit/$', views.InterfaceTemplateBulkEditView.as_view(), name='devicetype_bulkedit_interface'),
|
||||||
url(r'^device-types/(?P<pk>\d+)/interfaces/delete/$', views.InterfaceTemplateBulkDeleteView.as_view(), name='devicetype_delete_interface'),
|
url(r'^device-types/(?P<pk>\d+)/interfaces/delete/$', views.InterfaceTemplateBulkDeleteView.as_view(), name='devicetype_delete_interface'),
|
||||||
|
|
||||||
# Device bay templates
|
# Device bay templates
|
||||||
url(r'^device-types/(?P<pk>\d+)/device-bays/add/$', views.DeviceBayTemplateAddView.as_view(), name='devicetype_add_devicebay'),
|
url(r'^device-types/(?P<pk>\d+)/device-bays/add/$', views.DeviceBayTemplateCreateView.as_view(), name='devicetype_add_devicebay'),
|
||||||
url(r'^device-types/(?P<pk>\d+)/device-bays/delete/$', views.DeviceBayTemplateBulkDeleteView.as_view(), name='devicetype_delete_devicebay'),
|
url(r'^device-types/(?P<pk>\d+)/device-bays/delete/$', views.DeviceBayTemplateBulkDeleteView.as_view(), name='devicetype_delete_devicebay'),
|
||||||
|
|
||||||
# Device roles
|
# Device roles
|
||||||
url(r'^device-roles/$', views.DeviceRoleListView.as_view(), name='devicerole_list'),
|
url(r'^device-roles/$', views.DeviceRoleListView.as_view(), name='devicerole_list'),
|
||||||
url(r'^device-roles/add/$', views.DeviceRoleEditView.as_view(), name='devicerole_add'),
|
url(r'^device-roles/add/$', views.DeviceRoleCreateView.as_view(), name='devicerole_add'),
|
||||||
url(r'^device-roles/delete/$', views.DeviceRoleBulkDeleteView.as_view(), name='devicerole_bulk_delete'),
|
url(r'^device-roles/delete/$', views.DeviceRoleBulkDeleteView.as_view(), name='devicerole_bulk_delete'),
|
||||||
url(r'^device-roles/(?P<slug>[\w-]+)/edit/$', views.DeviceRoleEditView.as_view(), name='devicerole_edit'),
|
url(r'^device-roles/(?P<slug>[\w-]+)/edit/$', views.DeviceRoleEditView.as_view(), name='devicerole_edit'),
|
||||||
|
|
||||||
# Platforms
|
# Platforms
|
||||||
url(r'^platforms/$', views.PlatformListView.as_view(), name='platform_list'),
|
url(r'^platforms/$', views.PlatformListView.as_view(), name='platform_list'),
|
||||||
url(r'^platforms/add/$', views.PlatformEditView.as_view(), name='platform_add'),
|
url(r'^platforms/add/$', views.PlatformCreateView.as_view(), name='platform_add'),
|
||||||
url(r'^platforms/delete/$', views.PlatformBulkDeleteView.as_view(), name='platform_bulk_delete'),
|
url(r'^platforms/delete/$', views.PlatformBulkDeleteView.as_view(), name='platform_bulk_delete'),
|
||||||
url(r'^platforms/(?P<slug>[\w-]+)/edit/$', views.PlatformEditView.as_view(), name='platform_edit'),
|
url(r'^platforms/(?P<slug>[\w-]+)/edit/$', views.PlatformEditView.as_view(), name='platform_edit'),
|
||||||
|
|
||||||
# Devices
|
# Devices
|
||||||
url(r'^devices/$', views.DeviceListView.as_view(), name='device_list'),
|
url(r'^devices/$', views.DeviceListView.as_view(), name='device_list'),
|
||||||
url(r'^devices/add/$', views.DeviceEditView.as_view(), name='device_add'),
|
url(r'^devices/add/$', views.DeviceCreateView.as_view(), name='device_add'),
|
||||||
url(r'^devices/import/$', views.DeviceBulkImportView.as_view(), name='device_import'),
|
url(r'^devices/import/$', views.DeviceBulkImportView.as_view(), name='device_import'),
|
||||||
url(r'^devices/import/child-devices/$', views.ChildDeviceBulkImportView.as_view(), name='device_import_child'),
|
url(r'^devices/import/child-devices/$', views.ChildDeviceBulkImportView.as_view(), name='device_import_child'),
|
||||||
url(r'^devices/edit/$', views.DeviceBulkEditView.as_view(), name='device_bulk_edit'),
|
url(r'^devices/edit/$', views.DeviceBulkEditView.as_view(), name='device_bulk_edit'),
|
||||||
@ -124,12 +124,12 @@ urlpatterns = [
|
|||||||
url(r'^devices/(?P<pk>\d+)/inventory/$', views.DeviceInventoryView.as_view(), name='device_inventory'),
|
url(r'^devices/(?P<pk>\d+)/inventory/$', views.DeviceInventoryView.as_view(), name='device_inventory'),
|
||||||
url(r'^devices/(?P<pk>\d+)/lldp-neighbors/$', views.DeviceLLDPNeighborsView.as_view(), name='device_lldp_neighbors'),
|
url(r'^devices/(?P<pk>\d+)/lldp-neighbors/$', views.DeviceLLDPNeighborsView.as_view(), name='device_lldp_neighbors'),
|
||||||
url(r'^devices/(?P<pk>\d+)/add-secret/$', secret_add, name='device_addsecret'),
|
url(r'^devices/(?P<pk>\d+)/add-secret/$', secret_add, name='device_addsecret'),
|
||||||
url(r'^devices/(?P<device>\d+)/services/assign/$', ServiceEditView.as_view(), name='service_assign'),
|
url(r'^devices/(?P<device>\d+)/services/assign/$', ServiceCreateView.as_view(), name='service_assign'),
|
||||||
url(r'^devices/(?P<object_id>\d+)/images/add/$', ImageAttachmentEditView.as_view(), name='device_add_image', kwargs={'model': Device}),
|
url(r'^devices/(?P<object_id>\d+)/images/add/$', ImageAttachmentEditView.as_view(), name='device_add_image', kwargs={'model': Device}),
|
||||||
|
|
||||||
# Console ports
|
# Console ports
|
||||||
url(r'^devices/console-ports/add/$', views.DeviceBulkAddConsolePortView.as_view(), name='device_bulk_add_consoleport'),
|
url(r'^devices/console-ports/add/$', views.DeviceBulkAddConsolePortView.as_view(), name='device_bulk_add_consoleport'),
|
||||||
url(r'^devices/(?P<pk>\d+)/console-ports/add/$', views.ConsolePortAddView.as_view(), name='consoleport_add'),
|
url(r'^devices/(?P<pk>\d+)/console-ports/add/$', views.ConsolePortCreateView.as_view(), name='consoleport_add'),
|
||||||
url(r'^devices/(?P<pk>\d+)/console-ports/delete/$', views.ConsolePortBulkDeleteView.as_view(), name='consoleport_bulk_delete'),
|
url(r'^devices/(?P<pk>\d+)/console-ports/delete/$', views.ConsolePortBulkDeleteView.as_view(), name='consoleport_bulk_delete'),
|
||||||
url(r'^console-ports/(?P<pk>\d+)/connect/$', views.consoleport_connect, name='consoleport_connect'),
|
url(r'^console-ports/(?P<pk>\d+)/connect/$', views.consoleport_connect, name='consoleport_connect'),
|
||||||
url(r'^console-ports/(?P<pk>\d+)/disconnect/$', views.consoleport_disconnect, name='consoleport_disconnect'),
|
url(r'^console-ports/(?P<pk>\d+)/disconnect/$', views.consoleport_disconnect, name='consoleport_disconnect'),
|
||||||
@ -138,7 +138,8 @@ urlpatterns = [
|
|||||||
|
|
||||||
# Console server ports
|
# Console server ports
|
||||||
url(r'^devices/console-server-ports/add/$', views.DeviceBulkAddConsoleServerPortView.as_view(), name='device_bulk_add_consoleserverport'),
|
url(r'^devices/console-server-ports/add/$', views.DeviceBulkAddConsoleServerPortView.as_view(), name='device_bulk_add_consoleserverport'),
|
||||||
url(r'^devices/(?P<pk>\d+)/console-server-ports/add/$', views.ConsoleServerPortAddView.as_view(), name='consoleserverport_add'),
|
url(r'^devices/(?P<pk>\d+)/console-server-ports/add/$', views.ConsoleServerPortCreateView.as_view(), name='consoleserverport_add'),
|
||||||
|
url(r'^devices/(?P<pk>\d+)/console-server-ports/disconnect/$', views.ConsoleServerPortBulkDisconnectView.as_view(), name='consoleserverport_bulk_disconnect'),
|
||||||
url(r'^devices/(?P<pk>\d+)/console-server-ports/delete/$', views.ConsoleServerPortBulkDeleteView.as_view(), name='consoleserverport_bulk_delete'),
|
url(r'^devices/(?P<pk>\d+)/console-server-ports/delete/$', views.ConsoleServerPortBulkDeleteView.as_view(), name='consoleserverport_bulk_delete'),
|
||||||
url(r'^console-server-ports/(?P<pk>\d+)/connect/$', views.consoleserverport_connect, name='consoleserverport_connect'),
|
url(r'^console-server-ports/(?P<pk>\d+)/connect/$', views.consoleserverport_connect, name='consoleserverport_connect'),
|
||||||
url(r'^console-server-ports/(?P<pk>\d+)/disconnect/$', views.consoleserverport_disconnect, name='consoleserverport_disconnect'),
|
url(r'^console-server-ports/(?P<pk>\d+)/disconnect/$', views.consoleserverport_disconnect, name='consoleserverport_disconnect'),
|
||||||
@ -147,7 +148,7 @@ urlpatterns = [
|
|||||||
|
|
||||||
# Power ports
|
# Power ports
|
||||||
url(r'^devices/power-ports/add/$', views.DeviceBulkAddPowerPortView.as_view(), name='device_bulk_add_powerport'),
|
url(r'^devices/power-ports/add/$', views.DeviceBulkAddPowerPortView.as_view(), name='device_bulk_add_powerport'),
|
||||||
url(r'^devices/(?P<pk>\d+)/power-ports/add/$', views.PowerPortAddView.as_view(), name='powerport_add'),
|
url(r'^devices/(?P<pk>\d+)/power-ports/add/$', views.PowerPortCreateView.as_view(), name='powerport_add'),
|
||||||
url(r'^devices/(?P<pk>\d+)/power-ports/delete/$', views.PowerPortBulkDeleteView.as_view(), name='powerport_bulk_delete'),
|
url(r'^devices/(?P<pk>\d+)/power-ports/delete/$', views.PowerPortBulkDeleteView.as_view(), name='powerport_bulk_delete'),
|
||||||
url(r'^power-ports/(?P<pk>\d+)/connect/$', views.powerport_connect, name='powerport_connect'),
|
url(r'^power-ports/(?P<pk>\d+)/connect/$', views.powerport_connect, name='powerport_connect'),
|
||||||
url(r'^power-ports/(?P<pk>\d+)/disconnect/$', views.powerport_disconnect, name='powerport_disconnect'),
|
url(r'^power-ports/(?P<pk>\d+)/disconnect/$', views.powerport_disconnect, name='powerport_disconnect'),
|
||||||
@ -156,7 +157,8 @@ urlpatterns = [
|
|||||||
|
|
||||||
# Power outlets
|
# Power outlets
|
||||||
url(r'^devices/power-outlets/add/$', views.DeviceBulkAddPowerOutletView.as_view(), name='device_bulk_add_poweroutlet'),
|
url(r'^devices/power-outlets/add/$', views.DeviceBulkAddPowerOutletView.as_view(), name='device_bulk_add_poweroutlet'),
|
||||||
url(r'^devices/(?P<pk>\d+)/power-outlets/add/$', views.PowerOutletAddView.as_view(), name='poweroutlet_add'),
|
url(r'^devices/(?P<pk>\d+)/power-outlets/add/$', views.PowerOutletCreateView.as_view(), name='poweroutlet_add'),
|
||||||
|
url(r'^devices/(?P<pk>\d+)/power-outlets/disconnect/$', views.PowerOutletBulkDisconnectView.as_view(), name='poweroutlet_bulk_disconnect'),
|
||||||
url(r'^devices/(?P<pk>\d+)/power-outlets/delete/$', views.PowerOutletBulkDeleteView.as_view(), name='poweroutlet_bulk_delete'),
|
url(r'^devices/(?P<pk>\d+)/power-outlets/delete/$', views.PowerOutletBulkDeleteView.as_view(), name='poweroutlet_bulk_delete'),
|
||||||
url(r'^power-outlets/(?P<pk>\d+)/connect/$', views.poweroutlet_connect, name='poweroutlet_connect'),
|
url(r'^power-outlets/(?P<pk>\d+)/connect/$', views.poweroutlet_connect, name='poweroutlet_connect'),
|
||||||
url(r'^power-outlets/(?P<pk>\d+)/disconnect/$', views.poweroutlet_disconnect, name='poweroutlet_disconnect'),
|
url(r'^power-outlets/(?P<pk>\d+)/disconnect/$', views.poweroutlet_disconnect, name='poweroutlet_disconnect'),
|
||||||
@ -165,8 +167,9 @@ urlpatterns = [
|
|||||||
|
|
||||||
# Interfaces
|
# Interfaces
|
||||||
url(r'^devices/interfaces/add/$', views.DeviceBulkAddInterfaceView.as_view(), name='device_bulk_add_interface'),
|
url(r'^devices/interfaces/add/$', views.DeviceBulkAddInterfaceView.as_view(), name='device_bulk_add_interface'),
|
||||||
url(r'^devices/(?P<pk>\d+)/interfaces/add/$', views.InterfaceAddView.as_view(), name='interface_add'),
|
url(r'^devices/(?P<pk>\d+)/interfaces/add/$', views.InterfaceCreateView.as_view(), name='interface_add'),
|
||||||
url(r'^devices/(?P<pk>\d+)/interfaces/edit/$', views.InterfaceBulkEditView.as_view(), name='interface_bulk_edit'),
|
url(r'^devices/(?P<pk>\d+)/interfaces/edit/$', views.InterfaceBulkEditView.as_view(), name='interface_bulk_edit'),
|
||||||
|
url(r'^devices/(?P<pk>\d+)/interfaces/disconnect/$', views.InterfaceBulkDisconnectView.as_view(), name='interface_bulk_disconnect'),
|
||||||
url(r'^devices/(?P<pk>\d+)/interfaces/delete/$', views.InterfaceBulkDeleteView.as_view(), name='interface_bulk_delete'),
|
url(r'^devices/(?P<pk>\d+)/interfaces/delete/$', views.InterfaceBulkDeleteView.as_view(), name='interface_bulk_delete'),
|
||||||
url(r'^devices/(?P<pk>\d+)/interface-connections/add/$', views.interfaceconnection_add, name='interfaceconnection_add'),
|
url(r'^devices/(?P<pk>\d+)/interface-connections/add/$', views.interfaceconnection_add, name='interfaceconnection_add'),
|
||||||
url(r'^interface-connections/(?P<pk>\d+)/delete/$', views.interfaceconnection_delete, name='interfaceconnection_delete'),
|
url(r'^interface-connections/(?P<pk>\d+)/delete/$', views.interfaceconnection_delete, name='interfaceconnection_delete'),
|
||||||
@ -175,7 +178,7 @@ urlpatterns = [
|
|||||||
|
|
||||||
# Device bays
|
# Device bays
|
||||||
url(r'^devices/device-bays/add/$', views.DeviceBulkAddDeviceBayView.as_view(), name='device_bulk_add_devicebay'),
|
url(r'^devices/device-bays/add/$', views.DeviceBulkAddDeviceBayView.as_view(), name='device_bulk_add_devicebay'),
|
||||||
url(r'^devices/(?P<pk>\d+)/bays/add/$', views.DeviceBayAddView.as_view(), name='devicebay_add'),
|
url(r'^devices/(?P<pk>\d+)/bays/add/$', views.DeviceBayCreateView.as_view(), name='devicebay_add'),
|
||||||
url(r'^devices/(?P<pk>\d+)/bays/delete/$', views.DeviceBayBulkDeleteView.as_view(), name='devicebay_bulk_delete'),
|
url(r'^devices/(?P<pk>\d+)/bays/delete/$', views.DeviceBayBulkDeleteView.as_view(), name='devicebay_bulk_delete'),
|
||||||
url(r'^device-bays/(?P<pk>\d+)/edit/$', views.DeviceBayEditView.as_view(), name='devicebay_edit'),
|
url(r'^device-bays/(?P<pk>\d+)/edit/$', views.DeviceBayEditView.as_view(), name='devicebay_edit'),
|
||||||
url(r'^device-bays/(?P<pk>\d+)/delete/$', views.DeviceBayDeleteView.as_view(), name='devicebay_delete'),
|
url(r'^device-bays/(?P<pk>\d+)/delete/$', views.DeviceBayDeleteView.as_view(), name='devicebay_delete'),
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from difflib import SequenceMatcher
|
|
||||||
import re
|
import re
|
||||||
from natsort import natsorted
|
from natsort import natsorted
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
@ -9,7 +8,7 @@ from django.contrib import messages
|
|||||||
from django.contrib.auth.decorators import permission_required
|
from django.contrib.auth.decorators import permission_required
|
||||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||||
from django.core.paginator import EmptyPage, PageNotAnInteger
|
from django.core.paginator import EmptyPage, PageNotAnInteger
|
||||||
from django.db.models import Count
|
from django.db.models import Count, Q
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.shortcuts import get_object_or_404, redirect, render
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
@ -142,6 +141,44 @@ class ComponentDeleteView(ObjectDeleteView):
|
|||||||
return obj.device.get_absolute_url()
|
return obj.device.get_absolute_url()
|
||||||
|
|
||||||
|
|
||||||
|
class BulkDisconnectView(View):
|
||||||
|
"""
|
||||||
|
An extendable view for disconnection console/power/interface components in bulk.
|
||||||
|
"""
|
||||||
|
model = None
|
||||||
|
form = None
|
||||||
|
template_name = 'dcim/bulk_disconnect.html'
|
||||||
|
|
||||||
|
def disconnect_objects(self, objects):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def post(self, request, pk):
|
||||||
|
|
||||||
|
device = get_object_or_404(Device, pk=pk)
|
||||||
|
selected_objects = []
|
||||||
|
|
||||||
|
if '_confirm' in request.POST:
|
||||||
|
form = self.form(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
count = self.disconnect_objects(form.cleaned_data['pk'])
|
||||||
|
messages.success(request, "Disconnected {} {} on {}".format(
|
||||||
|
count, self.model._meta.verbose_name_plural, device
|
||||||
|
))
|
||||||
|
return redirect(device.get_absolute_url())
|
||||||
|
|
||||||
|
else:
|
||||||
|
form = self.form(initial={'pk': request.POST.getlist('pk')})
|
||||||
|
selected_objects = self.model.objects.filter(pk__in=form.initial['pk'])
|
||||||
|
|
||||||
|
return render(request, self.template_name, {
|
||||||
|
'form': form,
|
||||||
|
'device': device,
|
||||||
|
'obj_type_plural': self.model._meta.verbose_name_plural,
|
||||||
|
'selected_objects': selected_objects,
|
||||||
|
'return_url': device.get_absolute_url(),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Regions
|
# Regions
|
||||||
#
|
#
|
||||||
@ -152,8 +189,8 @@ class RegionListView(ObjectListView):
|
|||||||
template_name = 'dcim/region_list.html'
|
template_name = 'dcim/region_list.html'
|
||||||
|
|
||||||
|
|
||||||
class RegionEditView(PermissionRequiredMixin, ObjectEditView):
|
class RegionCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'dcim.change_region'
|
permission_required = 'dcim.add_region'
|
||||||
model = Region
|
model = Region
|
||||||
form_class = forms.RegionForm
|
form_class = forms.RegionForm
|
||||||
|
|
||||||
@ -161,6 +198,10 @@ class RegionEditView(PermissionRequiredMixin, ObjectEditView):
|
|||||||
return reverse('dcim:region_list')
|
return reverse('dcim:region_list')
|
||||||
|
|
||||||
|
|
||||||
|
class RegionEditView(RegionCreateView):
|
||||||
|
permission_required = 'dcim.change_region'
|
||||||
|
|
||||||
|
|
||||||
class RegionBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
class RegionBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||||
permission_required = 'dcim.delete_region'
|
permission_required = 'dcim.delete_region'
|
||||||
cls = Region
|
cls = Region
|
||||||
@ -204,14 +245,18 @@ class SiteView(View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class SiteEditView(PermissionRequiredMixin, ObjectEditView):
|
class SiteCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'dcim.change_site'
|
permission_required = 'dcim.add_site'
|
||||||
model = Site
|
model = Site
|
||||||
form_class = forms.SiteForm
|
form_class = forms.SiteForm
|
||||||
template_name = 'dcim/site_edit.html'
|
template_name = 'dcim/site_edit.html'
|
||||||
default_return_url = 'dcim:site_list'
|
default_return_url = 'dcim:site_list'
|
||||||
|
|
||||||
|
|
||||||
|
class SiteEditView(SiteCreateView):
|
||||||
|
permission_required = 'dcim.change_site'
|
||||||
|
|
||||||
|
|
||||||
class SiteDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
class SiteDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||||
permission_required = 'dcim.delete_site'
|
permission_required = 'dcim.delete_site'
|
||||||
model = Site
|
model = Site
|
||||||
@ -246,8 +291,8 @@ class RackGroupListView(ObjectListView):
|
|||||||
template_name = 'dcim/rackgroup_list.html'
|
template_name = 'dcim/rackgroup_list.html'
|
||||||
|
|
||||||
|
|
||||||
class RackGroupEditView(PermissionRequiredMixin, ObjectEditView):
|
class RackGroupCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'dcim.change_rackgroup'
|
permission_required = 'dcim.add_rackgroup'
|
||||||
model = RackGroup
|
model = RackGroup
|
||||||
form_class = forms.RackGroupForm
|
form_class = forms.RackGroupForm
|
||||||
|
|
||||||
@ -255,6 +300,10 @@ class RackGroupEditView(PermissionRequiredMixin, ObjectEditView):
|
|||||||
return reverse('dcim:rackgroup_list')
|
return reverse('dcim:rackgroup_list')
|
||||||
|
|
||||||
|
|
||||||
|
class RackGroupEditView(RackGroupCreateView):
|
||||||
|
permission_required = 'dcim.change_rackgroup'
|
||||||
|
|
||||||
|
|
||||||
class RackGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
class RackGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||||
permission_required = 'dcim.delete_rackgroup'
|
permission_required = 'dcim.delete_rackgroup'
|
||||||
cls = RackGroup
|
cls = RackGroup
|
||||||
@ -272,8 +321,8 @@ class RackRoleListView(ObjectListView):
|
|||||||
template_name = 'dcim/rackrole_list.html'
|
template_name = 'dcim/rackrole_list.html'
|
||||||
|
|
||||||
|
|
||||||
class RackRoleEditView(PermissionRequiredMixin, ObjectEditView):
|
class RackRoleCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'dcim.change_rackrole'
|
permission_required = 'dcim.add_rackrole'
|
||||||
model = RackRole
|
model = RackRole
|
||||||
form_class = forms.RackRoleForm
|
form_class = forms.RackRoleForm
|
||||||
|
|
||||||
@ -281,6 +330,10 @@ class RackRoleEditView(PermissionRequiredMixin, ObjectEditView):
|
|||||||
return reverse('dcim:rackrole_list')
|
return reverse('dcim:rackrole_list')
|
||||||
|
|
||||||
|
|
||||||
|
class RackRoleEditView(RackRoleCreateView):
|
||||||
|
permission_required = 'dcim.change_rackrole'
|
||||||
|
|
||||||
|
|
||||||
class RackRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
class RackRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||||
permission_required = 'dcim.delete_rackrole'
|
permission_required = 'dcim.delete_rackrole'
|
||||||
cls = RackRole
|
cls = RackRole
|
||||||
@ -374,14 +427,18 @@ class RackView(View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class RackEditView(PermissionRequiredMixin, ObjectEditView):
|
class RackCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'dcim.change_rack'
|
permission_required = 'dcim.add_rack'
|
||||||
model = Rack
|
model = Rack
|
||||||
form_class = forms.RackForm
|
form_class = forms.RackForm
|
||||||
template_name = 'dcim/rack_edit.html'
|
template_name = 'dcim/rack_edit.html'
|
||||||
default_return_url = 'dcim:rack_list'
|
default_return_url = 'dcim:rack_list'
|
||||||
|
|
||||||
|
|
||||||
|
class RackEditView(RackCreateView):
|
||||||
|
permission_required = 'dcim.change_rack'
|
||||||
|
|
||||||
|
|
||||||
class RackDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
class RackDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||||
permission_required = 'dcim.delete_rack'
|
permission_required = 'dcim.delete_rack'
|
||||||
model = Rack
|
model = Rack
|
||||||
@ -423,8 +480,8 @@ class RackReservationListView(ObjectListView):
|
|||||||
template_name = 'dcim/rackreservation_list.html'
|
template_name = 'dcim/rackreservation_list.html'
|
||||||
|
|
||||||
|
|
||||||
class RackReservationEditView(PermissionRequiredMixin, ObjectEditView):
|
class RackReservationCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'dcim.change_rackreservation'
|
permission_required = 'dcim.add_rackreservation'
|
||||||
model = RackReservation
|
model = RackReservation
|
||||||
form_class = forms.RackReservationForm
|
form_class = forms.RackReservationForm
|
||||||
|
|
||||||
@ -438,6 +495,10 @@ class RackReservationEditView(PermissionRequiredMixin, ObjectEditView):
|
|||||||
return obj.rack.get_absolute_url()
|
return obj.rack.get_absolute_url()
|
||||||
|
|
||||||
|
|
||||||
|
class RackReservationEditView(RackReservationCreateView):
|
||||||
|
permission_required = 'dcim.change_rackreservation'
|
||||||
|
|
||||||
|
|
||||||
class RackReservationDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
class RackReservationDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||||
permission_required = 'dcim.delete_rackreservation'
|
permission_required = 'dcim.delete_rackreservation'
|
||||||
model = RackReservation
|
model = RackReservation
|
||||||
@ -462,8 +523,8 @@ class ManufacturerListView(ObjectListView):
|
|||||||
template_name = 'dcim/manufacturer_list.html'
|
template_name = 'dcim/manufacturer_list.html'
|
||||||
|
|
||||||
|
|
||||||
class ManufacturerEditView(PermissionRequiredMixin, ObjectEditView):
|
class ManufacturerCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'dcim.change_manufacturer'
|
permission_required = 'dcim.add_manufacturer'
|
||||||
model = Manufacturer
|
model = Manufacturer
|
||||||
form_class = forms.ManufacturerForm
|
form_class = forms.ManufacturerForm
|
||||||
|
|
||||||
@ -471,6 +532,10 @@ class ManufacturerEditView(PermissionRequiredMixin, ObjectEditView):
|
|||||||
return reverse('dcim:manufacturer_list')
|
return reverse('dcim:manufacturer_list')
|
||||||
|
|
||||||
|
|
||||||
|
class ManufacturerEditView(ManufacturerCreateView):
|
||||||
|
permission_required = 'dcim.change_manufacturer'
|
||||||
|
|
||||||
|
|
||||||
class ManufacturerBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
class ManufacturerBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||||
permission_required = 'dcim.delete_manufacturer'
|
permission_required = 'dcim.delete_manufacturer'
|
||||||
cls = Manufacturer
|
cls = Manufacturer
|
||||||
@ -542,14 +607,18 @@ class DeviceTypeView(View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class DeviceTypeEditView(PermissionRequiredMixin, ObjectEditView):
|
class DeviceTypeCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'dcim.change_devicetype'
|
permission_required = 'dcim.add_devicetype'
|
||||||
model = DeviceType
|
model = DeviceType
|
||||||
form_class = forms.DeviceTypeForm
|
form_class = forms.DeviceTypeForm
|
||||||
template_name = 'dcim/devicetype_edit.html'
|
template_name = 'dcim/devicetype_edit.html'
|
||||||
default_return_url = 'dcim:devicetype_list'
|
default_return_url = 'dcim:devicetype_list'
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceTypeEditView(DeviceTypeCreateView):
|
||||||
|
permission_required = 'dcim.change_devicetype'
|
||||||
|
|
||||||
|
|
||||||
class DeviceTypeDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
class DeviceTypeDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||||
permission_required = 'dcim.delete_devicetype'
|
permission_required = 'dcim.delete_devicetype'
|
||||||
model = DeviceType
|
model = DeviceType
|
||||||
@ -576,7 +645,7 @@ class DeviceTypeBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
|||||||
# Device type components
|
# Device type components
|
||||||
#
|
#
|
||||||
|
|
||||||
class ConsolePortTemplateAddView(PermissionRequiredMixin, ComponentCreateView):
|
class ConsolePortTemplateCreateView(PermissionRequiredMixin, ComponentCreateView):
|
||||||
permission_required = 'dcim.add_consoleporttemplate'
|
permission_required = 'dcim.add_consoleporttemplate'
|
||||||
parent_model = DeviceType
|
parent_model = DeviceType
|
||||||
parent_field = 'device_type'
|
parent_field = 'device_type'
|
||||||
@ -593,7 +662,7 @@ class ConsolePortTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView)
|
|||||||
parent_cls = DeviceType
|
parent_cls = DeviceType
|
||||||
|
|
||||||
|
|
||||||
class ConsoleServerPortTemplateAddView(PermissionRequiredMixin, ComponentCreateView):
|
class ConsoleServerPortTemplateCreateView(PermissionRequiredMixin, ComponentCreateView):
|
||||||
permission_required = 'dcim.add_consoleserverporttemplate'
|
permission_required = 'dcim.add_consoleserverporttemplate'
|
||||||
parent_model = DeviceType
|
parent_model = DeviceType
|
||||||
parent_field = 'device_type'
|
parent_field = 'device_type'
|
||||||
@ -608,7 +677,7 @@ class ConsoleServerPortTemplateBulkDeleteView(PermissionRequiredMixin, BulkDelet
|
|||||||
parent_cls = DeviceType
|
parent_cls = DeviceType
|
||||||
|
|
||||||
|
|
||||||
class PowerPortTemplateAddView(PermissionRequiredMixin, ComponentCreateView):
|
class PowerPortTemplateCreateView(PermissionRequiredMixin, ComponentCreateView):
|
||||||
permission_required = 'dcim.add_powerporttemplate'
|
permission_required = 'dcim.add_powerporttemplate'
|
||||||
parent_model = DeviceType
|
parent_model = DeviceType
|
||||||
parent_field = 'device_type'
|
parent_field = 'device_type'
|
||||||
@ -623,7 +692,7 @@ class PowerPortTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
|||||||
parent_cls = DeviceType
|
parent_cls = DeviceType
|
||||||
|
|
||||||
|
|
||||||
class PowerOutletTemplateAddView(PermissionRequiredMixin, ComponentCreateView):
|
class PowerOutletTemplateCreateView(PermissionRequiredMixin, ComponentCreateView):
|
||||||
permission_required = 'dcim.add_poweroutlettemplate'
|
permission_required = 'dcim.add_poweroutlettemplate'
|
||||||
parent_model = DeviceType
|
parent_model = DeviceType
|
||||||
parent_field = 'device_type'
|
parent_field = 'device_type'
|
||||||
@ -638,7 +707,7 @@ class PowerOutletTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView)
|
|||||||
parent_cls = DeviceType
|
parent_cls = DeviceType
|
||||||
|
|
||||||
|
|
||||||
class InterfaceTemplateAddView(PermissionRequiredMixin, ComponentCreateView):
|
class InterfaceTemplateCreateView(PermissionRequiredMixin, ComponentCreateView):
|
||||||
permission_required = 'dcim.add_interfacetemplate'
|
permission_required = 'dcim.add_interfacetemplate'
|
||||||
parent_model = DeviceType
|
parent_model = DeviceType
|
||||||
parent_field = 'device_type'
|
parent_field = 'device_type'
|
||||||
@ -661,7 +730,7 @@ class InterfaceTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
|||||||
parent_cls = DeviceType
|
parent_cls = DeviceType
|
||||||
|
|
||||||
|
|
||||||
class DeviceBayTemplateAddView(PermissionRequiredMixin, ComponentCreateView):
|
class DeviceBayTemplateCreateView(PermissionRequiredMixin, ComponentCreateView):
|
||||||
permission_required = 'dcim.add_devicebaytemplate'
|
permission_required = 'dcim.add_devicebaytemplate'
|
||||||
parent_model = DeviceType
|
parent_model = DeviceType
|
||||||
parent_field = 'device_type'
|
parent_field = 'device_type'
|
||||||
@ -686,8 +755,8 @@ class DeviceRoleListView(ObjectListView):
|
|||||||
template_name = 'dcim/devicerole_list.html'
|
template_name = 'dcim/devicerole_list.html'
|
||||||
|
|
||||||
|
|
||||||
class DeviceRoleEditView(PermissionRequiredMixin, ObjectEditView):
|
class DeviceRoleCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'dcim.change_devicerole'
|
permission_required = 'dcim.add_devicerole'
|
||||||
model = DeviceRole
|
model = DeviceRole
|
||||||
form_class = forms.DeviceRoleForm
|
form_class = forms.DeviceRoleForm
|
||||||
|
|
||||||
@ -695,6 +764,10 @@ class DeviceRoleEditView(PermissionRequiredMixin, ObjectEditView):
|
|||||||
return reverse('dcim:devicerole_list')
|
return reverse('dcim:devicerole_list')
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceRoleEditView(DeviceRoleCreateView):
|
||||||
|
permission_required = 'dcim.change_devicerole'
|
||||||
|
|
||||||
|
|
||||||
class DeviceRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
class DeviceRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||||
permission_required = 'dcim.delete_devicerole'
|
permission_required = 'dcim.delete_devicerole'
|
||||||
cls = DeviceRole
|
cls = DeviceRole
|
||||||
@ -711,8 +784,8 @@ class PlatformListView(ObjectListView):
|
|||||||
template_name = 'dcim/platform_list.html'
|
template_name = 'dcim/platform_list.html'
|
||||||
|
|
||||||
|
|
||||||
class PlatformEditView(PermissionRequiredMixin, ObjectEditView):
|
class PlatformCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'dcim.change_platform'
|
permission_required = 'dcim.add_platform'
|
||||||
model = Platform
|
model = Platform
|
||||||
form_class = forms.PlatformForm
|
form_class = forms.PlatformForm
|
||||||
|
|
||||||
@ -720,6 +793,10 @@ class PlatformEditView(PermissionRequiredMixin, ObjectEditView):
|
|||||||
return reverse('dcim:platform_list')
|
return reverse('dcim:platform_list')
|
||||||
|
|
||||||
|
|
||||||
|
class PlatformEditView(PlatformCreateView):
|
||||||
|
permission_required = 'dcim.change_platform'
|
||||||
|
|
||||||
|
|
||||||
class PlatformBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
class PlatformBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||||
permission_required = 'dcim.delete_platform'
|
permission_required = 'dcim.delete_platform'
|
||||||
cls = Platform
|
cls = Platform
|
||||||
@ -843,14 +920,18 @@ class DeviceLLDPNeighborsView(View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class DeviceEditView(PermissionRequiredMixin, ObjectEditView):
|
class DeviceCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'dcim.change_device'
|
permission_required = 'dcim.add_device'
|
||||||
model = Device
|
model = Device
|
||||||
form_class = forms.DeviceForm
|
form_class = forms.DeviceForm
|
||||||
template_name = 'dcim/device_edit.html'
|
template_name = 'dcim/device_edit.html'
|
||||||
default_return_url = 'dcim:device_list'
|
default_return_url = 'dcim:device_list'
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceEditView(DeviceCreateView):
|
||||||
|
permission_required = 'dcim.change_device'
|
||||||
|
|
||||||
|
|
||||||
class DeviceDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
class DeviceDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||||
permission_required = 'dcim.delete_device'
|
permission_required = 'dcim.delete_device'
|
||||||
model = Device
|
model = Device
|
||||||
@ -904,7 +985,7 @@ class DeviceBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
|||||||
# Console ports
|
# Console ports
|
||||||
#
|
#
|
||||||
|
|
||||||
class ConsolePortAddView(PermissionRequiredMixin, ComponentCreateView):
|
class ConsolePortCreateView(PermissionRequiredMixin, ComponentCreateView):
|
||||||
permission_required = 'dcim.add_consoleport'
|
permission_required = 'dcim.add_consoleport'
|
||||||
parent_model = Device
|
parent_model = Device
|
||||||
parent_field = 'device'
|
parent_field = 'device'
|
||||||
@ -1017,7 +1098,7 @@ class ConsoleConnectionsBulkImportView(PermissionRequiredMixin, BulkImportView):
|
|||||||
# Console server ports
|
# Console server ports
|
||||||
#
|
#
|
||||||
|
|
||||||
class ConsoleServerPortAddView(PermissionRequiredMixin, ComponentCreateView):
|
class ConsoleServerPortCreateView(PermissionRequiredMixin, ComponentCreateView):
|
||||||
permission_required = 'dcim.add_consoleserverport'
|
permission_required = 'dcim.add_consoleserverport'
|
||||||
parent_model = Device
|
parent_model = Device
|
||||||
parent_field = 'device'
|
parent_field = 'device'
|
||||||
@ -1116,6 +1197,15 @@ class ConsoleServerPortDeleteView(PermissionRequiredMixin, ComponentDeleteView):
|
|||||||
model = ConsoleServerPort
|
model = ConsoleServerPort
|
||||||
|
|
||||||
|
|
||||||
|
class ConsoleServerPortBulkDisconnectView(PermissionRequiredMixin, BulkDisconnectView):
|
||||||
|
permission_required = 'dcim.change_consoleserverport'
|
||||||
|
model = ConsoleServerPort
|
||||||
|
form = forms.ConsoleServerPortBulkDisconnectForm
|
||||||
|
|
||||||
|
def disconnect_objects(self, cs_ports):
|
||||||
|
return ConsolePort.objects.filter(cs_port__in=cs_ports).update(cs_port=None, connection_status=None)
|
||||||
|
|
||||||
|
|
||||||
class ConsoleServerPortBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
class ConsoleServerPortBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||||
permission_required = 'dcim.delete_consoleserverport'
|
permission_required = 'dcim.delete_consoleserverport'
|
||||||
cls = ConsoleServerPort
|
cls = ConsoleServerPort
|
||||||
@ -1126,7 +1216,7 @@ class ConsoleServerPortBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
|||||||
# Power ports
|
# Power ports
|
||||||
#
|
#
|
||||||
|
|
||||||
class PowerPortAddView(PermissionRequiredMixin, ComponentCreateView):
|
class PowerPortCreateView(PermissionRequiredMixin, ComponentCreateView):
|
||||||
permission_required = 'dcim.add_powerport'
|
permission_required = 'dcim.add_powerport'
|
||||||
parent_model = Device
|
parent_model = Device
|
||||||
parent_field = 'device'
|
parent_field = 'device'
|
||||||
@ -1239,7 +1329,7 @@ class PowerConnectionsBulkImportView(PermissionRequiredMixin, BulkImportView):
|
|||||||
# Power outlets
|
# Power outlets
|
||||||
#
|
#
|
||||||
|
|
||||||
class PowerOutletAddView(PermissionRequiredMixin, ComponentCreateView):
|
class PowerOutletCreateView(PermissionRequiredMixin, ComponentCreateView):
|
||||||
permission_required = 'dcim.add_poweroutlet'
|
permission_required = 'dcim.add_poweroutlet'
|
||||||
parent_model = Device
|
parent_model = Device
|
||||||
parent_field = 'device'
|
parent_field = 'device'
|
||||||
@ -1338,6 +1428,17 @@ class PowerOutletDeleteView(PermissionRequiredMixin, ComponentDeleteView):
|
|||||||
model = PowerOutlet
|
model = PowerOutlet
|
||||||
|
|
||||||
|
|
||||||
|
class PowerOutletBulkDisconnectView(PermissionRequiredMixin, BulkDisconnectView):
|
||||||
|
permission_required = 'dcim.change_poweroutlet'
|
||||||
|
model = PowerOutlet
|
||||||
|
form = forms.PowerOutletBulkDisconnectForm
|
||||||
|
|
||||||
|
def disconnect_objects(self, power_outlets):
|
||||||
|
return PowerPort.objects.filter(power_outlet__in=power_outlets).update(
|
||||||
|
power_outlet=None, connection_status=None
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class PowerOutletBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
class PowerOutletBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||||
permission_required = 'dcim.delete_poweroutlet'
|
permission_required = 'dcim.delete_poweroutlet'
|
||||||
cls = PowerOutlet
|
cls = PowerOutlet
|
||||||
@ -1348,7 +1449,7 @@ class PowerOutletBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
|||||||
# Interfaces
|
# Interfaces
|
||||||
#
|
#
|
||||||
|
|
||||||
class InterfaceAddView(PermissionRequiredMixin, ComponentCreateView):
|
class InterfaceCreateView(PermissionRequiredMixin, ComponentCreateView):
|
||||||
permission_required = 'dcim.add_interface'
|
permission_required = 'dcim.add_interface'
|
||||||
parent_model = Device
|
parent_model = Device
|
||||||
parent_field = 'device'
|
parent_field = 'device'
|
||||||
@ -1368,6 +1469,18 @@ class InterfaceDeleteView(PermissionRequiredMixin, ComponentDeleteView):
|
|||||||
model = Interface
|
model = Interface
|
||||||
|
|
||||||
|
|
||||||
|
class InterfaceBulkDisconnectView(PermissionRequiredMixin, BulkDisconnectView):
|
||||||
|
permission_required = 'dcim.change_interface'
|
||||||
|
model = Interface
|
||||||
|
form = forms.InterfaceBulkDisconnectForm
|
||||||
|
|
||||||
|
def disconnect_objects(self, interfaces):
|
||||||
|
count, _ = InterfaceConnection.objects.filter(
|
||||||
|
Q(interface_a__in=interfaces) | Q(interface_b__in=interfaces)
|
||||||
|
).delete()
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
class InterfaceBulkEditView(PermissionRequiredMixin, BulkEditView):
|
class InterfaceBulkEditView(PermissionRequiredMixin, BulkEditView):
|
||||||
permission_required = 'dcim.change_interface'
|
permission_required = 'dcim.change_interface'
|
||||||
cls = Interface
|
cls = Interface
|
||||||
@ -1386,7 +1499,7 @@ class InterfaceBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
|||||||
# Device bays
|
# Device bays
|
||||||
#
|
#
|
||||||
|
|
||||||
class DeviceBayAddView(PermissionRequiredMixin, ComponentCreateView):
|
class DeviceBayCreateView(PermissionRequiredMixin, ComponentCreateView):
|
||||||
permission_required = 'dcim.add_devicebay'
|
permission_required = 'dcim.add_devicebay'
|
||||||
parent_model = Device
|
parent_model = Device
|
||||||
parent_field = 'device'
|
parent_field = 'device'
|
||||||
|
@ -371,7 +371,8 @@ class TopologyMap(models.Model):
|
|||||||
# Add all circuits to the graph
|
# Add all circuits to the graph
|
||||||
for termination in CircuitTermination.objects.filter(term_side='A', interface__device__in=devices):
|
for termination in CircuitTermination.objects.filter(term_side='A', interface__device__in=devices):
|
||||||
peer_termination = termination.get_peer_termination()
|
peer_termination = termination.get_peer_termination()
|
||||||
if peer_termination is not None and peer_termination.interface.device in devices:
|
if (peer_termination is not None and peer_termination.interface is not None and
|
||||||
|
peer_termination.interface.device in devices):
|
||||||
graph.edge(termination.interface.device.name, peer_termination.interface.device.name, color='blue')
|
graph.edge(termination.interface.device.name, peer_termination.interface.device.name, color='blue')
|
||||||
|
|
||||||
return graph.pipe(format=img_format)
|
return graph.pipe(format=img_format)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.core.exceptions import MultipleObjectsReturned
|
||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
|
|
||||||
from dcim.models import Site, Rack, Device, Interface
|
from dcim.models import Site, Rack, Device, Interface
|
||||||
@ -301,6 +302,10 @@ class PrefixCSVForm(forms.ModelForm):
|
|||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
raise forms.ValidationError("Global VLAN {} not found in group {}".format(vlan_vid, vlan_group))
|
raise forms.ValidationError("Global VLAN {} not found in group {}".format(vlan_vid, vlan_group))
|
||||||
|
except MultipleObjectsReturned:
|
||||||
|
raise forms.ValidationError(
|
||||||
|
"Multiple VLANs with VID {} found in group {}".format(vlan_vid, vlan_group)
|
||||||
|
)
|
||||||
elif vlan_vid:
|
elif vlan_vid:
|
||||||
try:
|
try:
|
||||||
self.instance.vlan = VLAN.objects.get(site=site, group__isnull=True, vid=vlan_vid)
|
self.instance.vlan = VLAN.objects.get(site=site, group__isnull=True, vid=vlan_vid)
|
||||||
@ -309,6 +314,8 @@ class PrefixCSVForm(forms.ModelForm):
|
|||||||
raise forms.ValidationError("VLAN {} not found in site {}".format(vlan_vid, site))
|
raise forms.ValidationError("VLAN {} not found in site {}".format(vlan_vid, site))
|
||||||
else:
|
else:
|
||||||
raise forms.ValidationError("Global VLAN {} not found".format(vlan_vid))
|
raise forms.ValidationError("Global VLAN {} not found".format(vlan_vid))
|
||||||
|
except MultipleObjectsReturned:
|
||||||
|
raise forms.ValidationError("Multiple VLANs with VID {} found".format(vlan_vid))
|
||||||
|
|
||||||
|
|
||||||
class PrefixBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
class PrefixBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
||||||
@ -490,7 +497,7 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldForm)
|
|||||||
initial['interface_site'] = instance.interface.device.site
|
initial['interface_site'] = instance.interface.device.site
|
||||||
initial['interface_rack'] = instance.interface.device.rack
|
initial['interface_rack'] = instance.interface.device.rack
|
||||||
initial['interface_device'] = instance.interface.device
|
initial['interface_device'] = instance.interface.device
|
||||||
if instance and instance.nat_inside is not None:
|
if instance and instance.nat_inside and instance.nat_inside.device is not None:
|
||||||
initial['nat_site'] = instance.nat_inside.device.site
|
initial['nat_site'] = instance.nat_inside.device.site
|
||||||
initial['nat_rack'] = instance.nat_inside.device.rack
|
initial['nat_rack'] = instance.nat_inside.device.rack
|
||||||
initial['nat_device'] = instance.nat_inside.device
|
initial['nat_device'] = instance.nat_inside.device
|
||||||
@ -582,7 +589,7 @@ class IPAddressCSVForm(forms.ModelForm):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
status = CSVChoiceField(
|
status = CSVChoiceField(
|
||||||
choices=PREFIX_STATUS_CHOICES,
|
choices=IPADDRESS_STATUS_CHOICES,
|
||||||
help_text='Operational status'
|
help_text='Operational status'
|
||||||
)
|
)
|
||||||
device = FlexibleModelChoiceField(
|
device = FlexibleModelChoiceField(
|
||||||
|
@ -10,7 +10,7 @@ urlpatterns = [
|
|||||||
|
|
||||||
# VRFs
|
# VRFs
|
||||||
url(r'^vrfs/$', views.VRFListView.as_view(), name='vrf_list'),
|
url(r'^vrfs/$', views.VRFListView.as_view(), name='vrf_list'),
|
||||||
url(r'^vrfs/add/$', views.VRFEditView.as_view(), name='vrf_add'),
|
url(r'^vrfs/add/$', views.VRFCreateView.as_view(), name='vrf_add'),
|
||||||
url(r'^vrfs/import/$', views.VRFBulkImportView.as_view(), name='vrf_import'),
|
url(r'^vrfs/import/$', views.VRFBulkImportView.as_view(), name='vrf_import'),
|
||||||
url(r'^vrfs/edit/$', views.VRFBulkEditView.as_view(), name='vrf_bulk_edit'),
|
url(r'^vrfs/edit/$', views.VRFBulkEditView.as_view(), name='vrf_bulk_edit'),
|
||||||
url(r'^vrfs/delete/$', views.VRFBulkDeleteView.as_view(), name='vrf_bulk_delete'),
|
url(r'^vrfs/delete/$', views.VRFBulkDeleteView.as_view(), name='vrf_bulk_delete'),
|
||||||
@ -20,13 +20,13 @@ urlpatterns = [
|
|||||||
|
|
||||||
# RIRs
|
# RIRs
|
||||||
url(r'^rirs/$', views.RIRListView.as_view(), name='rir_list'),
|
url(r'^rirs/$', views.RIRListView.as_view(), name='rir_list'),
|
||||||
url(r'^rirs/add/$', views.RIREditView.as_view(), name='rir_add'),
|
url(r'^rirs/add/$', views.RIRCreateView.as_view(), name='rir_add'),
|
||||||
url(r'^rirs/delete/$', views.RIRBulkDeleteView.as_view(), name='rir_bulk_delete'),
|
url(r'^rirs/delete/$', views.RIRBulkDeleteView.as_view(), name='rir_bulk_delete'),
|
||||||
url(r'^rirs/(?P<slug>[\w-]+)/edit/$', views.RIREditView.as_view(), name='rir_edit'),
|
url(r'^rirs/(?P<slug>[\w-]+)/edit/$', views.RIREditView.as_view(), name='rir_edit'),
|
||||||
|
|
||||||
# Aggregates
|
# Aggregates
|
||||||
url(r'^aggregates/$', views.AggregateListView.as_view(), name='aggregate_list'),
|
url(r'^aggregates/$', views.AggregateListView.as_view(), name='aggregate_list'),
|
||||||
url(r'^aggregates/add/$', views.AggregateEditView.as_view(), name='aggregate_add'),
|
url(r'^aggregates/add/$', views.AggregateCreateView.as_view(), name='aggregate_add'),
|
||||||
url(r'^aggregates/import/$', views.AggregateBulkImportView.as_view(), name='aggregate_import'),
|
url(r'^aggregates/import/$', views.AggregateBulkImportView.as_view(), name='aggregate_import'),
|
||||||
url(r'^aggregates/edit/$', views.AggregateBulkEditView.as_view(), name='aggregate_bulk_edit'),
|
url(r'^aggregates/edit/$', views.AggregateBulkEditView.as_view(), name='aggregate_bulk_edit'),
|
||||||
url(r'^aggregates/delete/$', views.AggregateBulkDeleteView.as_view(), name='aggregate_bulk_delete'),
|
url(r'^aggregates/delete/$', views.AggregateBulkDeleteView.as_view(), name='aggregate_bulk_delete'),
|
||||||
@ -36,13 +36,13 @@ urlpatterns = [
|
|||||||
|
|
||||||
# Roles
|
# Roles
|
||||||
url(r'^roles/$', views.RoleListView.as_view(), name='role_list'),
|
url(r'^roles/$', views.RoleListView.as_view(), name='role_list'),
|
||||||
url(r'^roles/add/$', views.RoleEditView.as_view(), name='role_add'),
|
url(r'^roles/add/$', views.RoleCreateView.as_view(), name='role_add'),
|
||||||
url(r'^roles/delete/$', views.RoleBulkDeleteView.as_view(), name='role_bulk_delete'),
|
url(r'^roles/delete/$', views.RoleBulkDeleteView.as_view(), name='role_bulk_delete'),
|
||||||
url(r'^roles/(?P<slug>[\w-]+)/edit/$', views.RoleEditView.as_view(), name='role_edit'),
|
url(r'^roles/(?P<slug>[\w-]+)/edit/$', views.RoleEditView.as_view(), name='role_edit'),
|
||||||
|
|
||||||
# Prefixes
|
# Prefixes
|
||||||
url(r'^prefixes/$', views.PrefixListView.as_view(), name='prefix_list'),
|
url(r'^prefixes/$', views.PrefixListView.as_view(), name='prefix_list'),
|
||||||
url(r'^prefixes/add/$', views.PrefixEditView.as_view(), name='prefix_add'),
|
url(r'^prefixes/add/$', views.PrefixCreateView.as_view(), name='prefix_add'),
|
||||||
url(r'^prefixes/import/$', views.PrefixBulkImportView.as_view(), name='prefix_import'),
|
url(r'^prefixes/import/$', views.PrefixBulkImportView.as_view(), name='prefix_import'),
|
||||||
url(r'^prefixes/edit/$', views.PrefixBulkEditView.as_view(), name='prefix_bulk_edit'),
|
url(r'^prefixes/edit/$', views.PrefixBulkEditView.as_view(), name='prefix_bulk_edit'),
|
||||||
url(r'^prefixes/delete/$', views.PrefixBulkDeleteView.as_view(), name='prefix_bulk_delete'),
|
url(r'^prefixes/delete/$', views.PrefixBulkDeleteView.as_view(), name='prefix_bulk_delete'),
|
||||||
@ -53,8 +53,8 @@ urlpatterns = [
|
|||||||
|
|
||||||
# IP addresses
|
# IP addresses
|
||||||
url(r'^ip-addresses/$', views.IPAddressListView.as_view(), name='ipaddress_list'),
|
url(r'^ip-addresses/$', views.IPAddressListView.as_view(), name='ipaddress_list'),
|
||||||
url(r'^ip-addresses/add/$', views.IPAddressEditView.as_view(), name='ipaddress_add'),
|
url(r'^ip-addresses/add/$', views.IPAddressCreateView.as_view(), name='ipaddress_add'),
|
||||||
url(r'^ip-addresses/bulk-add/$', views.IPAddressBulkAddView.as_view(), name='ipaddress_bulk_add'),
|
url(r'^ip-addresses/bulk-add/$', views.IPAddressBulkCreateView.as_view(), name='ipaddress_bulk_add'),
|
||||||
url(r'^ip-addresses/import/$', views.IPAddressBulkImportView.as_view(), name='ipaddress_import'),
|
url(r'^ip-addresses/import/$', views.IPAddressBulkImportView.as_view(), name='ipaddress_import'),
|
||||||
url(r'^ip-addresses/edit/$', views.IPAddressBulkEditView.as_view(), name='ipaddress_bulk_edit'),
|
url(r'^ip-addresses/edit/$', views.IPAddressBulkEditView.as_view(), name='ipaddress_bulk_edit'),
|
||||||
url(r'^ip-addresses/delete/$', views.IPAddressBulkDeleteView.as_view(), name='ipaddress_bulk_delete'),
|
url(r'^ip-addresses/delete/$', views.IPAddressBulkDeleteView.as_view(), name='ipaddress_bulk_delete'),
|
||||||
@ -64,13 +64,13 @@ urlpatterns = [
|
|||||||
|
|
||||||
# VLAN groups
|
# VLAN groups
|
||||||
url(r'^vlan-groups/$', views.VLANGroupListView.as_view(), name='vlangroup_list'),
|
url(r'^vlan-groups/$', views.VLANGroupListView.as_view(), name='vlangroup_list'),
|
||||||
url(r'^vlan-groups/add/$', views.VLANGroupEditView.as_view(), name='vlangroup_add'),
|
url(r'^vlan-groups/add/$', views.VLANGroupCreateView.as_view(), name='vlangroup_add'),
|
||||||
url(r'^vlan-groups/delete/$', views.VLANGroupBulkDeleteView.as_view(), name='vlangroup_bulk_delete'),
|
url(r'^vlan-groups/delete/$', views.VLANGroupBulkDeleteView.as_view(), name='vlangroup_bulk_delete'),
|
||||||
url(r'^vlan-groups/(?P<pk>\d+)/edit/$', views.VLANGroupEditView.as_view(), name='vlangroup_edit'),
|
url(r'^vlan-groups/(?P<pk>\d+)/edit/$', views.VLANGroupEditView.as_view(), name='vlangroup_edit'),
|
||||||
|
|
||||||
# VLANs
|
# VLANs
|
||||||
url(r'^vlans/$', views.VLANListView.as_view(), name='vlan_list'),
|
url(r'^vlans/$', views.VLANListView.as_view(), name='vlan_list'),
|
||||||
url(r'^vlans/add/$', views.VLANEditView.as_view(), name='vlan_add'),
|
url(r'^vlans/add/$', views.VLANCreateView.as_view(), name='vlan_add'),
|
||||||
url(r'^vlans/import/$', views.VLANBulkImportView.as_view(), name='vlan_import'),
|
url(r'^vlans/import/$', views.VLANBulkImportView.as_view(), name='vlan_import'),
|
||||||
url(r'^vlans/edit/$', views.VLANBulkEditView.as_view(), name='vlan_bulk_edit'),
|
url(r'^vlans/edit/$', views.VLANBulkEditView.as_view(), name='vlan_bulk_edit'),
|
||||||
url(r'^vlans/delete/$', views.VLANBulkDeleteView.as_view(), name='vlan_bulk_delete'),
|
url(r'^vlans/delete/$', views.VLANBulkDeleteView.as_view(), name='vlan_bulk_delete'),
|
||||||
|
@ -13,7 +13,7 @@ from django.views.generic import View
|
|||||||
from dcim.models import Device
|
from dcim.models import Device
|
||||||
from utilities.paginator import EnhancedPaginator
|
from utilities.paginator import EnhancedPaginator
|
||||||
from utilities.views import (
|
from utilities.views import (
|
||||||
BulkAddView, BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
|
BulkCreateView, BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
|
||||||
)
|
)
|
||||||
from . import filters, forms, tables
|
from . import filters, forms, tables
|
||||||
from .models import (
|
from .models import (
|
||||||
@ -114,14 +114,18 @@ class VRFView(View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class VRFEditView(PermissionRequiredMixin, ObjectEditView):
|
class VRFCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'ipam.change_vrf'
|
permission_required = 'ipam.add_vrf'
|
||||||
model = VRF
|
model = VRF
|
||||||
form_class = forms.VRFForm
|
form_class = forms.VRFForm
|
||||||
template_name = 'ipam/vrf_edit.html'
|
template_name = 'ipam/vrf_edit.html'
|
||||||
default_return_url = 'ipam:vrf_list'
|
default_return_url = 'ipam:vrf_list'
|
||||||
|
|
||||||
|
|
||||||
|
class VRFEditView(VRFCreateView):
|
||||||
|
permission_required = 'ipam.change_vrf'
|
||||||
|
|
||||||
|
|
||||||
class VRFDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
class VRFDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||||
permission_required = 'ipam.delete_vrf'
|
permission_required = 'ipam.delete_vrf'
|
||||||
model = VRF
|
model = VRF
|
||||||
@ -239,8 +243,8 @@ class RIRListView(ObjectListView):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class RIREditView(PermissionRequiredMixin, ObjectEditView):
|
class RIRCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'ipam.change_rir'
|
permission_required = 'ipam.add_rir'
|
||||||
model = RIR
|
model = RIR
|
||||||
form_class = forms.RIRForm
|
form_class = forms.RIRForm
|
||||||
|
|
||||||
@ -248,6 +252,10 @@ class RIREditView(PermissionRequiredMixin, ObjectEditView):
|
|||||||
return reverse('ipam:rir_list')
|
return reverse('ipam:rir_list')
|
||||||
|
|
||||||
|
|
||||||
|
class RIREditView(RIRCreateView):
|
||||||
|
permission_required = 'ipam.change_rir'
|
||||||
|
|
||||||
|
|
||||||
class RIRBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
class RIRBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||||
permission_required = 'ipam.delete_rir'
|
permission_required = 'ipam.delete_rir'
|
||||||
cls = RIR
|
cls = RIR
|
||||||
@ -324,14 +332,18 @@ class AggregateView(View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class AggregateEditView(PermissionRequiredMixin, ObjectEditView):
|
class AggregateCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'ipam.change_aggregate'
|
permission_required = 'ipam.add_aggregate'
|
||||||
model = Aggregate
|
model = Aggregate
|
||||||
form_class = forms.AggregateForm
|
form_class = forms.AggregateForm
|
||||||
template_name = 'ipam/aggregate_edit.html'
|
template_name = 'ipam/aggregate_edit.html'
|
||||||
default_return_url = 'ipam:aggregate_list'
|
default_return_url = 'ipam:aggregate_list'
|
||||||
|
|
||||||
|
|
||||||
|
class AggregateEditView(AggregateCreateView):
|
||||||
|
permission_required = 'ipam.change_aggregate'
|
||||||
|
|
||||||
|
|
||||||
class AggregateDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
class AggregateDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||||
permission_required = 'ipam.delete_aggregate'
|
permission_required = 'ipam.delete_aggregate'
|
||||||
model = Aggregate
|
model = Aggregate
|
||||||
@ -371,8 +383,8 @@ class RoleListView(ObjectListView):
|
|||||||
template_name = 'ipam/role_list.html'
|
template_name = 'ipam/role_list.html'
|
||||||
|
|
||||||
|
|
||||||
class RoleEditView(PermissionRequiredMixin, ObjectEditView):
|
class RoleCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'ipam.change_role'
|
permission_required = 'ipam.add_role'
|
||||||
model = Role
|
model = Role
|
||||||
form_class = forms.RoleForm
|
form_class = forms.RoleForm
|
||||||
|
|
||||||
@ -380,6 +392,10 @@ class RoleEditView(PermissionRequiredMixin, ObjectEditView):
|
|||||||
return reverse('ipam:role_list')
|
return reverse('ipam:role_list')
|
||||||
|
|
||||||
|
|
||||||
|
class RoleEditView(RoleCreateView):
|
||||||
|
permission_required = 'ipam.change_role'
|
||||||
|
|
||||||
|
|
||||||
class RoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
class RoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||||
permission_required = 'ipam.delete_role'
|
permission_required = 'ipam.delete_role'
|
||||||
cls = Role
|
cls = Role
|
||||||
@ -519,14 +535,18 @@ class PrefixIPAddressesView(View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class PrefixEditView(PermissionRequiredMixin, ObjectEditView):
|
class PrefixCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'ipam.change_prefix'
|
permission_required = 'ipam.add_prefix'
|
||||||
model = Prefix
|
model = Prefix
|
||||||
form_class = forms.PrefixForm
|
form_class = forms.PrefixForm
|
||||||
template_name = 'ipam/prefix_edit.html'
|
template_name = 'ipam/prefix_edit.html'
|
||||||
default_return_url = 'ipam:prefix_list'
|
default_return_url = 'ipam:prefix_list'
|
||||||
|
|
||||||
|
|
||||||
|
class PrefixEditView(PrefixCreateView):
|
||||||
|
permission_required = 'ipam.change_prefix'
|
||||||
|
|
||||||
|
|
||||||
class PrefixDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
class PrefixDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||||
permission_required = 'ipam.delete_prefix'
|
permission_required = 'ipam.delete_prefix'
|
||||||
model = Prefix
|
model = Prefix
|
||||||
@ -612,21 +632,25 @@ class IPAddressView(View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class IPAddressEditView(PermissionRequiredMixin, ObjectEditView):
|
class IPAddressCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'ipam.change_ipaddress'
|
permission_required = 'ipam.add_ipaddress'
|
||||||
model = IPAddress
|
model = IPAddress
|
||||||
form_class = forms.IPAddressForm
|
form_class = forms.IPAddressForm
|
||||||
template_name = 'ipam/ipaddress_edit.html'
|
template_name = 'ipam/ipaddress_edit.html'
|
||||||
default_return_url = 'ipam:ipaddress_list'
|
default_return_url = 'ipam:ipaddress_list'
|
||||||
|
|
||||||
|
|
||||||
|
class IPAddressEditView(IPAddressCreateView):
|
||||||
|
permission_required = 'ipam.change_ipaddress'
|
||||||
|
|
||||||
|
|
||||||
class IPAddressDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
class IPAddressDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||||
permission_required = 'ipam.delete_ipaddress'
|
permission_required = 'ipam.delete_ipaddress'
|
||||||
model = IPAddress
|
model = IPAddress
|
||||||
default_return_url = 'ipam:ipaddress_list'
|
default_return_url = 'ipam:ipaddress_list'
|
||||||
|
|
||||||
|
|
||||||
class IPAddressBulkAddView(PermissionRequiredMixin, BulkAddView):
|
class IPAddressBulkCreateView(PermissionRequiredMixin, BulkCreateView):
|
||||||
permission_required = 'ipam.add_ipaddress'
|
permission_required = 'ipam.add_ipaddress'
|
||||||
pattern_form = forms.IPAddressPatternForm
|
pattern_form = forms.IPAddressPatternForm
|
||||||
model_form = forms.IPAddressBulkAddForm
|
model_form = forms.IPAddressBulkAddForm
|
||||||
@ -683,8 +707,8 @@ class VLANGroupListView(ObjectListView):
|
|||||||
template_name = 'ipam/vlangroup_list.html'
|
template_name = 'ipam/vlangroup_list.html'
|
||||||
|
|
||||||
|
|
||||||
class VLANGroupEditView(PermissionRequiredMixin, ObjectEditView):
|
class VLANGroupCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'ipam.change_vlangroup'
|
permission_required = 'ipam.add_vlangroup'
|
||||||
model = VLANGroup
|
model = VLANGroup
|
||||||
form_class = forms.VLANGroupForm
|
form_class = forms.VLANGroupForm
|
||||||
|
|
||||||
@ -692,6 +716,10 @@ class VLANGroupEditView(PermissionRequiredMixin, ObjectEditView):
|
|||||||
return reverse('ipam:vlangroup_list')
|
return reverse('ipam:vlangroup_list')
|
||||||
|
|
||||||
|
|
||||||
|
class VLANGroupEditView(VLANGroupCreateView):
|
||||||
|
permission_required = 'ipam.change_vlangroup'
|
||||||
|
|
||||||
|
|
||||||
class VLANGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
class VLANGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||||
permission_required = 'ipam.delete_vlangroup'
|
permission_required = 'ipam.delete_vlangroup'
|
||||||
cls = VLANGroup
|
cls = VLANGroup
|
||||||
@ -728,14 +756,18 @@ class VLANView(View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class VLANEditView(PermissionRequiredMixin, ObjectEditView):
|
class VLANCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'ipam.change_vlan'
|
permission_required = 'ipam.add_vlan'
|
||||||
model = VLAN
|
model = VLAN
|
||||||
form_class = forms.VLANForm
|
form_class = forms.VLANForm
|
||||||
template_name = 'ipam/vlan_edit.html'
|
template_name = 'ipam/vlan_edit.html'
|
||||||
default_return_url = 'ipam:vlan_list'
|
default_return_url = 'ipam:vlan_list'
|
||||||
|
|
||||||
|
|
||||||
|
class VLANEditView(VLANCreateView):
|
||||||
|
permission_required = 'ipam.change_vlan'
|
||||||
|
|
||||||
|
|
||||||
class VLANDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
class VLANDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||||
permission_required = 'ipam.delete_vlan'
|
permission_required = 'ipam.delete_vlan'
|
||||||
model = VLAN
|
model = VLAN
|
||||||
@ -769,8 +801,8 @@ class VLANBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
|||||||
# Services
|
# Services
|
||||||
#
|
#
|
||||||
|
|
||||||
class ServiceEditView(PermissionRequiredMixin, ObjectEditView):
|
class ServiceCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'ipam.change_service'
|
permission_required = 'ipam.add_service'
|
||||||
model = Service
|
model = Service
|
||||||
form_class = forms.ServiceForm
|
form_class = forms.ServiceForm
|
||||||
template_name = 'ipam/service_edit.html'
|
template_name = 'ipam/service_edit.html'
|
||||||
@ -784,6 +816,10 @@ class ServiceEditView(PermissionRequiredMixin, ObjectEditView):
|
|||||||
return obj.device.get_absolute_url()
|
return obj.device.get_absolute_url()
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceEditView(ServiceCreateView):
|
||||||
|
permission_required = 'ipam.change_service'
|
||||||
|
|
||||||
|
|
||||||
class ServiceDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
class ServiceDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||||
permission_required = 'ipam.delete_service'
|
permission_required = 'ipam.delete_service'
|
||||||
model = Service
|
model = Service
|
||||||
|
@ -13,7 +13,7 @@ except ImportError:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
VERSION = '2.0.6'
|
VERSION = '2.0.7'
|
||||||
|
|
||||||
# Import required configuration parameters
|
# Import required configuration parameters
|
||||||
ALLOWED_HOSTS = DATABASE = SECRET_KEY = None
|
ALLOWED_HOSTS = DATABASE = SECRET_KEY = None
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
var search_field = $('#id_livesearch');
|
var search_field = $('#id_livesearch');
|
||||||
var real_field = $('#id_' + search_field.attr('data-field'));
|
var real_field = $('#id_' + search_field.attr('data-field'));
|
||||||
|
var select_fields = $('#select select');
|
||||||
var search_key = search_field.attr('data-key');
|
var search_key = search_field.attr('data-key');
|
||||||
var label = search_field.attr('data-label');
|
var label = search_field.attr('data-label');
|
||||||
if (!label) {
|
if (!label) {
|
||||||
@ -40,13 +41,22 @@ $(document).ready(function() {
|
|||||||
select: function(event, ui) {
|
select: function(event, ui) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
search_field.val(ui.item.label);
|
search_field.val(ui.item.label);
|
||||||
|
select_fields.val('');
|
||||||
|
select_fields.attr('disabled', 'disabled');
|
||||||
real_field.empty();
|
real_field.empty();
|
||||||
real_field.append($("<option></option>").attr('value', ui.item.value).text(ui.item.label));
|
real_field.append($("<option></option>").attr('value', ui.item.value).text(ui.item.label));
|
||||||
real_field.change();
|
real_field.change();
|
||||||
// If the field has a parent helper, reset the parent to no selection
|
// Disable parent selection fields
|
||||||
$('select[filter-for="' + real_field.attr('name') + '"]').val('');
|
// $('select[filter-for="' + real_field.attr('name') + '"]').val('');
|
||||||
},
|
},
|
||||||
minLength: 4,
|
minLength: 4,
|
||||||
delay: 500
|
delay: 500
|
||||||
});
|
});
|
||||||
|
|
||||||
|
search_field.change(function() {
|
||||||
|
if (!search_field.val()) {
|
||||||
|
select_fields.removeAttr('disabled');
|
||||||
|
select_fields.val('');
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -10,7 +10,7 @@ urlpatterns = [
|
|||||||
|
|
||||||
# Secret roles
|
# Secret roles
|
||||||
url(r'^secret-roles/$', views.SecretRoleListView.as_view(), name='secretrole_list'),
|
url(r'^secret-roles/$', views.SecretRoleListView.as_view(), name='secretrole_list'),
|
||||||
url(r'^secret-roles/add/$', views.SecretRoleEditView.as_view(), name='secretrole_add'),
|
url(r'^secret-roles/add/$', views.SecretRoleCreateView.as_view(), name='secretrole_add'),
|
||||||
url(r'^secret-roles/delete/$', views.SecretRoleBulkDeleteView.as_view(), name='secretrole_bulk_delete'),
|
url(r'^secret-roles/delete/$', views.SecretRoleBulkDeleteView.as_view(), name='secretrole_bulk_delete'),
|
||||||
url(r'^secret-roles/(?P<slug>[\w-]+)/edit/$', views.SecretRoleEditView.as_view(), name='secretrole_edit'),
|
url(r'^secret-roles/(?P<slug>[\w-]+)/edit/$', views.SecretRoleEditView.as_view(), name='secretrole_edit'),
|
||||||
|
|
||||||
|
@ -40,8 +40,8 @@ class SecretRoleListView(ObjectListView):
|
|||||||
template_name = 'secrets/secretrole_list.html'
|
template_name = 'secrets/secretrole_list.html'
|
||||||
|
|
||||||
|
|
||||||
class SecretRoleEditView(PermissionRequiredMixin, ObjectEditView):
|
class SecretRoleCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'secrets.change_secretrole'
|
permission_required = 'secrets.add_secretrole'
|
||||||
model = SecretRole
|
model = SecretRole
|
||||||
form_class = forms.SecretRoleForm
|
form_class = forms.SecretRoleForm
|
||||||
|
|
||||||
@ -49,6 +49,10 @@ class SecretRoleEditView(PermissionRequiredMixin, ObjectEditView):
|
|||||||
return reverse('secrets:secretrole_list')
|
return reverse('secrets:secretrole_list')
|
||||||
|
|
||||||
|
|
||||||
|
class SecretRoleEditView(SecretRoleCreateView):
|
||||||
|
permission_required = 'secrets.change_secretrole'
|
||||||
|
|
||||||
|
|
||||||
class SecretRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
class SecretRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||||
permission_required = 'secrets.delete_secretrole'
|
permission_required = 'secrets.delete_secretrole'
|
||||||
cls = SecretRole
|
cls = SecretRole
|
||||||
|
13
netbox/templates/dcim/bulk_disconnect.html
Normal file
13
netbox/templates/dcim/bulk_disconnect.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{% extends 'utilities/confirmation_form.html' %}
|
||||||
|
{% load helpers %}
|
||||||
|
|
||||||
|
{% block title %}Disconnect {{ obj_type_plural|bettertitle }}{% endblock %}
|
||||||
|
|
||||||
|
{% block message %}
|
||||||
|
<p>Are you sure you want to disconnect all {{ selected_objects|length }} of these {{ obj_type_plural }} on <strong>{{ device }}</strong>?</p>
|
||||||
|
<ul>
|
||||||
|
{% for obj in selected_objects %}
|
||||||
|
<li>{{ obj }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
@ -424,12 +424,17 @@
|
|||||||
<div class="panel-footer">
|
<div class="panel-footer">
|
||||||
{% if interfaces and perms.dcim.change_interface %}
|
{% if interfaces and perms.dcim.change_interface %}
|
||||||
<button type="submit" name="_edit" formaction="{% url 'dcim:interface_bulk_edit' pk=device.pk %}" class="btn btn-warning btn-xs">
|
<button type="submit" name="_edit" formaction="{% url 'dcim:interface_bulk_edit' pk=device.pk %}" class="btn btn-warning btn-xs">
|
||||||
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Edit selected
|
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Edit
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
|
{% if interfaces and perms.dcim.delete_interfaceconnection %}
|
||||||
|
<button type="submit" name="_disconnect" formaction="{% url 'dcim:interface_bulk_disconnect' pk=device.pk %}" class="btn btn-danger btn-xs">
|
||||||
|
<span class="glyphicon glyphicon-resize-full" aria-hidden="true"></span> Disconnect
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if interfaces and perms.dcim.delete_interface %}
|
{% if interfaces and perms.dcim.delete_interface %}
|
||||||
<button type="submit" name="_delete" formaction="{% url 'dcim:interface_bulk_delete' pk=device.pk %}" class="btn btn-danger btn-xs">
|
<button type="submit" name="_delete" formaction="{% url 'dcim:interface_bulk_delete' pk=device.pk %}" class="btn btn-danger btn-xs">
|
||||||
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete selected
|
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if perms.dcim.add_interface %}
|
{% if perms.dcim.add_interface %}
|
||||||
@ -479,9 +484,14 @@
|
|||||||
</table>
|
</table>
|
||||||
{% if perms.dcim.add_consoleserverport or perms.dcim.delete_consoleserverport %}
|
{% if perms.dcim.add_consoleserverport or perms.dcim.delete_consoleserverport %}
|
||||||
<div class="panel-footer">
|
<div class="panel-footer">
|
||||||
|
{% if cs_ports and perms.dcim.change_consoleport %}
|
||||||
|
<button type="submit" name="_disconnect" formaction="{% url 'dcim:consoleserverport_bulk_disconnect' pk=device.pk %}" class="btn btn-danger btn-xs">
|
||||||
|
<span class="glyphicon glyphicon-resize-full" aria-hidden="true"></span> Disconnect
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
{% if cs_ports and perms.dcim.delete_consoleserverport %}
|
{% if cs_ports and perms.dcim.delete_consoleserverport %}
|
||||||
<button type="submit" class="btn btn-danger btn-xs">
|
<button type="submit" class="btn btn-danger btn-xs">
|
||||||
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete selected
|
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if perms.dcim.add_consoleserverport %}
|
{% if perms.dcim.add_consoleserverport %}
|
||||||
@ -531,9 +541,14 @@
|
|||||||
</table>
|
</table>
|
||||||
{% if perms.dcim.add_poweroutlet or perms.dcim.delete_poweroutlet %}
|
{% if perms.dcim.add_poweroutlet or perms.dcim.delete_poweroutlet %}
|
||||||
<div class="panel-footer">
|
<div class="panel-footer">
|
||||||
|
{% if power_outlets and perms.dcim.change_powerport %}
|
||||||
|
<button type="submit" name="_disconnect" formaction="{% url 'dcim:poweroutlet_bulk_disconnect' pk=device.pk %}" class="btn btn-danger btn-xs">
|
||||||
|
<span class="glyphicon glyphicon-resize-full" aria-hidden="true"></span> Disconnect
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
{% if power_outlets and perms.dcim.delete_poweroutlet %}
|
{% if power_outlets and perms.dcim.delete_poweroutlet %}
|
||||||
<button type="submit" class="btn btn-danger btn-xs">
|
<button type="submit" class="btn btn-danger btn-xs">
|
||||||
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete selected
|
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if perms.dcim.add_poweroutlet %}
|
{% if perms.dcim.add_poweroutlet %}
|
||||||
|
@ -10,13 +10,13 @@ urlpatterns = [
|
|||||||
|
|
||||||
# Tenant groups
|
# Tenant groups
|
||||||
url(r'^tenant-groups/$', views.TenantGroupListView.as_view(), name='tenantgroup_list'),
|
url(r'^tenant-groups/$', views.TenantGroupListView.as_view(), name='tenantgroup_list'),
|
||||||
url(r'^tenant-groups/add/$', views.TenantGroupEditView.as_view(), name='tenantgroup_add'),
|
url(r'^tenant-groups/add/$', views.TenantGroupCreateView.as_view(), name='tenantgroup_add'),
|
||||||
url(r'^tenant-groups/delete/$', views.TenantGroupBulkDeleteView.as_view(), name='tenantgroup_bulk_delete'),
|
url(r'^tenant-groups/delete/$', views.TenantGroupBulkDeleteView.as_view(), name='tenantgroup_bulk_delete'),
|
||||||
url(r'^tenant-groups/(?P<slug>[\w-]+)/edit/$', views.TenantGroupEditView.as_view(), name='tenantgroup_edit'),
|
url(r'^tenant-groups/(?P<slug>[\w-]+)/edit/$', views.TenantGroupEditView.as_view(), name='tenantgroup_edit'),
|
||||||
|
|
||||||
# Tenants
|
# Tenants
|
||||||
url(r'^tenants/$', views.TenantListView.as_view(), name='tenant_list'),
|
url(r'^tenants/$', views.TenantListView.as_view(), name='tenant_list'),
|
||||||
url(r'^tenants/add/$', views.TenantEditView.as_view(), name='tenant_add'),
|
url(r'^tenants/add/$', views.TenantCreateView.as_view(), name='tenant_add'),
|
||||||
url(r'^tenants/import/$', views.TenantBulkImportView.as_view(), name='tenant_import'),
|
url(r'^tenants/import/$', views.TenantBulkImportView.as_view(), name='tenant_import'),
|
||||||
url(r'^tenants/edit/$', views.TenantBulkEditView.as_view(), name='tenant_bulk_edit'),
|
url(r'^tenants/edit/$', views.TenantBulkEditView.as_view(), name='tenant_bulk_edit'),
|
||||||
url(r'^tenants/delete/$', views.TenantBulkDeleteView.as_view(), name='tenant_bulk_delete'),
|
url(r'^tenants/delete/$', views.TenantBulkDeleteView.as_view(), name='tenant_bulk_delete'),
|
||||||
|
@ -26,8 +26,8 @@ class TenantGroupListView(ObjectListView):
|
|||||||
template_name = 'tenancy/tenantgroup_list.html'
|
template_name = 'tenancy/tenantgroup_list.html'
|
||||||
|
|
||||||
|
|
||||||
class TenantGroupEditView(PermissionRequiredMixin, ObjectEditView):
|
class TenantGroupCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'tenancy.change_tenantgroup'
|
permission_required = 'tenancy.add_tenantgroup'
|
||||||
model = TenantGroup
|
model = TenantGroup
|
||||||
form_class = forms.TenantGroupForm
|
form_class = forms.TenantGroupForm
|
||||||
|
|
||||||
@ -35,6 +35,10 @@ class TenantGroupEditView(PermissionRequiredMixin, ObjectEditView):
|
|||||||
return reverse('tenancy:tenantgroup_list')
|
return reverse('tenancy:tenantgroup_list')
|
||||||
|
|
||||||
|
|
||||||
|
class TenantGroupEditView(TenantGroupCreateView):
|
||||||
|
permission_required = 'tenancy.change_tenantgroup'
|
||||||
|
|
||||||
|
|
||||||
class TenantGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
class TenantGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||||
permission_required = 'tenancy.delete_tenantgroup'
|
permission_required = 'tenancy.delete_tenantgroup'
|
||||||
cls = TenantGroup
|
cls = TenantGroup
|
||||||
@ -81,14 +85,18 @@ class TenantView(View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class TenantEditView(PermissionRequiredMixin, ObjectEditView):
|
class TenantCreateView(PermissionRequiredMixin, ObjectEditView):
|
||||||
permission_required = 'tenancy.change_tenant'
|
permission_required = 'tenancy.add_tenant'
|
||||||
model = Tenant
|
model = Tenant
|
||||||
form_class = forms.TenantForm
|
form_class = forms.TenantForm
|
||||||
template_name = 'tenancy/tenant_edit.html'
|
template_name = 'tenancy/tenant_edit.html'
|
||||||
default_return_url = 'tenancy:tenant_list'
|
default_return_url = 'tenancy:tenant_list'
|
||||||
|
|
||||||
|
|
||||||
|
class TenantEditView(TenantCreateView):
|
||||||
|
permission_required = 'tenancy.change_tenant'
|
||||||
|
|
||||||
|
|
||||||
class TenantDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
class TenantDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||||
permission_required = 'tenancy.delete_tenant'
|
permission_required = 'tenancy.delete_tenant'
|
||||||
model = Tenant
|
model = Tenant
|
||||||
|
@ -249,7 +249,7 @@ class CSVDataField(forms.CharField):
|
|||||||
reader = csv.reader(value.splitlines())
|
reader = csv.reader(value.splitlines())
|
||||||
|
|
||||||
# Consume and valdiate the first line of CSV data as column headers
|
# Consume and valdiate the first line of CSV data as column headers
|
||||||
headers = reader.next()
|
headers = next(reader)
|
||||||
for f in self.required_fields:
|
for f in self.required_fields:
|
||||||
if f not in headers:
|
if f not in headers:
|
||||||
raise forms.ValidationError('Required column header "{}" not found.'.format(f))
|
raise forms.ValidationError('Required column header "{}" not found.'.format(f))
|
||||||
@ -472,6 +472,9 @@ class ChainedFieldsMixin(forms.BaseForm):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(ChainedFieldsMixin, self).__init__(*args, **kwargs)
|
super(ChainedFieldsMixin, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
# if self.is_bound:
|
||||||
|
# assert False, self.data
|
||||||
|
|
||||||
for field_name, field in self.fields.items():
|
for field_name, field in self.fields.items():
|
||||||
|
|
||||||
if isinstance(field, ChainedModelChoiceField):
|
if isinstance(field, ChainedModelChoiceField):
|
||||||
|
@ -290,7 +290,7 @@ class ObjectDeleteView(GetReturnURLMixin, View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class BulkAddView(View):
|
class BulkCreateView(View):
|
||||||
"""
|
"""
|
||||||
Create new objects in bulk.
|
Create new objects in bulk.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user