mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-23 04:22:01 -06:00
Added a status field for virtual machines
This commit is contained in:
parent
136d16b7fd
commit
6872ab0e14
@ -51,6 +51,12 @@
|
||||
<td>Name</td>
|
||||
<td>{{ vm.name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Status</td>
|
||||
<td>
|
||||
<span class="label label-{{ vm.get_status_class }}">{{ vm.get_status_display }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Cluster</td>
|
||||
<td>
|
||||
|
@ -6,6 +6,7 @@
|
||||
<div class="panel-heading"><strong>Virtual Machine</strong></div>
|
||||
<div class="panel-body">
|
||||
{% render_field form.name %}
|
||||
{% render_field form.status %}
|
||||
{% render_field form.cluster_group %}
|
||||
{% render_field form.cluster %}
|
||||
{% render_field form.platform %}
|
||||
|
@ -8,6 +8,7 @@ from dcim.models import Interface
|
||||
from extras.api.customfields import CustomFieldModelSerializer
|
||||
from tenancy.api.serializers import NestedTenantSerializer
|
||||
from utilities.api import ChoiceFieldSerializer, ValidatedModelSerializer
|
||||
from virtualization.constants import STATUS_CHOICES
|
||||
from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine
|
||||
|
||||
|
||||
@ -82,6 +83,7 @@ class WritableClusterSerializer(CustomFieldModelSerializer):
|
||||
#
|
||||
|
||||
class VirtualMachineSerializer(CustomFieldModelSerializer):
|
||||
status = ChoiceFieldSerializer(choices=STATUS_CHOICES)
|
||||
cluster = NestedClusterSerializer()
|
||||
tenant = NestedTenantSerializer()
|
||||
platform = NestedPlatformSerializer()
|
||||
@ -89,7 +91,8 @@ class VirtualMachineSerializer(CustomFieldModelSerializer):
|
||||
class Meta:
|
||||
model = VirtualMachine
|
||||
fields = [
|
||||
'id', 'name', 'cluster', 'tenant', 'platform', 'primary_ip4', 'primary_ip6', 'comments', 'custom_fields',
|
||||
'id', 'name', 'status', 'cluster', 'tenant', 'platform', 'primary_ip4', 'primary_ip6', 'comments',
|
||||
'custom_fields',
|
||||
]
|
||||
|
||||
|
||||
@ -106,7 +109,8 @@ class WritableVirtualMachineSerializer(CustomFieldModelSerializer):
|
||||
class Meta:
|
||||
model = VirtualMachine
|
||||
fields = [
|
||||
'id', 'name', 'cluster', 'tenant', 'platform', 'primary_ip4', 'primary_ip6', 'comments', 'custom_fields',
|
||||
'id', 'name', 'status', 'cluster', 'tenant', 'platform', 'primary_ip4', 'primary_ip6', 'comments',
|
||||
'custom_fields',
|
||||
]
|
||||
|
||||
|
||||
|
19
netbox/virtualization/constants.py
Normal file
19
netbox/virtualization/constants.py
Normal file
@ -0,0 +1,19 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
||||
# VirtualMachine statuses (replicated from Device statuses)
|
||||
STATUS_OFFLINE = 0
|
||||
STATUS_ACTIVE = 1
|
||||
STATUS_STAGED = 3
|
||||
STATUS_CHOICES = [
|
||||
[STATUS_ACTIVE, 'Active'],
|
||||
[STATUS_OFFLINE, 'Offline'],
|
||||
[STATUS_STAGED, 'Staged'],
|
||||
]
|
||||
|
||||
# Bootstrap CSS classes for VirtualMachine statuses
|
||||
VM_STATUS_CLASSES = {
|
||||
0: 'warning',
|
||||
1: 'success',
|
||||
3: 'primary',
|
||||
}
|
@ -7,6 +7,7 @@ from dcim.models import Platform
|
||||
from extras.filters import CustomFieldFilterSet
|
||||
from tenancy.models import Tenant
|
||||
from utilities.filters import NullableModelMultipleChoiceFilter, NumericInFilter
|
||||
from .constants import STATUS_CHOICES
|
||||
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
|
||||
|
||||
|
||||
@ -55,6 +56,9 @@ class VirtualMachineFilter(CustomFieldFilterSet):
|
||||
method='search',
|
||||
label='Search',
|
||||
)
|
||||
status = django_filters.MultipleChoiceFilter(
|
||||
choices=STATUS_CHOICES
|
||||
)
|
||||
cluster_group_id = NullableModelMultipleChoiceFilter(
|
||||
name='cluster__group',
|
||||
queryset=ClusterGroup.objects.all(),
|
||||
|
@ -12,10 +12,11 @@ from extras.forms import CustomFieldBulkEditForm, CustomFieldForm, CustomFieldFi
|
||||
from tenancy.forms import TenancyForm
|
||||
from tenancy.models import Tenant
|
||||
from utilities.forms import (
|
||||
APISelect, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ChainedFieldsMixin,
|
||||
ChainedModelChoiceField, ChainedModelMultipleChoiceField, CommentField, ComponentForm, ConfirmationForm,
|
||||
ExpandableNameField, FilterChoiceField, SlugField, SmallTextarea,
|
||||
add_blank_choice, APISelect, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect,
|
||||
ChainedFieldsMixin, ChainedModelChoiceField, ChainedModelMultipleChoiceField, CommentField, ComponentForm,
|
||||
ConfirmationForm, CSVChoiceField, ExpandableNameField, FilterChoiceField, SlugField, SmallTextarea,
|
||||
)
|
||||
from .constants import STATUS_CHOICES
|
||||
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
|
||||
|
||||
|
||||
@ -185,7 +186,9 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
||||
|
||||
class Meta:
|
||||
model = VirtualMachine
|
||||
fields = ['name', 'cluster_group', 'cluster', 'tenant', 'platform', 'vcpus', 'memory', 'disk', 'comments']
|
||||
fields = [
|
||||
'name', 'status', 'cluster_group', 'cluster', 'tenant', 'platform', 'vcpus', 'memory', 'disk', 'comments',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
@ -200,6 +203,11 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
||||
|
||||
|
||||
class VirtualMachineCSVForm(forms.ModelForm):
|
||||
status = CSVChoiceField(
|
||||
choices=STATUS_CHOICES,
|
||||
required=False,
|
||||
help_text='Operational status of device'
|
||||
)
|
||||
cluster = forms.ModelChoiceField(
|
||||
queryset=Cluster.objects.all(),
|
||||
to_field_name='name',
|
||||
@ -229,11 +237,12 @@ class VirtualMachineCSVForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = VirtualMachine
|
||||
fields = ['name', 'cluster', 'tenant', 'platform', 'vcpus', 'memory', 'disk', 'comments']
|
||||
fields = ['name', 'status', 'cluster', 'tenant', 'platform', 'vcpus', 'memory', 'disk', 'comments']
|
||||
|
||||
|
||||
class VirtualMachineBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
||||
pk = forms.ModelMultipleChoiceField(queryset=VirtualMachine.objects.all(), widget=forms.MultipleHiddenInput)
|
||||
status = forms.ChoiceField(choices=add_blank_choice(STATUS_CHOICES), required=False, initial='')
|
||||
cluster = forms.ModelChoiceField(queryset=Cluster.objects.all(), required=False)
|
||||
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), required=False)
|
||||
platform = forms.ModelChoiceField(queryset=Platform.objects.all(), required=False)
|
||||
@ -246,6 +255,13 @@ class VirtualMachineBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
||||
nullable_fields = ['tenant', 'platform', 'vcpus', 'memory', 'disk']
|
||||
|
||||
|
||||
def vm_status_choices():
|
||||
status_counts = {}
|
||||
for status in VirtualMachine.objects.values('status').annotate(count=Count('status')).order_by('status'):
|
||||
status_counts[status['status']] = status['count']
|
||||
return [(s[0], '{} ({})'.format(s[1], status_counts.get(s[0], 0))) for s in STATUS_CHOICES]
|
||||
|
||||
|
||||
class VirtualMachineFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||
model = VirtualMachine
|
||||
q = forms.CharField(required=False, label='Search')
|
||||
@ -258,6 +274,7 @@ class VirtualMachineFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||
queryset=Cluster.objects.annotate(filter_count=Count('virtual_machines')),
|
||||
label='Cluster'
|
||||
)
|
||||
status = forms.MultipleChoiceField(choices=vm_status_choices, required=False)
|
||||
|
||||
|
||||
#
|
||||
|
@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.4 on 2017-09-14 17:49
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('virtualization', '0001_virtualization'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='virtualmachine',
|
||||
name='status',
|
||||
field=models.PositiveSmallIntegerField(choices=[[1, 'Active'], [0, 'Offline'], [3, 'Staged']], default=1, verbose_name='Status'),
|
||||
),
|
||||
]
|
@ -7,6 +7,7 @@ from django.utils.encoding import python_2_unicode_compatible
|
||||
|
||||
from extras.models import CustomFieldModel, CustomFieldValue
|
||||
from utilities.models import CreatedUpdatedModel
|
||||
from .constants import STATUS_ACTIVE, STATUS_CHOICES, VM_STATUS_CLASSES
|
||||
|
||||
|
||||
#
|
||||
@ -139,6 +140,11 @@ class VirtualMachine(CreatedUpdatedModel, CustomFieldModel):
|
||||
max_length=64,
|
||||
unique=True
|
||||
)
|
||||
status = models.PositiveSmallIntegerField(
|
||||
choices=STATUS_CHOICES,
|
||||
default=STATUS_ACTIVE,
|
||||
verbose_name='Status'
|
||||
)
|
||||
primary_ip4 = models.OneToOneField(
|
||||
to='ipam.IPAddress',
|
||||
on_delete=models.SET_NULL,
|
||||
@ -187,3 +193,6 @@ class VirtualMachine(CreatedUpdatedModel, CustomFieldModel):
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('virtualization:virtualmachine', args=[self.pk])
|
||||
|
||||
def get_status_class(self):
|
||||
return VM_STATUS_CLASSES[self.status]
|
||||
|
@ -20,6 +20,10 @@ CLUSTERGROUP_ACTIONS = """
|
||||
{% endif %}
|
||||
"""
|
||||
|
||||
VIRTUALMACHINE_STATUS = """
|
||||
<span class="label label-{{ record.get_status_class }}">{{ record.get_status_display }}</span>
|
||||
"""
|
||||
|
||||
|
||||
#
|
||||
# Cluster types
|
||||
@ -79,12 +83,13 @@ class ClusterTable(BaseTable):
|
||||
class VirtualMachineTable(BaseTable):
|
||||
pk = ToggleColumn()
|
||||
name = tables.LinkColumn()
|
||||
status = tables.TemplateColumn(template_code=VIRTUALMACHINE_STATUS)
|
||||
cluster = tables.LinkColumn('virtualization:cluster', args=[Accessor('cluster.pk')])
|
||||
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')])
|
||||
|
||||
class Meta(BaseTable.Meta):
|
||||
model = VirtualMachine
|
||||
fields = ('pk', 'name', 'cluster', 'tenant', 'vcpus', 'memory', 'disk')
|
||||
fields = ('pk', 'name', 'status', 'cluster', 'tenant', 'vcpus', 'memory', 'disk')
|
||||
|
||||
|
||||
#
|
||||
|
Loading…
Reference in New Issue
Block a user