Пример #1
0
 def test_input_url_defaults_empty_with_no_input(self):
     script = factory.make_Script(parameters={"url": {"type": "url"}})
     form = ParametersForm(data={}, script=script, node=factory.make_Node())
     self.assertTrue(form.is_valid(), form.errors)
     self.assertDictEqual({}, form.cleaned_data["input"][0])
Пример #2
0
 def test_validates_parameters_is_dict(self):
     form = ParametersForm(data=[factory.make_name() for _ in range(3)])
     self.assertFalse(form.is_valid())
     self.assertDictEqual({"parameters": ["Must be a dictionary"]},
                          form.errors)
Пример #3
0
    def is_valid(self):
        valid = super().is_valid()

        if valid and self.instance.default and not self.edit_default:
            for field in self.Meta.fields:
                if field in ["tags", "timeout"]:
                    continue
                if field in self.data:
                    set_form_error(
                        self,
                        field,
                        "Not allowed to change on default scripts.",
                    )
                    valid = False

        name = self.data.get("name")
        # none is used to tell the API to not run testing_scripts during
        # commissioning.
        if name is not None and name.lower() == "none":
            set_form_error(self, "name", '"none" is a reserved name.')
            valid = False

        # The name can't be a digit as MAAS allows scripts to be selected by
        # id.
        if name is not None and name.isdigit():
            set_form_error(self, "name", "Cannot be a number.")
            valid = False

        if name is not None and pipes.quote(name) != name:
            set_form_error(
                self,
                "name",
                "Name '%s' contains disallowed characters, e.g. space or quotes."
                % name,
            )
            valid = False

        # If comment and script exist __init__ combines both fields into a dict
        # to pass to VersionedTextFileField.
        if "comment" in self.data:
            set_form_error(
                self,
                "comment",
                '"comment" may only be used when specifying a "script" '
                "as well.",
            )
            valid = False

        if "script" in self.data:
            if not self._validate_results(self.instance.results):
                valid = False

        if "parameters" in self.data:
            params_form = ParametersForm(data=self.data.get("parameters"))
            if not params_form.is_valid():
                valid = False

        if (not valid and self.instance.script_id is not None
                and self.initial.get("script") != self.instance.script_id
                and self.instance.script.id is not None):
            # If form validation failed cleanup any new VersionedTextFile
            # created by the VersionedTextFileField.
            self.instance.script.delete()
        return valid
Пример #4
0
 def test__validates_unsupported_parameter_types_if_not_required(self):
     unsupported_type = factory.make_name("unsupported")
     form = ParametersForm(
         data={"storage": {"type": unsupported_type, "required": False}}
     )
     self.assertTrue(form.is_valid())
Пример #5
0
    def regenerate(self, storage=True, network=True):
        """Regenerate any ScriptResult which has a storage parameter.

        Deletes and recreates ScriptResults for any ScriptResult which has a
        storage parameter. Used after commissioning has completed when there
        are tests to be run.
        """
        # Avoid circular dependencies.
        from metadataserver.models import ScriptResult

        regenerate_scripts = {}
        for script_result in (self.scriptresult_set.filter(
                status=SCRIPT_STATUS.PENDING).exclude(parameters={}).defer(
                    "stdout", "stderr", "output", "result")):
            # If there are multiple storage devices or interface on the system
            # for every script which contains a storage or interface type
            # parameter there will be one ScriptResult per device. If we
            # already know a script must be regenearted it can be deleted as
            # the device the ScriptResult is for may no longer exist.
            # Regeneratation below will generate ScriptResults for each
            # existing storage or interface device.
            if script_result.script in regenerate_scripts:
                script_result.delete()
                continue
            # Check if the ScriptResult contains any storage or interface type
            # parameter. If so remove the value of the storage or interface
            # parameter only and add it to the list of Scripts which must be
            # regenearted.
            for param_name, param in script_result.parameters.items():
                if (storage and param["type"] == "storage") or (
                        network and param["type"] == "interface"):
                    # Remove the storage or interface parameter as the storage
                    # device or interface may no longer exist. The
                    # ParametersForm will set the default value(all).
                    script_result.parameters.pop(param_name)
                    # Only preserve the value of the parameter as that is what
                    # the form will validate.
                    regenerate_scripts[script_result.script] = {
                        key: value["value"]
                        for key, value in script_result.parameters.items()
                    }
                    script_result.delete()
                    break

        for script, params in regenerate_scripts.items():
            form = ParametersForm(data=params, script=script, node=self.node)
            if not form.is_valid():
                err_msg = (
                    "Removing Script %s from ScriptSet due to regeneration "
                    "error - %s" % (script.name, dict(form.errors)))
                logger.error(err_msg)
                Event.objects.create_node_event(
                    system_id=self.node.system_id,
                    event_type=EVENT_TYPES.SCRIPT_RESULT_ERROR,
                    event_description=err_msg,
                )
                continue
            for i in form.cleaned_data["input"]:
                ScriptResult.objects.create(
                    script_set=self,
                    status=SCRIPT_STATUS.PENDING,
                    script=script,
                    script_name=script.name,
                    parameters=i,
                )