From d06813f52823459e57453b9ce593bf6c60f0e57b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 4 Aug 2017 17:02:52 -0400 Subject: [PATCH] Initial work on virtualization support (#142) --- netbox/dcim/views.py | 90 +------ netbox/netbox/settings.py | 1 + netbox/netbox/urls.py | 1 + netbox/templates/_base.html | 28 +++ netbox/templates/virtualization/cluster.html | 92 +++++++ .../virtualization/cluster_list.html | 26 ++ .../virtualization/clustergroup_list.html | 19 ++ .../virtualization/clustertype_list.html | 19 ++ .../virtualization/virtualmachine.html | 77 ++++++ .../virtualization/virtualmachine_edit.html | 39 +++ .../virtualization/virtualmachine_list.html | 26 ++ netbox/utilities/views.py | 87 +++++++ netbox/virtualization/__init__.py | 0 netbox/virtualization/apps.py | 7 + netbox/virtualization/forms.py | 101 ++++++++ .../virtualization/migrations/0001_initial.py | 107 ++++++++ netbox/virtualization/migrations/__init__.py | 0 netbox/virtualization/models.py | 218 +++++++++++++++++ netbox/virtualization/tables.py | 84 +++++++ netbox/virtualization/urls.py | 41 ++++ netbox/virtualization/views.py | 229 ++++++++++++++++++ 21 files changed, 1210 insertions(+), 82 deletions(-) create mode 100644 netbox/templates/virtualization/cluster.html create mode 100644 netbox/templates/virtualization/cluster_list.html create mode 100644 netbox/templates/virtualization/clustergroup_list.html create mode 100644 netbox/templates/virtualization/clustertype_list.html create mode 100644 netbox/templates/virtualization/virtualmachine.html create mode 100644 netbox/templates/virtualization/virtualmachine_edit.html create mode 100644 netbox/templates/virtualization/virtualmachine_list.html create mode 100644 netbox/virtualization/__init__.py create mode 100644 netbox/virtualization/apps.py create mode 100644 netbox/virtualization/forms.py create mode 100644 netbox/virtualization/migrations/0001_initial.py create mode 100644 netbox/virtualization/migrations/__init__.py create mode 100644 netbox/virtualization/models.py create mode 100644 netbox/virtualization/tables.py create mode 100644 netbox/virtualization/urls.py create mode 100644 netbox/virtualization/views.py diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 78881c20097..552a6a53462 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -23,7 +23,8 @@ from utilities.forms import ConfirmationForm from utilities.paginator import EnhancedPaginator from utilities.views import ( - BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView, + BulkDeleteView, BulkEditView, BulkImportView, ComponentCreateView, ComponentDeleteView, ComponentEditView, + ObjectDeleteView, ObjectEditView, ObjectListView, ) from . import filters, forms, tables from .models import ( @@ -60,87 +61,6 @@ def expand_pattern(string): yield "{0}{1}".format(lead, i) -class ComponentCreateView(View): - parent_model = None - parent_field = None - model = None - form = None - model_form = None - - def get(self, request, pk): - - parent = get_object_or_404(self.parent_model, pk=pk) - form = self.form(parent, initial=request.GET) - - return render(request, 'dcim/device_component_add.html', { - 'parent': parent, - 'component_type': self.model._meta.verbose_name, - 'form': form, - 'return_url': parent.get_absolute_url(), - }) - - def post(self, request, pk): - - parent = get_object_or_404(self.parent_model, pk=pk) - - form = self.form(parent, request.POST) - if form.is_valid(): - - new_components = [] - data = deepcopy(form.cleaned_data) - - for name in form.cleaned_data['name_pattern']: - component_data = { - self.parent_field: parent.pk, - 'name': name, - } - # Replace objects with their primary key to keep component_form.clean() happy - for k, v in data.items(): - if hasattr(v, 'pk'): - component_data[k] = v.pk - else: - component_data[k] = v - component_form = self.model_form(component_data) - if component_form.is_valid(): - new_components.append(component_form.save(commit=False)) - else: - for field, errors in component_form.errors.as_data().items(): - # Assign errors on the child form's name field to name_pattern on the parent form - if field == 'name': - field = 'name_pattern' - for e in errors: - form.add_error(field, '{}: {}'.format(name, ', '.join(e))) - - if not form.errors: - self.model.objects.bulk_create(new_components) - messages.success(request, "Added {} {} to {}.".format( - len(new_components), self.model._meta.verbose_name_plural, parent - )) - if '_addanother' in request.POST: - return redirect(request.path) - else: - return redirect(parent.get_absolute_url()) - - return render(request, 'dcim/device_component_add.html', { - 'parent': parent, - 'component_type': self.model._meta.verbose_name, - 'form': form, - 'return_url': parent.get_absolute_url(), - }) - - -class ComponentEditView(ObjectEditView): - - def get_return_url(self, request, obj): - return obj.device.get_absolute_url() - - -class ComponentDeleteView(ObjectDeleteView): - - def get_return_url(self, request, obj): - return obj.device.get_absolute_url() - - class BulkDisconnectView(View): """ An extendable view for disconnection console/power/interface components in bulk. @@ -662,6 +582,7 @@ class ConsolePortTemplateCreateView(PermissionRequiredMixin, ComponentCreateView model = ConsolePortTemplate form = forms.ConsolePortTemplateCreateForm model_form = forms.ConsolePortTemplateForm + template_name = 'dcim/device_component_add.html' class ConsolePortTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): @@ -680,6 +601,7 @@ class ConsoleServerPortTemplateCreateView(PermissionRequiredMixin, ComponentCrea model = ConsoleServerPortTemplate form = forms.ConsoleServerPortTemplateCreateForm model_form = forms.ConsoleServerPortTemplateForm + template_name = 'dcim/device_component_add.html' class ConsoleServerPortTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): @@ -696,6 +618,7 @@ class PowerPortTemplateCreateView(PermissionRequiredMixin, ComponentCreateView): model = PowerPortTemplate form = forms.PowerPortTemplateCreateForm model_form = forms.PowerPortTemplateForm + template_name = 'dcim/device_component_add.html' class PowerPortTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): @@ -712,6 +635,7 @@ class PowerOutletTemplateCreateView(PermissionRequiredMixin, ComponentCreateView model = PowerOutletTemplate form = forms.PowerOutletTemplateCreateForm model_form = forms.PowerOutletTemplateForm + template_name = 'dcim/device_component_add.html' class PowerOutletTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): @@ -728,6 +652,7 @@ class InterfaceTemplateCreateView(PermissionRequiredMixin, ComponentCreateView): model = InterfaceTemplate form = forms.InterfaceTemplateCreateForm model_form = forms.InterfaceTemplateForm + template_name = 'dcim/device_component_add.html' class InterfaceTemplateBulkEditView(PermissionRequiredMixin, BulkEditView): @@ -752,6 +677,7 @@ class DeviceBayTemplateCreateView(PermissionRequiredMixin, ComponentCreateView): model = DeviceBayTemplate form = forms.DeviceBayTemplateCreateForm model_form = forms.DeviceBayTemplateForm + template_name = 'dcim/device_component_add.html' class DeviceBayTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 00acc3e67d7..0fcb02a3fb6 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -145,6 +145,7 @@ 'tenancy', 'users', 'utilities', + 'virtualization', ) # Middleware diff --git a/netbox/netbox/urls.py b/netbox/netbox/urls.py index ddddf27a28b..260d389cfb6 100644 --- a/netbox/netbox/urls.py +++ b/netbox/netbox/urls.py @@ -32,6 +32,7 @@ url(r'^secrets/', include('secrets.urls')), url(r'^tenancy/', include('tenancy.urls')), url(r'^user/', include('users.urls')), + url(r'^virtualization/', include('virtualization.urls')), # API url(r'^api/$', APIRootView.as_view(), name='api-root'), diff --git a/netbox/templates/_base.html b/netbox/templates/_base.html index c56a95abeb7..4450e4213c3 100644 --- a/netbox/templates/_base.html +++ b/netbox/templates/_base.html @@ -202,6 +202,34 @@ {% endif %} +