mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-16 20:48:17 -06:00
Closes #8437
This commit is contained in:
parent
8cd24b1a67
commit
9937efc4ee
@ -17,6 +17,7 @@ from django.urls import reverse
|
||||
from utilities.choices import unpack_grouped_choices
|
||||
from utilities.utils import content_type_identifier, content_type_name
|
||||
from utilities.validators import EnhancedURLValidator
|
||||
from virtualization.choices import MemoryUnitChoices
|
||||
from . import widgets
|
||||
from .constants import *
|
||||
from .utils import expand_alphanumeric_pattern, expand_ipaddress_pattern, parse_csv, validate_csv
|
||||
@ -41,6 +42,7 @@ __all__ = (
|
||||
'JSONField',
|
||||
'LaxURLField',
|
||||
'MACAddressField',
|
||||
'MemoryField',
|
||||
'SlugField',
|
||||
'TagFilterField',
|
||||
)
|
||||
@ -150,6 +152,40 @@ class MACAddressField(forms.Field):
|
||||
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
|
||||
#
|
||||
|
@ -6,6 +6,7 @@ from django.conf import settings
|
||||
from django.contrib.postgres.forms import SimpleArrayField
|
||||
|
||||
from utilities.choices import ColorChoices
|
||||
from virtualization.choices import MemoryUnitChoices
|
||||
from .utils import add_blank_choice, parse_numeric_range
|
||||
|
||||
__all__ = (
|
||||
@ -16,6 +17,7 @@ __all__ = (
|
||||
'ColorSelect',
|
||||
'DatePicker',
|
||||
'DateTimePicker',
|
||||
'MemoryWidget',
|
||||
'NumericArrayField',
|
||||
'SelectSpeedWidget',
|
||||
'SelectWithDisabled',
|
||||
@ -310,3 +312,21 @@ class TimePicker(forms.TextInput):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.attrs['class'] = 'time-picker'
|
||||
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 ['', '']
|
||||
|
@ -84,6 +84,25 @@
|
||||
</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' %}
|
||||
<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 %}">
|
||||
@ -93,7 +112,7 @@
|
||||
{{ field }}
|
||||
{% if bulk_nullable %}
|
||||
<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>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
@ -5,6 +5,17 @@ from utilities.choices import ChoiceSet
|
||||
# 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):
|
||||
|
||||
STATUS_OFFLINE = 'offline'
|
||||
|
@ -8,7 +8,7 @@ from ipam.models import VLAN
|
||||
from tenancy.models import Tenant
|
||||
from utilities.forms import (
|
||||
add_blank_choice, BulkEditNullBooleanSelect, BulkRenameForm, CommentField, DynamicModelChoiceField,
|
||||
DynamicModelMultipleChoiceField, SmallTextarea, StaticSelect
|
||||
DynamicModelMultipleChoiceField, SmallTextarea, StaticSelect, MemoryField
|
||||
)
|
||||
from virtualization.choices import *
|
||||
from virtualization.models import *
|
||||
@ -131,10 +131,10 @@ class VirtualMachineBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm
|
||||
required=False,
|
||||
label='vCPUs'
|
||||
)
|
||||
memory = forms.IntegerField(
|
||||
required=False,
|
||||
label='Memory (MB)'
|
||||
)
|
||||
memory = MemoryField()
|
||||
# memory = forms.IntegerField(
|
||||
# required=False
|
||||
# )
|
||||
disk = forms.IntegerField(
|
||||
required=False,
|
||||
label='Disk (GB)'
|
||||
|
@ -11,7 +11,7 @@ from ipam.models import IPAddress, VLAN, VLANGroup
|
||||
from tenancy.forms import TenancyForm
|
||||
from utilities.forms import (
|
||||
BootstrapMixin, CommentField, ConfirmationForm, DynamicModelChoiceField, DynamicModelMultipleChoiceField,
|
||||
JSONField, SlugField, StaticSelect,
|
||||
JSONField, SlugField, StaticSelect, MemoryField
|
||||
)
|
||||
from virtualization.models import *
|
||||
|
||||
@ -205,6 +205,7 @@ class VirtualMachineForm(TenancyForm, CustomFieldModelForm):
|
||||
queryset=Tag.objects.all(),
|
||||
required=False
|
||||
)
|
||||
memory = MemoryField()
|
||||
|
||||
class Meta:
|
||||
model = VirtualMachine
|
||||
|
@ -192,7 +192,8 @@ class VirtualMachineTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
||||
'primary_ip4': None,
|
||||
'primary_ip6': None,
|
||||
'vcpus': 4,
|
||||
'memory': 32768,
|
||||
'memory_0': 32768,
|
||||
'memory_1': MemoryUnitChoices.UNIT_MB,
|
||||
'disk': 4000,
|
||||
'comments': 'Some comments',
|
||||
'tags': [t.pk for t in tags],
|
||||
|
Loading…
Reference in New Issue
Block a user