Esempio n. 1
0
def make_active_discovery_interval_field(*args, **kwargs):
    """Build and return the network_discovery field."""
    field = forms.ChoiceField(
        initial=CONFIG_ITEMS['active_discovery_interval']['default'],
        choices=ACTIVE_DISCOVERY_INTERVAL_CHOICES,
        error_messages={
            'invalid_choice':
            compose_invalid_choice_text('active_discovery_interval',
                                        ACTIVE_DISCOVERY_INTERVAL_CHOICES)
        },
        **kwargs)
    return field
Esempio n. 2
0
def make_network_discovery_field(*args, **kwargs):
    """Build and return the network_discovery field."""
    field = forms.ChoiceField(
        initial=CONFIG_ITEMS['network_discovery']['default'],
        choices=NETWORK_DISCOVERY_CHOICES,
        error_messages={
            'invalid_choice':
            compose_invalid_choice_text('network_discovery',
                                        NETWORK_DISCOVERY_CHOICES)
        },
        **kwargs)
    return field
Esempio n. 3
0
def make_dnssec_validation_field(*args, **kwargs):
    """Build and return the dnssec_validation field."""
    field = forms.ChoiceField(
        initial=CONFIG_ITEMS['dnssec_validation']['default'],
        choices=DNSSEC_VALIDATION_CHOICES,
        error_messages={
            'invalid_choice':
            compose_invalid_choice_text('dnssec_validation',
                                        DNSSEC_VALIDATION_CHOICES)
        },
        **kwargs)
    return field
Esempio n. 4
0
 def set_up_id_field(self):
     link_ids = self.instance.ip_addresses.all().values_list(
         "id", flat=True)
     link_choices = [
         (link_id, link_id)
         for link_id in link_ids
     ]
     invalid_choice = compose_invalid_choice_text('id', link_choices)
     self.fields["id"] = forms.ChoiceField(
         choices=link_choices, required=True,
         error_messages={
             'invalid_choice': invalid_choice,
         })
Esempio n. 5
0
 def setup_root_device_field(self):
     """Setup the possible root devices."""
     choices = [
         (block_device.id, block_device.id)
         for block_device in self.block_devices
     ]
     invalid_choice_message = compose_invalid_choice_text(
         "root_device", choices
     )
     self.fields["root_device"] = forms.ChoiceField(
         choices=choices,
         required=False,
         error_messages={"invalid_choice": invalid_choice_message},
     )
Esempio n. 6
0
 def setup_cache_device_field(self):
     """Setup the possible cache devices."""
     if self.boot_disk is None:
         return
     choices = [(block_device.id, block_device.id)
                for block_device in self.block_devices
                if block_device != self.boot_disk]
     invalid_choice_message = compose_invalid_choice_text(
         "cache_device", choices)
     self.fields["cache_device"] = forms.ChoiceField(
         choices=choices,
         required=False,
         error_messages={"invalid_choice": invalid_choice_message},
     )
Esempio n. 7
0
def make_default_osystem_field(*args, **kwargs):
    """Build and return the default_osystem field."""
    usable_oses = list_all_usable_osystems()
    os_choices = list_osystem_choices(usable_oses, include_default=False)
    if len(os_choices) == 0:
        os_choices = [("---", "--- No Usable Operating System ---")]
    field = forms.ChoiceField(
        initial=Config.objects.get_config("default_osystem"),
        choices=os_choices,
        validators=[validate_missing_boot_images],
        error_messages={
            "invalid_choice":
            compose_invalid_choice_text("osystem", os_choices)
        },
        **kwargs)
    return field
Esempio n. 8
0
def make_commissioning_distro_series_field(*args, **kwargs):
    """Build and return the commissioning_distro_series field."""
    usable_oses = list_all_usable_osystems()
    commissioning_choices = list_commissioning_choices(usable_oses)
    if len(commissioning_choices) == 0:
        commissioning_choices = [('---', '--- No Usable Release ---')]
    field = forms.ChoiceField(
        initial=Config.objects.get_config('commissioning_distro_series'),
        choices=commissioning_choices,
        validators=[validate_missing_boot_images],
        error_messages={
            'invalid_choice': compose_invalid_choice_text(
                'commissioning_distro_series', commissioning_choices)
        },
        **kwargs)
    return field
