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
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
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
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, })
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}, )
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}, )
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
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
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
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
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)
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
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
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'])
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]))
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
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