class EditClusterForm(forms.ModelForm): """ Basic form for editing a cluster. """ class Meta: model = Cluster widgets = { 'password': forms.PasswordInput(), } ram = DataVolumeField(label=_('Memory'), required=False, min_value=0) disk = DataVolumeField(label=_('Disk Space'), required=False, min_value=0) def clean(self): """ Validate this form. Much of the validation is handled in the Cluster model; this method should not duplicate any validation done as part of the Cluster model definition. """ data = self.cleaned_data = super(EditClusterForm, self).clean() user = data.get('username', None) password = data.get('password', None) hostname = data.get("hostname", None) if self.instance is None or not self.instance.username: # new cluster or a cluster without a username set if user and not password: msg = _('Enter a password') self._errors['password'] = self.error_class([msg]) elif password and not user: msg = _('Enter a username') self._errors['username'] = self.error_class([msg]) # Automatically set the slug on cluster creation, based on the # hostname, if no slug was provided. if hostname and 'slug' not in data: data['slug'] = slugify(hostname.split('.')[0]) del self._errors['slug'] elif self.instance.username: # cluster had a username set. password is not required unless the # username is changed if user: if user != self.instance.username and not password: msg = _('Enter a password') self._errors['password'] = self.error_class([msg]) elif not password: # user didn't enter a password and it wasn't required # retain existing password instead of setting to empty string data['password'] = self.instance.password elif password: msg = _('Enter a username') self._errors['username'] = self.error_class([msg]) return data
class QuotaForm(forms.Form): """ Form for editing user quota on a cluster """ input = forms.TextInput(attrs={'size': 5}) user = forms.ModelChoiceField(queryset=ClusterUser.objects.all(), \ widget=forms.HiddenInput) ram = DataVolumeField(label='Memory', required=False, min_value=0) virtual_cpus = forms.IntegerField(label='Virtual CPUs', required=False, \ min_value=0, widget=input) disk = DataVolumeField(label='Disk Space', required=False, min_value=0) delete = forms.BooleanField(required=False, widget=forms.HiddenInput)
def create_disk_fields(self, count): """ dynamically add fields for disks """ self.disk_fields = range(count) for i in range(count): disk_size = DataVolumeField(min_value=100, required=True, label=_("Disk/%s Size" % i)) self.fields['disk_size_%s' % i] = disk_size
class VirtualMachineForm(forms.ModelForm): """ Parent class that holds all vm clean methods and shared form fields. """ memory = DataVolumeField(label=_('Memory'), min_value=100) class Meta: model = VirtualMachineTemplate def create_disk_fields(self, count): """ dynamically add fields for disks """ self.disk_fields = range(count) for i in range(count): disk_size = DataVolumeField(min_value=100, required=True, label=_("Disk/%s Size" % i)) self.fields['disk_size_%s' % i] = disk_size def create_nic_fields(self, count, defaults=None): """ dynamically add fields for nics """ self.nic_fields = range(count) for i in range(count): nic_mode = forms.ChoiceField(label=_('NIC/%s Mode' % i), choices=HV_NIC_MODES) nic_link = forms.CharField(label=_('NIC/%s Link' % i), max_length=255) if defaults is not None: nic_link.initial = defaults['nic_link'] self.fields['nic_mode_%s' % i] = nic_mode self.fields['nic_link_%s' % i] = nic_link def clean_hostname(self): data = self.cleaned_data hostname = data.get('hostname') cluster = data.get('cluster') if hostname and cluster: # Verify that this hostname is not in use for this cluster. It can # only be reused when recovering a VM that failed to deploy. # # Recoveries are only allowed when the user is the owner of the VM try: vm = VirtualMachine.objects.get(cluster=cluster, hostname=hostname) # detect vm that failed to deploy if not vm.pending_delete and vm.template is not None: current_owner = vm.owner.cast() if current_owner == self.owner: data['vm_recovery'] = vm else: msg = _( "Owner cannot be changed when recovering a failed deployment" ) self._errors["owner"] = self.error_class([msg]) else: raise ValidationError( _("Hostname is already in use for this cluster")) except VirtualMachine.DoesNotExist: # doesn't exist, no further checks needed pass # Spaces in hostname will always break things. if ' ' in hostname: self.errors["hostname"] = self.error_class( ["Hostname contains illegal character"]) return hostname def clean_vcpus(self): vcpus = self.cleaned_data.get("vcpus", None) if vcpus is not None and vcpus < 1: self._errors["vcpus"] = self.error_class( ["At least one CPU must be present"]) else: return vcpus def clean_initrd_path(self): data = self.cleaned_data['initrd_path'] if data and not data.startswith('/') and data != 'no_initrd_path': msg = u"%s." % _('This field must start with a "/"') self._errors['initrd_path'] = self.error_class([msg]) return data def clean_security_domain(self): data = self.cleaned_data['security_domain'] security_model = self.cleaned_data['security_model'] msg = None if data and security_model != 'user': msg = u'%s.' % _( 'This field can not be set if Security Mode is not set to User' ) elif security_model == 'user': if not data: msg = u'%s.' % _('This field is required') elif not data[0].isalpha(): msg = u'%s.' % _( 'This field must being with an alpha character') if msg: self._errors['security_domain'] = self.error_class([msg]) return data def clean_vnc_x509_path(self): data = self.cleaned_data['vnc_x509_path'] if data and not data.startswith('/'): msg = u'%s,' % _('This field must start with a "/"') self._errors['vnc_x509_path'] = self.error_class([msg]) return data