Esempio n. 9
0
def make_default_distro_series_field(*args, **kwargs):
    """Build and return the default_distro_series field."""
    default_osystem = Config.objects.get_config("default_osystem")
    default_usable_os = get_default_usable_osystem(default_osystem)
    release_choices = [("---", "--- No Usable Release ---")]
    if default_usable_os is not None:
        releases = default_usable_os["releases"]
        valid_release_choices = list_choices_for_releases(releases)
        if len(valid_release_choices) > 0:
            release_choices = valid_release_choices
    field = forms.ChoiceField(
        initial=Config.objects.get_config("default_distro_series"),
        choices=release_choices,
        validators=[validate_missing_boot_images],
        error_messages={
            "invalid_choice":
            compose_invalid_choice_text("release", release_choices)
        },
        **kwargs)
    return field
Esempio n. 10
0
def make_default_distro_series_field(*args, **kwargs):
    """Build and return the default_distro_series field."""
    default_osystem = Config.objects.get_config('default_osystem')
    default_usable_os = get_default_usable_osystem(default_osystem)
    release_choices = [('---', '--- No Usable Release ---')]
    if default_usable_os is not None:
        releases = list_all_usable_releases([default_usable_os
                                             ])[default_osystem]
        valid_release_choices = list_choices_for_releases(releases)
        if len(valid_release_choices) > 0:
            release_choices = valid_release_choices
    field = forms.ChoiceField(
        initial=Config.objects.get_config('default_distro_series'),
        choices=release_choices,
        validators=[validate_missing_boot_images],
        error_messages={
            'invalid_choice':
            compose_invalid_choice_text('release', release_choices)
        },
        **kwargs)
    return field
Esempio n. 11
0
 def test__creates_choice_field_for_choices(self):
     json_field = {
         "name": "some_field",
         "label": "Some Field",
         "field_type": "choice",
         "choices": [
             ["choice-one", "Choice One"],
             ["choice-two", "Choice Two"],
         ],
         "default": "choice-one",
         "required": False,
     }
     django_field = make_form_field(json_field)
     self.assertIsInstance(django_field, forms.ChoiceField)
     self.assertEqual(json_field["choices"], django_field.choices)
     invalid_msg = compose_invalid_choice_text(
         json_field["name"], json_field["choices"]
     )
     self.assertEqual(
         invalid_msg, django_field.error_messages["invalid_choice"]
     )
     self.assertEqual(json_field["default"], django_field.initial)
Esempio n. 12
0
def make_default_min_hwe_kernel_field(*args, **kwargs):
    """Build and return the default_min_hwe_kernel field."""
    kernel_choices = [('', '--- No minimum kernel ---')]
    # Global choices are limited to the commissioning release as min_hwe_kernel
    # is used during commissioning.
    commissioning_series = Config.objects.get_config(
        'commissioning_distro_series')
    if commissioning_series:
        commissioning_os_release = "ubuntu/" + commissioning_series
        kernel_choices += list_hwe_kernel_choices(
            [kernel
             for kernel in BootResource.objects.get_usable_hwe_kernels(
                 commissioning_os_release)
             if release_a_newer_than_b(kernel, commissioning_series)])
    field = forms.ChoiceField(
        initial=Config.objects.get_config('default_min_hwe_kernel'),
        choices=kernel_choices,
        error_messages={
            'invalid_choice': compose_invalid_choice_text(
                'default_min_hwe_kernel', kernel_choices)
        },
        **kwargs)
    return field
