Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show virtual machines on Cluster page #5426

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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