This commit is contained in:
Alex Gittings 2022-03-11 19:14:03 +00:00
parent 8cd24b1a67
commit 9937efc4ee
7 changed files with 96 additions and 8 deletions

View File

@ -17,6 +17,7 @@ from django.urls import reverse
from utilities.choices import unpack_grouped_choices from utilities.choices import unpack_grouped_choices
from utilities.utils import content_type_identifier, content_type_name from utilities.utils import content_type_identifier, content_type_name
from utilities.validators import EnhancedURLValidator from utilities.validators import EnhancedURLValidator
from virtualization.choices import MemoryUnitChoices
from . import widgets from . import widgets
from .constants import * from .constants import *
from .utils import expand_alphanumeric_pattern, expand_ipaddress_pattern, parse_csv, validate_csv from .utils import expand_alphanumeric_pattern, expand_ipaddress_pattern, parse_csv, validate_csv
@ -41,6 +42,7 @@ __all__ = (
'JSONField', 'JSONField',
'LaxURLField', 'LaxURLField',
'MACAddressField', 'MACAddressField',
'MemoryField',
'SlugField', 'SlugField',
'TagFilterField', 'TagFilterField',
) )
@ -150,6 +152,40 @@ class MACAddressField(forms.Field):
return value return value
class MemoryField(forms.MultiValueField):
widget = widgets.MemoryWidget
empty_values = ['', 'gb', 'mb', 'tb']
def __init__(self, **kwargs):
fields = (
forms.IntegerField(required=False),
forms.CharField(required=False),
)
super(MemoryField, self).__init__(
fields=fields, required=False,
require_all_fields=False, **kwargs
)
def compress(self, data):
if data:
value = data[0]
unit = data[1]
defs = {
'gb': 1024**1,
'tb': 1024**2,
}
if value:
if unit != MemoryUnitChoices.UNIT_MB:
return value * defs[unit]
else:
return value
# #
# Content type fields # Content type fields
# #

View File