Esempio n. 13
0
    def power_on(self, request, system_id):
        """@description-title Turn on a node
        @description Turn on the given node with optional user-data and
        comment.

        @param (string) "user_data" [required=false] Base64-encoded blob of
        data to be made available to the nodes through the metadata service.

        @param (string) "comment" [required=false] Comment for the event log.

        @success (http-status-code) "204" 204
        @success (json) "success_json" A JSON object containing the node's
        information.
        @success-example "success_json" [exkey=power-on] placeholder text

        @error (http-status-code) "404" 404
        @error (content) "not-found" The requested node is not found.
        @error-example "not-found"
            Not Found

        @error (http-status-code) "403" 403
        @error (content) "no-perms" The user is not authorized to power on the
        node.

        @error (http-status-code) "503" 503
        @error (content) "no-ips" Returns 503 if the start-up attempted to
        allocate an IP address, and there were no IP addresses available on the
        relevant cluster interface.
        """
        user_data = request.POST.get("user_data", None)
        comment = get_optional_param(request.POST, "comment")

        node = self.model.objects.get_node_or_404(system_id=system_id,
                                                  user=request.user,
                                                  perm=NodePermission.edit)
        if node.owner is None and node.node_type != NODE_TYPE.RACK_CONTROLLER:
            raise NodeStateViolation(
                "Can't start node: it hasn't been allocated.")
        if user_data is not None:
            user_data = b64decode(user_data)
        try:
            # These parameters are passed in the request from
            # maasserver.api.machines.deploy when powering on
            # the node for deployment.
            install_kvm = get_optional_param(
                request.POST,
                "install_kvm",
                default=False,
                validator=StringBool,
            )
            bridge_type = get_optional_param(request.POST,
                                             "bridge_type",
                                             default=None)
            if (bridge_type is not None
                    and bridge_type not in BRIDGE_TYPE_CHOICES_DICT):
                raise MAASAPIValidationError({
                    "bridge_type":
                    compose_invalid_choice_text("bridge_type",
                                                BRIDGE_TYPE_CHOICES)
                })
            bridge_stp = get_optional_param(request.POST,
                                            "bridge_stp",
                                            default=None,
                                            validator=StringBool)
            bridge_fd = get_optional_param(request.POST,
                                           "bridge_fd",
                                           default=None,
                                           validator=Int)
            node.start(
                request.user,
                user_data=user_data,
                comment=comment,
                install_kvm=install_kvm,
                bridge_type=bridge_type,
                bridge_stp=bridge_stp,
                bridge_fd=bridge_fd,
            )
        except StaticIPAddressExhaustion:
            # The API response should contain error text with the
            # system_id in it, as that is the primary API key to a node.
            raise StaticIPAddressExhaustion(
                "%s: Unable to allocate static IP due to address"
                " exhaustion." % system_id)
        return node
Esempio n. 14
0
 def test_commissioning_distro_series_config(self):
     field = get_config_field('commissioning_distro_series')
     self.assertEqual(
         compose_invalid_choice_text('commissioning_distro_series',
                                     field.choices),
         field.error_messages['invalid_choice'])
Esempio n. 15
0
 def test_map_enum_includes_all_enum_values(self):
     choices = [(factory.make_name("key"), factory.make_name("value"))
                for _ in range(2)]
     msg = compose_invalid_choice_text(factory.make_name(), choices)
     self.assertThat(msg,
                     ContainsAll(["'%s'" % key for key, val in choices]))
Esempio n. 16
0
class BondInterfaceForm(ChildInterfaceForm):
    """Form used to create/edit a bond interface."""

    bond_mode = forms.ChoiceField(
        choices=BOND_MODE_CHOICES, required=False,
        initial=BOND_MODE_CHOICES[0][0], error_messages={
            'invalid_choice': compose_invalid_choice_text(
                'bond_mode', BOND_MODE_CHOICES),
        })

    bond_miimon = forms.IntegerField(min_value=0, initial=100, required=False)

    bond_downdelay = forms.IntegerField(min_value=0, initial=0, required=False)

    bond_updelay = forms.IntegerField(min_value=0, initial=0, required=False)

    # Note: we don't need a separate bond_num_unsol_na field, since (as of
    # Linux kernel 3.0+) it's actually an alias for the same value.
    bond_num_grat_arp = forms.IntegerField(
        min_value=0, max_value=255, initial=1, required=False)

    bond_lacp_rate = forms.ChoiceField(
        choices=BOND_LACP_RATE_CHOICES, required=False,
        initial=BOND_LACP_RATE_CHOICES[0][0], error_messages={
            'invalid_choice': compose_invalid_choice_text(
                'bond_lacp_rate', BOND_LACP_RATE_CHOICES),
        })

    bond_xmit_hash_policy = forms.ChoiceField(
        choices=BOND_XMIT_HASH_POLICY_CHOICES, required=False,
        initial=BOND_XMIT_HASH_POLICY_CHOICES[0][0], error_messages={
            'invalid_choice': compose_invalid_choice_text(
                'bond_xmit_hash_policy', BOND_XMIT_HASH_POLICY_CHOICES),
        })

    class Meta:
        model = BondInterface
        fields = InterfaceForm.Meta.fields + (
            'mac_address',
            'name',
        )

    def clean(self):
        cleaned_data = super().clean()
        if self.fields_ok(['parents']):
            parents = self.cleaned_data.get('parents')
            # Set the mac_address if its missing and the interface is being
            # created.
            if parents:
                self._set_default_child_mac(parents)
                self.validate_parental_fidelity(parents)
                self._set_default_vlan(parents)
                self._validate_parent_vlans_match(parents)
        return cleaned_data

    def _validate_parent_vlans_match(self, parents):
        # When creating the bond set VLAN to the same as the parents
        # and check that the parents all belong to the same VLAN.
        if self.instance.id is None:
            vlan = self.cleaned_data.get('vlan')
            parent_vlans = {
                parent.vlan
                for parent in parents
                }
            if parent_vlans != set([vlan]):
                set_form_error(
                    self, 'parents',
                    "All parents must belong to the same VLAN.")

    def set_extra_parameters(self, interface, created):
        """Set the bond parameters as well."""
        super().set_extra_parameters(interface, created)
        # Set all the bond_* parameters.
        bond_fields = [
            field_name
            for field_name in self.fields
            if field_name.startswith("bond_")
        ]
        for bond_field in bond_fields:
            value = self.cleaned_data.get(bond_field)
            params = interface.params.copy()
            if (value is not None and
                    isinstance(value, str) and
                    len(value) > 0 and not value.isspace()):
                params[bond_field] = value
            elif (value is not None and
                    not isinstance(value, str)):
                params[bond_field] = value
            elif created:
                params[bond_field] = self.fields[bond_field].initial
            interface.params = params
