~lutostag/ubuntu/trusty/maas/1.5.4+keystone

« back to all changes in this revision

Viewing changes to src/maasserver/forms.py

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez
  • Date: 2013-03-04 11:49:44 UTC
  • mto: This revision was merged to the branch mainline in revision 25.
  • Revision ID: package-import@ubuntu.com-20130304114944-azcvu9anlf8mizpa
Tags: upstream-1.3+bzr1452+dfsg
ImportĀ upstreamĀ versionĀ 1.3+bzr1452+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
__all__ = [
14
14
    "AdminNodeWithMACAddressesForm",
15
15
    "CommissioningForm",
 
16
    "CommissioningScriptForm",
16
17
    "get_action_form",
17
18
    "get_node_edit_form",
18
19
    "get_node_create_form",
19
 
    "HostnameFormField",
20
20
    "MACAddressForm",
21
21
    "MAASAndNetworkForm",
22
22
    "NodeGroupInterfaceForm",
31
31
 
32
32
import collections
33
33
import json
 
34
import pipes
34
35
import re
35
36
 
36
37
from django import forms
47
48
    PermissionDenied,
48
49
    ValidationError,
49
50
    )
50
 
from django.core.validators import URLValidator
51
51
from django.forms import (
52
 
    CharField,
53
52
    Form,
54
53
    ModelForm,
55
54
    )
84
83
from maasserver.node_action import compile_node_actions
85
84
from maasserver.power_parameters import POWER_TYPE_PARAMETERS
86
85
from maasserver.utils import strip_domain
 
86
from metadataserver.fields import Bin
 
87
from metadataserver.models import CommissioningScript
87
88
from provisioningserver.enum import (
88
89
    POWER_TYPE,
89
90
    POWER_TYPE_CHOICES,
611
612
        help_text=(
612
613
            "This is used by the cluster and region controllers for "
613
614
            "downloading PXE boot images and other provisioning-related "
614
 
            "resources. It is not passed into provisioned nodes."))
 
615
            "resources. This will also be passed onto provisioned "
 
616
            "nodes instead of the default proxy (the region controller "
 
617
            "proxy)."))
615
618
 
616
619
 
617
620
class CommissioningForm(ConfigForm):
618
 
    """Settings page, CommissioningF section."""
 
621
    """Settings page, Commissioning section."""
619
622
    check_compatibility = forms.BooleanField(
620
623
        label="Check component compatibility and certification",
621
624
        required=False)
628
631
        error_messages={'invalid_choice': INVALID_DISTRO_SERIES_MESSAGE})
629
632
 
630
633
 
 
634
url_error_msg = "Enter a valid url (e.g. http://host.example.com)."
 
635
 
 
636
 
631
637
class UbuntuForm(ConfigForm):
632
638
    """Settings page, Ubuntu section."""
633
 
    fallback_master_archive = forms.BooleanField(
634
 
        label="Fallback to Ubuntu master archive",
635
 
        required=False)
636
639
    default_distro_series = forms.ChoiceField(
637
640
        choices=DISTRO_SERIES_CHOICES, required=False,
638
641
        label="Default distro series used for deployment",
639
642
        error_messages={'invalid_choice': INVALID_DISTRO_SERIES_MESSAGE})
640
 
    keep_mirror_list_uptodate = forms.BooleanField(
641
 
        label="Keep mirror list up to date",
642
 
        required=False)
643
 
    fetch_new_releases = forms.BooleanField(
644
 
        label="Fetch new releases automatically",
645
 
        required=False)
646
 
 
647
 
    def __init__(self, *args, **kwargs):
648
 
        super(UbuntuForm, self).__init__(*args, **kwargs)
649
 
        # The field 'update_from' must be added dynamically because its
650
 
        # 'choices' must be evaluated each time the form is instantiated.
651
 
        self.fields['update_from'] = forms.ChoiceField(
652
 
            label="Update from",
653
 
            choices=Config.objects.get_config('update_from_choice'))
654
 
        # The list of fields has changed: load initial values.
655
 
        self._load_initials()
656
 
 
657
 
 
658
 