@ -6,6 +6,7 @@ from django.conf import settings
from django.contrib.postgres.forms import SimpleArrayField from django.contrib.postgres.forms import SimpleArrayField
from utilities.choices import ColorChoices from utilities.choices import ColorChoices
from virtualization.choices import MemoryUnitChoices
from .utils import add_blank_choice, parse_numeric_range from .utils import add_blank_choice, parse_numeric_range
__all__ = ( __all__ = (
@ -16,6 +17,7 @@ __all__ = (
'ColorSelect', 'ColorSelect',
'DatePicker', 'DatePicker',
'DateTimePicker', 'DateTimePicker',
'MemoryWidget',
'NumericArrayField', 'NumericArrayField',
'SelectSpeedWidget', 'SelectSpeedWidget',
'SelectWithDisabled', 'SelectWithDisabled',
@ -310,3 +312,21 @@ class TimePicker(forms.TextInput):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.attrs['class'] = 'time-picker' self.attrs['class'] = 'time-picker'
self.attrs['placeholder'] = 'hh:mm:ss' self.attrs['placeholder'] = 'hh:mm:ss'
class MemoryWidget(forms.MultiWidget):
"""
Memory Widget.
"""
def __init__(self, attrs=None):
widget = (
forms.NumberInput(),
StaticSelect(choices=MemoryUnitChoices.choices)
)
super(MemoryWidget, self).__init__(widget, attrs)
def decompress(self, value):
if value:
return [value, '']
else:
return ['', '']

View File

@ -84,6 +84,25 @@
</div> </div>
</div> </div>
{% elif field|widget_type == 'memorywidget'%}
<div class="row mb-3">
<label class="col-sm-3 col-form-label text-lg-end{% if field.field.required %} required{% endif %}" for="{{ field.id_for_label }}">
{{ field.label }}
</label>
<div class="col">
<div class="input-group">
{{ field }}
</div>
{% if bulk_nullable %}
<div class="form-check my-1">
<input type="checkbox" class="form-check-input" name="_nullify" value="{{ field.name }}" />
<label class="form-check-label">Set Null</label>
</div>
{% endif %}
</div>
</div>
{% elif field|widget_type == 'selectmultiple' %} {% elif field|widget_type == 'selectmultiple' %}
<div class="row mb-3"> <div class="row mb-3">
<label for="{{ field.id_for_label }}" class="form-label col col-md-3 text-lg-end{% if field.field.required %} required{% endif %}"> <label for="{{ field.id_for_label }}" class="form-label col col-md-3 text-lg-end{% if field.field.required %} required{% endif %}">
@ -93,7 +112,7 @@
{{ field }} {{ field }}
{% if bulk_nullable %} {% if bulk_nullable %}
<div class="form-check my-1"> <div class="form-check my-1">
<input type="checkbox" class="form-check-input" name="_nullify" value="{{ field.name }}" /> <input type="checkbox" class="form-check-input" name="_nullify" value="{{ field.name }}_0" />
<label class="form-check-label">Set Null</label> <label class="form-check-label">Set Null</label>
</div> </div>
{% endif %} {% endif %}

View File

@ -5,6 +5,17 @@ from utilities.choices import ChoiceSet
# VirtualMachines # VirtualMachines
# #
class MemoryUnitChoices(ChoiceSet):
UNIT_MB = 'mb'
UNIT_GB = 'gb'
UNIT_TB = 'tb'
choices = (
(UNIT_MB, 'MB'),
(UNIT_GB, 'GB'),
(UNIT_TB, 'TB'),
)
class VirtualMachineStatusChoices(ChoiceSet): class VirtualMachineStatusChoices(ChoiceSet):
STATUS_OFFLINE = 'offline' STATUS_OFFLINE = 'offline'

View File

@ -8,7 +8,7 @@ from ipam.models import VLAN
from tenancy.models import Tenant from tenancy.models import Tenant
from utilities.forms import ( from utilities.forms import (
add_blank_choice, BulkEditNullBooleanSelect, BulkRenameForm, CommentField, DynamicModelChoiceField, add_blank_choice, BulkEditNullBooleanSelect, BulkRenameForm, CommentField, DynamicModelChoiceField,
DynamicModelMultipleChoiceField, SmallTextarea, StaticSelect DynamicModelMultipleChoiceField, SmallTextarea, StaticSelect, MemoryField
) )
from virtualization.choices import * from virtualization.choices import *
from virtualization.models import * from virtualization.models import *
@ -131,10 +131,10 @@ class VirtualMachineBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm
required=False, required=False,
label='vCPUs' label='vCPUs'
) )
memory = forms.IntegerField( memory = MemoryField()
required=False, # memory = forms.IntegerField(
label='Memory (MB)' # required=False
) # )
disk = forms.IntegerField( disk = forms.IntegerField(
required=False, required=False,
label='Disk (GB)' label='Disk (GB)'

View File

@ -11,7 +11,7 @@ from ipam.models import IPAddress, VLAN, VLANGroup
from tenancy.forms import TenancyForm from tenancy.forms import TenancyForm
from utilities.forms import ( from utilities.forms import (
BootstrapMixin, CommentField, ConfirmationForm, DynamicModelChoiceField, DynamicModelMultipleChoiceField, BootstrapMixin, CommentField, ConfirmationForm, DynamicModelChoiceField, DynamicModelMultipleChoiceField,
JSONField, SlugField, StaticSelect, JSONField, SlugField, StaticSelect, MemoryField
) )
from virtualization.models import * from virtualization.models import *
@ -205,6 +205,7 @@ class VirtualMachineForm(TenancyForm, CustomFieldModelForm):
queryset=Tag.objects.all(), queryset=Tag.objects.all(),
required=False required=False
) )
memory = MemoryField()
class Meta: class Meta:
model = VirtualMachine model = VirtualMachine

View File

@ -192,7 +192,8 @@ class VirtualMachineTestCase(ViewTestCases.PrimaryObjectViewTestCase):
'primary_ip4': None, 'primary_ip4': None,
'primary_ip6': None, 'primary_ip6': None,
'vcpus': 4, 'vcpus': 4,
'memory': 32768, 'memory_0': 32768,
'memory_1': MemoryUnitChoices.UNIT_MB,
'disk': 4000, 'disk': 4000,
'comments': 'Some comments', 'comments': 'Some comments',
'tags': [t.pk for t in tags], 'tags': [t.pk for t in tags],