mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-26 10:28:37 -06:00
Show virtual machines on Cluster page
This commit is contained in:
parent
e7f64334c0
commit
cfb81a8a01
@ -151,8 +151,25 @@
|
|||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</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 %}
|
{% plugin_right_page cluster %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
|
@ -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 %}
|
@ -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
|
# Virtual Machines
|
||||||
#
|
#
|
||||||
|
@ -38,6 +38,7 @@ urlpatterns = [
|
|||||||
path('clusters/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='cluster_changelog', kwargs={'model': Cluster}),
|
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/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>/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
|
# Virtual machines
|
||||||
path('virtual-machines/', views.VirtualMachineListView.as_view(), name='virtualmachine_list'),
|
path('virtual-machines/', views.VirtualMachineListView.as_view(), name='virtualmachine_list'),
|
||||||
|
@ -14,6 +14,7 @@ from utilities.views import (
|
|||||||
BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, BulkRenameView, ComponentCreateView,
|
BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, BulkRenameView, ComponentCreateView,
|
||||||
ObjectView, ObjectDeleteView, ObjectEditView, ObjectListView,
|
ObjectView, ObjectDeleteView, ObjectEditView, ObjectListView,
|
||||||
)
|
)
|
||||||
|
from virtualization.tables import VirtualMachineTable
|
||||||
from . import filters, forms, tables
|
from . import filters, forms, tables
|
||||||
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
|
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
|
||||||
|
|
||||||
@ -103,11 +104,18 @@ class ClusterView(ObjectView):
|
|||||||
queryset = Cluster.objects.all()
|
queryset = Cluster.objects.all()
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
virtual_machines = VirtualMachine.objects.restrict(request.user)
|
||||||
|
|
||||||
self.queryset = self.queryset.prefetch_related(
|
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)
|
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(
|
devices = Device.objects.restrict(request.user, 'view').filter(cluster=cluster).prefetch_related(
|
||||||
'site', 'rack', 'tenant', 'device_type__manufacturer'
|
'site', 'rack', 'tenant', 'device_type__manufacturer'
|
||||||
)
|
)
|
||||||
@ -118,6 +126,7 @@ class ClusterView(ObjectView):
|
|||||||
return render(request, 'virtualization/cluster.html', {
|
return render(request, 'virtualization/cluster.html', {
|
||||||
'cluster': cluster,
|
'cluster': cluster,
|
||||||
'device_table': device_table,
|
'device_table': device_table,
|
||||||
|
'virtual_machine_table': virtual_machine_table,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@ -232,6 +241,47 @@ class ClusterRemoveDevicesView(ObjectEditView):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
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
|
# Virtual machines
|
||||||
#
|
#
|
||||||
|
Loading…
Reference in New Issue
Block a user