Esempio n. 17
0
class BridgeInterfaceForm(ChildInterfaceForm):
    """Form used to create/edit a bridge interface."""

    bridge_type = forms.ChoiceField(choices=BRIDGE_TYPE_CHOICES,
                                    required=False,
                                    initial=BRIDGE_TYPE_CHOICES[0][0],
                                    error_messages={
                                        'invalid_choice':
                                        compose_invalid_choice_text(
                                            'bridge_type',
                                            BRIDGE_TYPE_CHOICES),
                                    })

    bridge_stp = forms.NullBooleanField(initial=False, required=False)

    bridge_fd = forms.IntegerField(min_value=0,
                                   initial=DEFAULT_BRIDGE_FD,
                                   required=False)

    class Meta:
        model = BridgeInterface
        fields = InterfaceForm.Meta.fields + (
            'mac_address',
            'name',
        )

    def clean_parents(self):
        parents = self.get_clean_parents()
        if parents is None:
            return
        if len(parents) != 1:
            raise ValidationError(
                "A bridge interface must have exactly one parent.")
        if parents[0].type == INTERFACE_TYPE.BRIDGE:
            raise ValidationError(
                "A bridge interface can't have another bridge interface as "
                "parent.")
        instance_id = None if self.instance is None else self.instance.id
        bond_or_bridge = {INTERFACE_TYPE.BOND, INTERFACE_TYPE.BRIDGE}
        parent_has_bad_children = any(
            rel.child.type in bond_or_bridge and rel.child.id != instance_id
            for rel in parents[0].children_relationships.all())
        if parent_has_bad_children:
            raise ValidationError(
                "A bridge interface can't have a parent that is already "
                "in a bond or a bridge.")
        return parents

    def get_delinquent_children(self, parents):
        """Returns a set of children who would prevent the creation of this
        bridge interface. The only difference between this method and the
        method it overrides is that it allows VLAN interface children, whom
        bridges may get along with.
        """
        return {
            parent.name
            for parent in parents
            for rel in parent.children_relationships.all()
            if (rel.child.id != self.instance.id
                and rel.child.type != INTERFACE_TYPE.VLAN)
        }

    def clean(self):
        cleaned_data = super().clean()
        if self.fields_ok(['vlan', 'parents']):
            parents = self.cleaned_data.get('parents')
            # Set the mac_address if its missing and the interface is being
            # created.
            if parents:
                self._set_default_child_mac(parents)
                self.validate_parental_fidelity(parents)
                self._set_default_vlan(parents)
        return cleaned_data

    def set_extra_parameters(self, interface, created):
        """Set the bridge parameters as well."""
        super().set_extra_parameters(interface, created)
        # Set all the bridge_* parameters.
        bridge_fields = [
            field_name for field_name in self.fields
            if field_name.startswith("bridge_")
        ]
        for bridge_field in bridge_fields:
            value = self.cleaned_data.get(bridge_field)
            params = interface.params.copy()
            if (value is not None and isinstance(value, str) and len(value) > 0
                    and not value.isspace()):
                params[bridge_field] = value
            elif (value is not None and not isinstance(value, str)):
                params[bridge_field] = value
            elif created:
                params[bridge_field] = (self.fields[bridge_field].initial)
            interface.params = params