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 TestDataVolumeFieldToPython(TestCase): """ Test converting DataVolumeField to Python types using the to_python() method. """ def setUp(self): self.f = DataVolumeField(required=True, min_value=0.) def test_trivial(self): """ Check that setUp() is sane. """ pass def test_clean_none(self): """ Check that a ValidationError is raised when None is passed in. """ self.assertRaises(ValidationError, self.f.clean, None) def test_validationerror(self): """ Make sure that ValidationError is raised when appropriate. """ self.assertRaises(ValidationError, self.f.clean, 'gdrcigeudr7d') self.assertRaises(ValidationError, self.f.clean, ' ') self.assertRaises(ValidationError, self.f.clean, '') # Wrong units? self.assertRaises(ValidationError, self.f.clean, '100.0 GMB') self.assertRaises(ValidationError, self.f.clean, '250 B') self.assertRaises(ValidationError, self.f.clean, '50 yogdiecidu') def test_empty_not_required(self): """ Make sure that empty fields clean() to None when a value isn't required. """ self.f.required = False self.assertEquals(self.f.clean(''), None) self.assertEquals(self.f.clean(' '), None) def test_correct_values(self): """ Make sure that correct values are generated for valid data. """ self.assertEquals(self.f.clean('9001 GB'), 9217024) self.assertEquals(self.f.clean('9001.000 GB'), 9217024) self.assertEquals(self.f.clean('9001G'), 9217024) self.assertEquals(self.f.clean('0.5G'), 512) self.assertEquals(self.f.clean('100.0 MB'), 100) self.assertEquals(self.f.clean('100.00MB'), 100) self.assertEquals(self.f.clean('100.000 M'), 100) self.assertEquals(self.f.clean('100M'), 100)
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
def setUp(self): self.f = DataVolumeField(required=True, min_value=0.)