hostname_error_msg = "Enter a valid hostname (e.g. host.example.com)."
659
 
 
660
 
 
661
 
def validate_hostname(value):
662
 
    try:
663
 
        validator = URLValidator(verify_exists=False)
664
 
        validator('http://%s' % value)
665
 
    except ValidationError:
666
 
        raise ValidationError(hostname_error_msg)
667
 
 
668
 
 
669
 
class HostnameFormField(CharField):
670
 
 
671
 
    def __init__(self, *args, **kwargs):
672
 
        super(HostnameFormField, self).__init__(
673
 
            validators=[validate_hostname], *args, **kwargs)
674
 
 
675
 
 
676
 
class AddArchiveForm(ConfigForm):
677
 
    archive_name = HostnameFormField(label="Archive name")
678
 
 
679
 
    def save(self):
680
 
        """Save the archive name in the Config table.
681
 
 
682
 
        This implementation of `save` does not support the `commit` argument.
683
 
        """
684
 
        archive_name = self.cleaned_data.get('archive_name')
685
 
        archives = Config.objects.get_config('update_from_choice')
686
 
        archives.append([archive_name, archive_name])
687
 
        Config.objects.set_config('update_from_choice', archives)
 
643
    main_archive = forms.URLField(
 
644
        label="Main archive",
 
645
        error_messages={'invalid': url_error_msg},
 
646
        help_text=(
 
647
            "Archive used by nodes to retrieve packages and by cluster "
 
648
            "controllers to retrieve boot images (Intel architectures). "
 
649
            "E.g. http://archive.ubuntu.com/ubuntu."
 
650
            ))
 
651
    ports_archive = forms.URLField(
 
652
        label="Ports archive",
 
653
        error_messages={'invalid': url_error_msg},
 
654
        help_text=(
 
655
            "Archive used by cluster controllers to retrieve boot images "
 
656
            "(non-Intel architectures). "
 
657
            "E.g. http://ports.ubuntu.com/ubuntu-ports."
 
658
            ))
 
659
    cloud_images_archive = forms.URLField(
 
660
        label="Cloud images archive",
 
661
        error_messages={'invalid': url_error_msg},
 
662
        help_text=(
 
663
            "Archive used by the nodes to retrieve ephemeral images. "
 
664
            "E.g. https://maas.ubuntu.com/images."
 
665
            ))
 
666
 
 
667
 
 
668
class GlobalKernelOptsForm(ConfigForm):
 
669
    """Settings page, Global Kernel Parameters section."""
 
670
    kernel_opts = forms.CharField(
 
671
        label="Boot parameters to pass to the kernel by default",
 
672
        required=False)
688
673
 
689
674
 
690
675
class NodeGroupInterfaceForm(ModelForm):
869
854
            'name',
870
855
            'comment',
871
856
            'definition',
 
857
            'kernel_opts',
872
858
            )
873
859
 
874
860
    def clean_definition(self):
881
867
            msg = 'Invalid xpath expression: %s' % (e,)
882
868
            raise ValidationError({'definition': [msg]})
883
869
        return definition
 
870
 
 
871
 
 
872
class CommissioningScriptForm(forms.Form):
 
873
 
 
874
    content = forms.FileField(
 
875
        label="Commissioning script", allow_empty_file=False)
 
876
 
 
877
    def __init__(self, instance=None, *args, **kwargs):
 
878
        super(CommissioningScriptForm, self).__init__(*args, **kwargs)
 
879
 
 
880
    def clean_content(self):
 
881
        content = self.cleaned_data['content']
 
882
        name = content.name
 
883
        if pipes.quote(name) != name:
 
884
            raise forms.ValidationError(
 
885
                "Name contains disallowed characters (e.g. space or quotes).")
 
886
        if CommissioningScript.objects.filter(name=name).exists():
 
887
            raise forms.ValidationError(
 
888
                "A script with that name already exists.")
 
889
        return content
 
890
 
 
891
    def save(self, *args, **kwargs):
 
892
        content = self.cleaned_data['content']
 
893
        CommissioningScript.objects.create(
 
894
            name=content.name,
 
895
            content=Bin(content.read()))