Skip to content

Commit

Permalink
Show virtual machines on Cluster page
Browse files Browse the repository at this point in the history
  • Loading branch information
furlongm committed Dec 8, 2020
1 parent e7f6433 commit cfb81a8
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 2 deletions.
19 changes: 18 additions & 1 deletion netbox/templates/virtualization/cluster.html
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,25 @@ <h1>{% block title %}{{ cluster }}{% endblock %}</h1>
</form>
{% endif %}
</div>
<div class="panel panel-default">
<div class="panel-heading">
<strong>Virtual Machines</strong>
</div>
{% include 'responsive_table.html' with table=virtual_machine_table %}
{% if perms.virtualization.change_cluster %}
<div class="panel-footer noprint">
<div class="pull-right">
<a href="{% url 'virtualization:cluster_add_virtualmachines' pk=cluster.pk %}?site={{ cluster.site.pk }}" class="btn btn-primary btn-xs">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
Add virtual machines
</a>
</div>
<div class="clearfix"></div>
</div>
{% endif %}
</div>
{% plugin_right_page cluster %}
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
Expand Down
37 changes: 37 additions & 0 deletions netbox/templates/virtualization/cluster_add_virtualmachines.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{% extends 'base.html' %}
{% load static %}
{% load form_helpers %}

{% block content %}
<form action="." method="post" class="form form-horizontal">
{% csrf_token %}
{% for field in form.hidden_fields %}
{{ field }}
{% endfor %}
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h3>{% block title %}Add Virtual Machines to Cluster {{ cluster }}{% endblock %}</h3>
{% if form.non_field_errors %}
<div class="panel panel-danger">
<div class="panel-heading"><strong>Errors</strong></div>
<div class="panel-body">
{{ form.non_field_errors }}
</div>
</div>
{% endif %}
<div class="panel panel-default">
<div class="panel-heading"><strong>Virtual Machine Selection</strong></div>
<div class="panel-body">
{% render_form form %}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-md-offset-3 text-right noprint">
<button type="submit" name="_add" class="btn btn-primary">Add Virtual Machines</button>
<a href="{{ return_url }}" class="btn btn-default">Cancel</a>
</div>
</div>
</form>
{% endblock %}
22 changes: 22 additions & 0 deletions netbox/virtualization/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,28 @@ class ClusterRemoveDevicesForm(ConfirmationForm):
)


class ClusterAddVirtualMachinesForm(BootstrapMixin, forms.Form):
virtualmachines = DynamicModelMultipleChoiceField(
queryset=VirtualMachine.objects.all(),
)

class Meta:
fields = [
'virtualmachines',
]

def __init__(self, cluster, *args, **kwargs):

self.cluster = cluster

super().__init__(*args, **kwargs)

self.fields['virtualmachines'].choices = []

def clean(self):
super().clean()


#
# Virtual Machines
#
Expand Down
1 change: 1 addition & 0 deletions netbox/virtualization/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
path('clusters/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='cluster_changelog', kwargs={'model': Cluster}),
path('clusters/<int:pk>/devices/add/', views.ClusterAddDevicesView.as_view(), name='cluster_add_devices'),
path('clusters/<int:pk>/devices/remove/', views.ClusterRemoveDevicesView.as_view(), name='cluster_remove_devices'),
path('clusters/<int:pk>/virtual-machines/add/', views.ClusterAddVirtualMachinesView.as_view(), name='cluster_add_virtualmachines'),

# Virtual machines
path('virtual-machines/', views.VirtualMachineListView.as_view(), name='virtualmachine_list'),
Expand Down
52 changes: 51 additions & 1 deletion netbox/virtualization/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, BulkRenameView, ComponentCreateView,
ObjectView, ObjectDeleteView, ObjectEditView, ObjectListView,
)
from virtualization.tables import VirtualMachineTable
from . import filters, forms, tables
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface

Expand Down Expand Up @@ -103,11 +104,18 @@ class ClusterView(ObjectView):
queryset = Cluster.objects.all()

def get(self, request, pk):
virtual_machines = VirtualMachine.objects.restrict(request.user)

self.queryset = self.queryset.prefetch_related(
Prefetch('virtual_machines', queryset=VirtualMachine.objects.restrict(request.user))
Prefetch('virtual_machines', queryset=virtual_machines)
)

cluster = get_object_or_404(self.queryset, pk=pk)

virtual_machine_table = VirtualMachineTable(list(virtual_machines.filter(cluster=cluster)), orderable=False)
if request.user.has_perm('virtualization.change_cluster'):
virtual_machine_table.columns.show('pk')

devices = Device.objects.restrict(request.user, 'view').filter(cluster=cluster).prefetch_related(
'site', 'rack', 'tenant', 'device_type__manufacturer'
)
Expand All @@ -118,6 +126,7 @@ def get(self, request, pk):
return render(request, 'virtualization/cluster.html', {
'cluster': cluster,
'device_table': device_table,
'virtual_machine_table': virtual_machine_table,
})


Expand Down Expand Up @@ -232,6 +241,47 @@ def post(self, request, pk):
})


class ClusterAddVirtualMachinesView(ObjectEditView):
queryset = Cluster.objects.all()
form = forms.ClusterAddVirtualMachinesForm
template_name = 'virtualization/cluster_add_virtualmachines.html'

def get(self, request, pk):
cluster = get_object_or_404(self.queryset, pk=pk)
form = self.form(cluster, initial=request.GET)

return render(request, self.template_name, {
'cluster': cluster,
'form': form,
'return_url': reverse('virtualization:cluster', kwargs={'pk': pk}),
})

def post(self, request, pk):
cluster = get_object_or_404(self.queryset, pk=pk)
form = self.form(cluster, request.POST)

if form.is_valid():

virtualmachine_pks = form.cleaned_data['virtualmachines']
with transaction.atomic():

# Assign the selected VirtualMachines to the Cluster
for virtualmachine in VirtualMachine.objects.filter(pk__in=virtualmachine_pks):
virtualmachine.cluster = cluster
virtualmachine.save()

messages.success(request, "Added {} virtual machines to cluster {}".format(
len(virtualmachine_pks), cluster
))
return redirect(cluster.get_absolute_url())

return render(request, self.template_name, {
'cluster': cluster,
'form': form,
'return_url': cluster.get_absolute_url(),
})


#
# Virtual machines
#
Expand Down

0 comments on commit cfb81a8

Please sign in to comment.