class MultiNetworkIPForm(SerializerForm): """ Delete multiple network IP addresses at once. """ _api_call = net_ip_list template = 'gui/dc/network_ips_form.html' ips = ArrayField(required=True, widget=forms.HiddenInput()) def __init__(self, request, net, ip, *args, **kwargs): self.net = net super(MultiNetworkIPForm, self).__init__(request, ip, *args, **kwargs) @staticmethod def api_call_args(net_name): return net_name, def get_action_message(self): assert self.action == 'delete', 'Unknown action' count = len(self.cleaned_data.get('ips', ())) return ungettext_lazy( 'IP address was successfully deleted', '%(count)d IP addresses were successfully deleted', count) % { 'count': count }
class NodeStatusForm(SerializerForm): """ Update compute node settings. """ _api_call = node_define _node_hostname = None _new_status = None hostnames = ArrayField(required=True, widget=forms.HiddenInput(attrs={'class': 'hide'})) status = forms.TypedChoiceField(label=_('Status'), choices=Node.STATUS, coerce=int, widget=forms.Select(attrs={'class': 'narrow input-select2'})) def _add_error(self, field_name, error): if self._node_hostname: if isinstance(error, (list, tuple)): error = ['%s: %s' % (self._node_hostname, err) for err in error] else: error = '%s: %s' % (self._node_hostname, error) return super(NodeStatusForm, self)._add_error(field_name, error) def _final_data(self, data=None): # Save target status from cleaned form data. # The save() method may remove the cleaned_data['status'] if there is and API error. if self._new_status is None: self._new_status = data['status'] return {'status': self._new_status} def call_node_define(self, hostname): # Save current node hostname for __add_error() self._node_hostname = hostname return self.save(action='update', args=(hostname,))
class MultiDnsRecordForm(SerializerForm): """ Delete multiple DNS records at once. """ _api_call = dns_record_list template = 'gui/dc/domain_records_form.html' records = ArrayField(required=True, widget=forms.HiddenInput()) def __init__(self, request, domain, record, *args, **kwargs): self.domain = domain super(MultiDnsRecordForm, self).__init__(request, record, *args, **kwargs) @staticmethod def api_call_args(domain_name): return domain_name,
class NodeUpdateForm(UpdateForm): """ Update the system on compute nodes to a new version. """ _api_call = system_node_update _node_hostname = None hostnames = ArrayField(required=True, widget=forms.HiddenInput(attrs={'class': 'hide'})) def _add_error(self, field_name, error): if self._node_hostname: if isinstance(error, (list, tuple)): error = [ '%s: %s' % (self._node_hostname, err) for err in error ] else: error = '%s: %s' % (self._node_hostname, error) return super(NodeUpdateForm, self)._add_error(field_name, error) def call_system_node_update(self, hostname): # Save current node hostname for __add_error() self._node_hostname = hostname return self.save(action='update', args=(hostname, ))
class AdminServerSettingsForm(ServerSettingsForm): """ Copy of vm_define serializer (api). """ admin = True _api_call = vm_define tags = TagField(label=_('Tags'), required=False, widget=TagWidget(attrs={'class': 'tags-select2 narrow'}), help_text=_('The tag will be created in case it does not exist.')) node = forms.TypedChoiceField(label=_('Node'), required=False, coerce=str, empty_value=None, widget=forms.Select(attrs={'class': 'narrow input-select2'})) template = forms.TypedChoiceField(label=_('Template'), required=False, coerce=str, empty_value=None, help_text=_('Setting template can modify lots of server attributes, ' 'e.g. disks, nics.'), widget=DataSelect(attrs={'class': 'narrow input-select2'})) ostype = forms.TypedChoiceField(label=_('OS Type'), choices=Vm.OSTYPE, required=True, coerce=int, widget=forms.Select(attrs={'class': 'input-select2 narrow', 'required': 'required'})) vcpus = forms.IntegerField(label=_('VCPUs'), max_value=64, min_value=1, required=True, widget=NumberInput(attrs={'class': 'input-transparent narrow', 'required': 'required'})) # noinspection SpellCheckingInspection ram = forms.IntegerField(label=_('RAM'), max_value=524288, min_value=32, required=True, widget=forms.TextInput(attrs={'class': 'input-transparent narrow input-mbytes', 'required': 'required', 'pattern': '[0-9\.]+[BKMGTPEbkmgtpe]?'})) monitored = forms.BooleanField(label=_('Monitored?'), required=False, widget=forms.CheckboxInput(attrs={'class': 'normal-check'})) installed = forms.BooleanField(label=_('Installed?'), required=False, help_text=_('This field is used for informational purposes only.'), widget=forms.CheckboxInput(attrs={'class': 'normal-check'})) snapshot_limit_manual = forms.IntegerField(label=_('Snapshot count limit'), required=False, widget=NumberInput(attrs={'class': 'input-transparent narrow'}), help_text=_('Maximum number of manual server snapshots.')) snapshot_size_limit = forms.IntegerField(label=_('Snapshot size limit'), required=False, widget=NumberInput(attrs={'class': 'input-transparent narrow'}), help_text=_('Maximum size of all server snapshots.')) cpu_shares = forms.IntegerField(label=_('CPU Shares'), max_value=1048576, min_value=0, required=True, widget=NumberInput(attrs={'class': 'input-transparent narrow', 'required': 'required'})) # cpu_cap = forms.IntegerField(label=_('CPU Capping'), max_value=6400, min_value=0, required=False, # widget=NumberInput(attrs={'class': 'input-transparent narrow'})) zfs_io_priority = forms.IntegerField(label=_('IO Priority'), max_value=1024, min_value=0, required=True, widget=NumberInput(attrs={'class': 'input-transparent narrow', 'required': 'required'})) zpool = forms.ChoiceField(label=_('Storage'), required=False, widget=forms.Select(attrs={'class': 'narrow input-select2'})) owner = forms.ChoiceField(label=_('Owner'), required=False, widget=forms.Select(attrs={'class': 'narrow input-select2'})) monitoring_templates = ArrayField(label=_('Monitoring templates'), required=False, help_text=_('Comma-separated list of custom monitoring templates.'), widget=ArrayWidget(attrs={'class': 'input-transparent narrow'})) monitoring_hostgroups = ArrayField(label=_('Monitoring hostgroups'), required=False, help_text=_('Comma-separated list of custom monitoring hostgroups.'), widget=ArrayWidget(attrs={'class': 'input-transparent narrow'})) mdata = DictField(label=_('Metadata'), required=False, help_text=_('key=value string pairs.'), widget=DictWidget(attrs={ 'class': 'input-transparent small', 'rows': 5, 'data-raw_input_enabled': 'true', })) def __init__(self, request, vm, *args, **kwargs): super(AdminServerSettingsForm, self).__init__(request, vm, *args, **kwargs) self.is_kvm = is_kvm(vm, self.data, prefix='opt-') # Set choices self.vm_nodes = get_nodes(request, is_compute=True) # TODO: node.color self.fields['node'].choices = [('', _('(auto)'))] + [(i.hostname, i.hostname) for i in self.vm_nodes] self.fields['owner'].choices = get_owners(request).values_list('username', 'username') self.fields['zpool'].choices = get_zpools(request).values_list('zpool', 'storage__alias').distinct() if not request.user.is_staff: self.fields['cpu_shares'].widget.attrs['disabled'] = 'disabled' self.fields['cpu_shares'].widget.attrs['class'] += ' uneditable-input' self.fields['zfs_io_priority'].widget.attrs['disabled'] = 'disabled' self.fields['zfs_io_priority'].widget.attrs['class'] += ' uneditable-input' if vm: empty_template_data = {} self.fields['ostype'].widget.attrs['disabled'] = 'disabled' if vm.is_deployed(): self.fields['node'].widget.attrs['class'] += ' disable_created2' self.fields['zpool'].widget.attrs['class'] += ' disable_created2' else: empty_template_data = self.initial # Remove Linux Zone support (lx brand) ostype = [i for i in Vm.OSTYPE if i[0] != Vm.LINUX_ZONE] # Disable zone support _only_ when adding new VM (zone must be available in edit mode) - Issue #chili-461 if not request.dc.settings.VMS_ZONE_ENABLED: # Remove SunOS Zone support ostype = [i for i in ostype if i[0] != Vm.SUNOS_ZONE] self.fields['ostype'].choices = ostype empty_template = AttrDict({'alias': _('(none)'), 'desc': '', 'web_data': empty_template_data}) self.fields['template'].choices = [('', empty_template)] + [(i.name, i) for i in get_templates(request)] def _initial_data(self, request, vm): fix = super(AdminServerSettingsForm, self)._initial_data(request, vm) ret = get_vm_define(request, vm) # We need string representation of tags, but vm_define returns a list if 'tags' in ret: ret['tags'] = tags_to_string(ret['tags']) # Some serializer data need to be replaced by data expected by the parent form ret.update(fix) return ret
class AdminNetworkForm(SerializerForm): """ Create Subnet by calling net_manage. """ _api_call = net_manage network = None netmask = None dc_bound = forms.BooleanField( label=_('DC-bound?'), required=False, widget=forms.CheckboxInput(attrs={'class': 'normal-check'})) name = forms.CharField( label=_('Name'), max_length=32, required=True, widget=forms.TextInput( attrs={ 'class': 'input-transparent narrow disable_created', 'required': 'required', 'pattern': '[A-Za-z0-9\._-]+' })) alias = forms.CharField(label=_('Alias'), required=True, max_length=32, widget=forms.TextInput(attrs=TEXT_INPUT_ATTRS)) owner = forms.ChoiceField(label=_('Owner'), required=False, widget=forms.Select(attrs=SELECT_ATTRS)) access = forms.TypedChoiceField(label=_('Access'), required=False, coerce=int, choices=Subnet.ACCESS, widget=forms.Select(attrs=SELECT_ATTRS)) desc = forms.CharField(label=_('Description'), max_length=128, required=False, widget=forms.TextInput(attrs={ 'class': 'input-transparent wide', 'required': '' })) ip_network = forms.CharField( label=_('Network/Netmask'), required=True, max_length=34, help_text=_('IPv4 network address with netmask in CIDR format.'), widget=forms.TextInput( attrs=TEXT_INPUT_ATTRS)) # IP address validated in serializer gateway = forms.CharField( label=_('Gateway'), required=False, max_length=32, help_text=_('IPv4 gateway in quad-dotted format.'), widget=forms.TextInput( attrs=TEXT_INPUT_ATTRS)) # IP address is validated in serializer vlan_id = forms.IntegerField( label=_('VLAN ID'), required=True, widget=forms.TextInput(attrs=TEXT_INPUT_ATTRS), help_text=_('802.1Q virtual LAN ID (0 - 4096, 0 = none).')) nic_tag = forms.ChoiceField( label=_('NIC Tag'), required=True, help_text=_('NIC tag or device name on compute node.'), widget=forms.Select(attrs=SELECT_ATTRS)) vxlan_id = forms.IntegerField( label=_('VXLAN ID'), required=False, widget=forms.TextInput(attrs=TEXT_INPUT_ATTRS), help_text=_('VXLAN ID required for overlay NIC tags (1 - 16777215).')) # Advanced options resolvers = ArrayField( label=_('Resolvers'), required=False, help_text= _('Comma-separated list of IPv4 addresses that can be used as resolvers.' ), widget=ArrayWidget(attrs={'class': 'input-transparent narrow'})) # dns_domain = forms.CharField(label=_('DNS Domain'), required=False, # help_text=_('Existing domain name used for creating A records for virtual servers'), # widget=forms.TextInput(attrs={'class': 'input-transparent wide', 'required': ''})) ptr_domain = forms.CharField( label=_('PTR Domain'), required=False, help_text=_( 'Existing in-addr.arpa domain used for creating PTR associations with ' 'virtual servers.'), widget=forms.TextInput(attrs={ 'class': 'input-transparent wide', 'required': '' })) dhcp_passthrough = forms.BooleanField( label=_('DHCP Passthrough'), required=False, help_text=_( 'When enabled, IP addresses for this network are managed by ' 'an external DHCP service.'), widget=forms.CheckboxInput(attrs={'class': 'normal-check'})) mtu = forms.IntegerField( label=_('MTU'), required=False, widget=forms.TextInput(attrs=TEXT_INPUT_ATTRS), help_text=_('MTU for the network vNIC (576 - 9000)')) def __init__(self, request, net, *args, **kwargs): super(AdminNetworkForm, self).__init__(request, net, *args, **kwargs) self.fields['owner'].choices = get_owners(request).values_list( 'username', 'username') self.fields['nic_tag'].choices = Node.all_nictags_choices() if not request.user.is_staff: self.fields['dc_bound'].widget.attrs['disabled'] = 'disabled' def clean_ip_network(self): try: n = '/'.join( map(str.strip, str(self.cleaned_data.get('ip_network')).split('/'))) net = ipaddress.ip_network(text_type(n)) except ValueError: raise forms.ValidationError( _('Enter valid IPv4 network and netmask.')) else: self.network, self.netmask = net.with_netmask.split('/') return text_type(net) def _initial_data(self, request, obj): return obj.web_data_admin def _set_custom_api_errors(self, errors): # ip_network field does not exist in NetworkSerializer # network and netmask errors must be set to ip_network field network_errors = errors.get('network', []) netmask_errors = errors.get('netmask', []) if network_errors or netmask_errors: if network_errors == netmask_errors: ip_network_errors = network_errors else: ip_network_errors = network_errors + netmask_errors self._errors['ip_network'] = self.error_class(ip_network_errors) # The ip_network will not probably be in cleaned_data, but just in case remove it here try: del self.cleaned_data['ip_network'] except KeyError: pass def _final_data(self, data=None): ret = super(AdminNetworkForm, self)._final_data(data=data) ip_network = ret.pop('ip_network', None) if ip_network: ret['network'] = self.network ret['netmask'] = self.netmask if self.action == 'create': # Add dc parameter when doing POST (required by api.db.utils.get_virt_object) ret['dc'] = self._request.dc.name return ret
class NodeForm(SerializerForm): """ Update compute node settings. """ _api_call = node_define hostname = forms.CharField( label=_('Hostname'), widget=forms.TextInput( attrs={ 'class': 'input-transparent narrow uneditable-input', 'disabled': 'disabled' })) owner = forms.ChoiceField( label=_('Owner'), widget=forms.Select(attrs={'class': 'narrow input-select2'})) status = forms.TypedChoiceField( label=_('Status'), choices=Node.STATUS, coerce=int, widget=forms.Select(attrs={'class': 'narrow input-select2'})) is_compute = forms.BooleanField( label=_('Compute?'), required=False, widget=forms.CheckboxInput(attrs={'class': 'normal-check'})) is_backup = forms.BooleanField( label=_('Backup?'), required=False, widget=forms.CheckboxInput(attrs={'class': 'normal-check'})) note = forms.CharField( label=_('Note'), help_text=_( 'Custom text information about this compute node, with markdown' ' support.'), required=False, widget=forms.Textarea(attrs={ 'class': 'input-transparent small', 'rows': 5 })) cpu_coef = forms.DecimalField( label=_('CPUs coefficient'), max_digits=4, decimal_places=2, help_text=_( 'Coefficient for calculating the the total number of virtual CPUs.' ), widget=forms.TextInput(attrs={ 'class': 'input-transparent narrow', 'required': 'required' })) ram_coef = forms.DecimalField( label=_('RAM coefficient'), max_digits=4, decimal_places=2, help_text=_('Coefficient for calculating the maximum amount of memory ' 'for virtual machines.'), widget=forms.TextInput(attrs={ 'class': 'input-transparent narrow', 'required': 'required' })) monitoring_templates = ArrayField( label=_('Monitoring templates'), required=False, tags=True, help_text=_('Comma-separated list of custom monitoring templates.'), widget=ArrayWidget(tags=True, escape_space=False, attrs={ 'class': 'tags-select2 narrow', 'data-tags-type': 'mon_templates', 'data-tags-api-call': 'mon_node_template_list' })) monitoring_hostgroups = ArrayField( label=_('Monitoring hostgroups'), required=False, tags=True, help_text=_('Comma-separated list of custom monitoring hostgroups.'), widget=ArrayWidget(tags=True, escape_space=False, attrs={ 'class': 'tags-select2 narrow', 'data-tags-type': 'mon_hostgroups', 'data-tags-api-call': 'mon_node_hostgroup_list' })) def __init__(self, request, node, *args, **kwargs): super(NodeForm, self).__init__(request, node, *args, **kwargs) self.fields['owner'].choices = get_owners(request).values_list( 'username', 'username') if node.is_unlicensed(): self.fields['status'].choices = Node.STATUS_DB self.fields['status'].widget.attrs['disabled'] = 'disabled' elif node.is_unreachable(): self.fields['status'].choices = Node.STATUS_DB[:-1] self.fields['status'].widget.attrs['disabled'] = 'disabled' def _initial_data(self, request, obj): return obj.web_data
class AdminServerSettingsForm(ServerSettingsForm): """ Copy of vm_define serializer (api). """ admin = True _api_call = vm_define tags = TagField( label=_('Tags'), required=False, widget=TagWidget(attrs={'class': 'tags-select2 narrow'}), help_text=_('The tag will be created in case it does not exist.')) node = forms.TypedChoiceField( label=_('Node'), required=False, coerce=str, empty_value=None, widget=forms.Select(attrs={'class': 'narrow input-select2'})) template = forms.TypedChoiceField( label=_('Template'), required=False, coerce=str, empty_value=None, help_text=_('Setting template can modify lots of server attributes, ' 'e.g. disks, nics.'), widget=DataSelect(attrs={'class': 'narrow input-select2'})) ostype = forms.TypedChoiceField( label=_('OS Type'), choices=Vm.OSTYPE, required=True, coerce=int, widget=forms.Select( attrs={ 'class': 'input-select2 narrow ostype-select', 'required': 'required', 'onChange': 'update_vm_form_fields_from_ostype()' })) hvm_type = forms.TypedChoiceField( label=_('Hypervisor Type'), choices=Vm.HVM_TYPE_GUI, required=False, coerce=int, widget=forms.Select( attrs={ 'class': 'input-select2 narrow hvm-type-select', 'required': 'required', 'onChange': 'update_vm_form_fields_from_hvm_type()' })) vcpus = forms.IntegerField( label=_('VCPUs'), required=False, widget=NumberInput(attrs={ 'class': 'input-transparent narrow', 'required': 'required' })) # noinspection SpellCheckingInspection ram = forms.IntegerField( label=_('RAM'), required=False, widget=forms.TextInput( attrs={ 'class': 'input-transparent narrow input-mbytes', 'required': 'required', 'pattern': '[0-9.]+[BKMGTPEbkmgtpe]?' })) note = forms.CharField( label=_('Note'), help_text=_( 'Text with markdown support, visible to every user with access ' 'to this server.'), required=False, widget=forms.Textarea(attrs={ 'class': 'input-transparent', 'rows': 5 })) monitored = forms.BooleanField( label=_('Monitored?'), required=False, widget=forms.CheckboxInput(attrs={'class': 'normal-check'})) installed = forms.BooleanField( label=_('Installed?'), required=False, help_text=_('This field is used for informational purposes only.'), widget=forms.CheckboxInput(attrs={'class': 'normal-check'})) snapshot_limit_manual = forms.IntegerField( label=_('Snapshot count limit'), required=False, widget=NumberInput(attrs={'class': 'input-transparent narrow'}), help_text=_('Maximum number of manual server snapshots.')) snapshot_size_percent_limit = forms.IntegerField( label=_('Snapshot size % limit'), required=False, widget=NumberInput(attrs={'class': 'input-transparent narrow'}), help_text=_( 'Maximum size of all server snapshots as % of all disk space ' 'of this VM (example: 200% = VM with 10GB disk(s) can have ' '20GB of snapshots).')) snapshot_size_limit = forms.IntegerField( label=_('Snapshot size limit'), required=False, widget=NumberInput(attrs={'class': 'input-transparent narrow'}), help_text=_('Maximum size of all server snapshots. ' 'If set, it takes precedence over % limit.')) cpu_shares = forms.IntegerField( label=_('CPU Shares'), max_value=1048576, min_value=0, required=True, widget=NumberInput(attrs={ 'class': 'input-transparent narrow', 'required': 'required' })) # cpu_cap = forms.IntegerField(label=_('CPU Capping'), max_value=6400, min_value=0, required=False, # widget=NumberInput(attrs={'class': 'input-transparent narrow'})) zfs_io_priority = forms.IntegerField( label=_('IO Priority'), max_value=1024, min_value=0, required=True, widget=NumberInput(attrs={ 'class': 'input-transparent narrow', 'required': 'required' })) bootrom = forms.ChoiceField( label=_('Bootrom'), required=False, widget=forms.Select(attrs={'class': 'narrow input-select2'})) zpool = forms.ChoiceField( label=_('Storage'), required=False, widget=forms.Select(attrs={'class': 'narrow input-select2'})) owner = forms.ChoiceField( label=_('Owner'), required=False, widget=forms.Select(attrs={'class': 'narrow input-select2'})) monitoring_templates = ArrayField( label=_('Monitoring templates'), required=False, tags=True, help_text=_('Comma-separated list of custom monitoring templates.'), widget=ArrayWidget(tags=True, escape_space=False, attrs={'class': 'tags-select2 narrow'})) monitoring_hostgroups = ArrayField( label=_('Monitoring hostgroups'), required=False, tags=True, validators=[ RegexValidator(regex=MonitoringBackend.RE_MONITORING_HOSTGROUPS) ], help_text=_('Comma-separated list of custom monitoring hostgroups.'), widget=ArrayWidget(tags=True, escape_space=False, attrs={'class': 'tags-select2 narrow'})) mdata = DictField(label=_('Metadata'), required=False, help_text=_('key=value string pairs.'), widget=DictWidget( attrs={ 'class': 'input-transparent small', 'rows': 5, 'data-raw_input_enabled': 'true', })) def __init__(self, request, vm, *args, **kwargs): super(AdminServerSettingsForm, self).__init__(request, vm, *args, **kwargs) dc_settings = request.dc.settings # Set choices self.vm_nodes = get_nodes(request, is_compute=True) # TODO: node.color self.fields['node'].choices = [('', _('(auto)'))] + [ (i.hostname, i.hostname) for i in self.vm_nodes ] self.fields['owner'].choices = get_owners(request).values_list( 'username', 'username') self.fields['zpool'].choices = get_zpools(request).values_list( 'zpool', 'storage__alias').distinct() self.fields['bootrom'].choices = Vm.BHYVE_BOOTROM if not request.user.is_staff: self.fields['cpu_shares'].widget.attrs['disabled'] = 'disabled' self.fields['cpu_shares'].widget.attrs[ 'class'] += ' uneditable-input' self.fields['zfs_io_priority'].widget.attrs[ 'disabled'] = 'disabled' self.fields['zfs_io_priority'].widget.attrs[ 'class'] += ' uneditable-input' if dc_settings.MON_ZABBIX_TEMPLATES_VM_RESTRICT: self.fields[ 'monitoring_templates'].widget.tag_choices = dc_settings.MON_ZABBIX_TEMPLATES_VM_ALLOWED if dc_settings.MON_ZABBIX_HOSTGROUPS_VM_RESTRICT: self.fields[ 'monitoring_hostgroups'].widget.tag_choices = dc_settings.MON_ZABBIX_HOSTGROUPS_VM_ALLOWED if dc_settings.MON_ZABBIX_HOSTGROUPS_VM: self.fields['monitoring_hostgroups'].help_text += _(' Automatically added hostgroups: ') \ + ', '.join(dc_settings.MON_ZABBIX_HOSTGROUPS_VM) if vm: empty_template_data = {} self.fields['ostype'].widget.attrs['disabled'] = 'disabled' self.fields['hvm_type'].widget.attrs['disabled'] = 'disabled' if not vm.is_hvm(): # for zones the only HVM choice is NO hypervisor self.fields['hvm_type'].choices = Vm.HVM_TYPE_GUI_NO_HYPERVISOR if vm.is_deployed(): self.fields['node'].widget.attrs[ 'class'] += ' disable_created2' self.fields['zpool'].widget.attrs[ 'class'] += ' disable_created2' else: empty_template_data = self.initial ostype = Vm.OSTYPE # Disable zone support _only_ when adding new VM (zone must be available in edit mode) - Issue #chili-461 if not dc_settings.VMS_ZONE_ENABLED: # Remove SunOS Zone support ostype = [i for i in ostype if i[0] not in Vm.ZONE_OSTYPES] self.fields['ostype'].choices = ostype empty_template = AttrDict({ 'alias': _('(none)'), 'desc': '', 'web_data': empty_template_data }) self.fields['template'].choices = [('', empty_template)] + [ (i.name, i) for i in get_templates(request) ] def _initial_data(self, request, vm): fix = super(AdminServerSettingsForm, self)._initial_data(request, vm) ret = get_vm_define(request, vm) # We need string representation of tags, but vm_define returns a list if 'tags' in ret: ret['tags'] = tags_to_string(ret['tags']) # Some serializer data need to be replaced by data expected by the parent form ret.update(fix) return ret
class BaseAlertFilterForm(SerializerForm): since = forms.DateTimeField( label=_('Since'), required=False, input_formats=('%Y-%m-%d', ''), widget=forms.DateInput( format='%Y-%m-%d', attrs={ 'placeholder': _('Since'), 'class': 'fill-up input-navigation input-transparent ' 'input-date' })) until = forms.DateTimeField( label=_('Until'), required=False, input_formats=('%Y-%m-%d', ), widget=forms.DateInput( format='%Y-%m-%d', attrs={ 'placeholder': _('Until'), 'class': 'fill-up input-navigation input-transparent ' 'input-date' })) vm_hostnames = ArrayField( label=_('Server hostnames'), required=False, widget=ArrayWidget( attrs={ 'placeholder': _('Server hostnames'), 'class': 'fill-up input-navigation input-transparent' })) node_hostnames = ArrayField( label=_('Node hostnames'), required=False, widget=ArrayWidget( attrs={ 'placeholder': _('Node hostnames'), 'class': 'fill-up input-navigation input-transparent' })) show_events = forms.BooleanField( label=_('Show events?'), required=False, widget=forms.CheckboxInput( attrs={'class': 'checkbox fill-up input-navigation'})) show_nodes = forms.BooleanField( label=_('Include compute nodes?'), required=False, widget=forms.CheckboxInput( attrs={'class': 'checkbox fill-up input-navigation'})) show_all = forms.BooleanField( label=_('Show all?'), required=False, widget=forms.CheckboxInput( attrs={'class': 'checkbox fill-up input-navigation'})) def __init__(self, request, *args, **kwargs): super(BaseAlertFilterForm, self).__init__(request, None, *args, **kwargs) self.api_data = None if request.user.is_staff: dc = request.dc if not dc.is_default( ) and dc.settings.MON_ZABBIX_SERVER != DefaultDc( ).settings.MON_ZABBIX_SERVER: self.fields['show_nodes'].widget.attrs['disabled'] = 'disabled' else: # SuperAdmin only fields self.fields.pop('node_hostnames') self.fields.pop('show_nodes') self.fields.pop('show_all') @staticmethod def _remove_empty_fields(data): for key, value in list(iteritems(data)): if value in (None, [], ''): del data[key] return data def clean(self): cleaned_data = super(BaseAlertFilterForm, self).clean() if self._errors: return cleaned_data data = cleaned_data.copy() tz = timezone.get_current_timezone() if data['since']: data['since'] = data['since'].replace( tzinfo=tz).astimezone(utc).strftime('%s') if data['until']: data['until'] = data['until'].replace( tzinfo=tz).astimezone(utc).strftime('%s') show_nodes = data.pop('show_nodes', False) if data.get('show_all', False): data['dc_bound'] = False else: data['dc_bound'] = not show_nodes self._remove_empty_fields(data) ser = AlertSerializer(self._request, data=data) if ser.is_valid(): api_data = ser.data # Not used filters del api_data['last'] del api_data['node_uuids'] del api_data['vm_uuids'] if not self._request.user.is_staff: # SuperAdmin only fields del api_data['node_hostnames'] del api_data['show_all'] api_data['dc_bound'] = True self.api_data = self._remove_empty_fields(api_data) else: self.api_data = None self._set_api_errors(ser.errors) return cleaned_data
class NodeForm(SerializerForm): """ Update compute node settings. """ _api_call = node_define hostname = forms.CharField( label=_('Hostname'), widget=forms.TextInput( attrs={ 'class': 'input-transparent narrow uneditable-input', 'disabled': 'disabled' })) owner = forms.ChoiceField( label=_('Owner'), widget=forms.Select(attrs={'class': 'narrow input-select2'})) status = forms.TypedChoiceField( label=_('Status'), choices=Node.STATUS, coerce=int, widget=forms.Select(attrs={'class': 'narrow input-select2'})) is_compute = forms.BooleanField( label=_('Compute?'), required=False, widget=forms.CheckboxInput(attrs={'class': 'normal-check'})) is_backup = forms.BooleanField( label=_('Backup?'), required=False, widget=forms.CheckboxInput(attrs={'class': 'normal-check'})) note = forms.CharField( label=_('Note'), help_text=_( 'Custom text information about this compute node, with markdown' ' support.'), required=False, widget=forms.Textarea(attrs={ 'class': 'input-transparent small', 'rows': 5 })) address = forms.ChoiceField( label=_('IP address'), help_text=_( 'IP address used for communication between compute nodes ' '(e.g., VM backups, VM replication, internal VM and node monitoring).' ), widget=forms.Select(attrs={'class': 'narrow input-select2'})) cpu_coef = forms.DecimalField( label=_('CPUs coefficient'), max_digits=4, decimal_places=2, help_text=_( 'Coefficient for calculating the the total number of virtual CPUs.' ), widget=forms.TextInput(attrs={ 'class': 'input-transparent narrow', 'required': 'required' })) ram_coef = forms.DecimalField( label=_('RAM coefficient'), max_digits=4, decimal_places=2, help_text=_( 'Coefficient for calculating the maximum amount of memory ' 'for virtual machines. Keep it under 1 unless you really know what you are doing.' ), widget=forms.TextInput(attrs={ 'class': 'input-transparent narrow', 'required': 'required' })) monitoring_templates = ArrayField( label=_('Monitoring templates'), required=False, tags=True, help_text=_('Comma-separated list of custom monitoring templates.'), widget=ArrayWidget(tags=True, escape_space=False, attrs={ 'class': 'tags-select2 narrow', 'data-tags-type': 'mon_templates', 'data-tags-api-call': 'mon_node_template_list' })) monitoring_hostgroups = ArrayField( label=_('Monitoring hostgroups'), required=False, tags=True, help_text=_('Comma-separated list of custom monitoring hostgroups.'), validators=[ RegexValidator(regex=MonitoringBackend.RE_MONITORING_HOSTGROUPS) ], widget=ArrayWidget(tags=True, escape_space=False, attrs={ 'class': 'tags-select2 narrow', 'data-tags-type': 'mon_hostgroups', 'data-tags-api-call': 'mon_node_hostgroup_list' })) def __init__(self, request, node, *args, **kwargs): super(NodeForm, self).__init__(request, node, *args, **kwargs) self.fields['owner'].choices = get_owners(request).values_list( 'username', 'username') self.fields['address'].choices = [(ip, ip) for ip in node.ips] dc1_settings = get_dc1_settings(request) if dc1_settings.MON_ZABBIX_HOSTGROUPS_NODE: self.fields['monitoring_hostgroups'].help_text += _(' Automatically added hostgroups: ') \ + ', '.join(dc1_settings.MON_ZABBIX_HOSTGROUPS_NODE) if node.is_unlicensed(): self.fields['status'].choices = Node.STATUS_DB self.fields['status'].widget.attrs['disabled'] = 'disabled' elif node.is_unreachable(): self.fields['status'].choices = Node.STATUS_DB[:-1] self.fields['status'].widget.attrs['disabled'] = 'disabled' def _initial_data(self, request, obj): return obj.web_data