示例#1
0
    def update(self, request, name):
        """Update a commissioning script.

        :param name: The name of the script.
        :type name: unicode

        :param title: The title of the script.
        :type title: unicode

        :param description: A description of what the script does.
        :type description: unicode

        :param tags: A comma seperated list of tags for this script.
        :type tags: unicode

        :param type: The type defines when the script should be used. Can be
            testing or commissioning, defaults to testing.
        :type script_type: unicode

        :param timeout: How long the script is allowed to run before failing.
            0 gives unlimited time, defaults to 0.
        :type timeout: unicode

        :param destructive: Whether or not the script overwrites data on any
            drive on the running system. Destructive scripts can not be run on
            deployed systems. Defaults to false.
        :type destructive: boolean

        :param script: The content of the script to be uploaded in binary form.
            note: this is not a normal parameter, but a file upload. Its
            filename is ignored; MAAS will know it by the name you pass to the
            request. Optionally you can ignore the name and script parameter in
            favor of uploading a single file as part of the request.

        :param comment: A comment about what this change does.
        :type comment: unicode
        """
        if name.isdigit():
            script = get_object_or_404(Script, id=int(name))
        else:
            script = get_object_or_404(Script, name=name)

        data = request.data.copy()
        if 'script' in request.FILES:
            data['script'] = request.FILES.get('script').read()
        elif len(request.FILES) == 1:
            for name, script_content in request.FILES.items():
                data['name'] = name
                data['script'] = script_content.read()

        form = ScriptForm(instance=script, data=data)
        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
示例#2
0
    def update(self, request, id):
        """@description-title Update a notification
        @description Update a notification with a given id.

        This is available to admins *only*.

        Note: One of the ``user``, ``users`` or ``admins`` parameters must be
        set to True for the notification to be visible to anyone.

        @param (int) "{id}" [required=true] The notification id.

        @param (string) "message" [required=true] The message for this
        notification. May contain basic HTML, such as formatting. This string
        will be sanitised before display so that it doesn't break MAAS HTML.

        @param (string) "context" [required=false] Optional JSON context. The
        root object *must* be an object (i.e. a mapping). The values herein can
        be referenced by ``message`` with Python's "format" (not %) codes.

        @param (string) "category" [required=false] Choose from: ``error``,
        ``warning``, ``success``, or ``info``. Defaults to ``info``.

        @param (string) "ident" [required=false] Unique identifier for this
        notification.

        @param (string) "user" [required=false] User ID this notification is
        intended for. By default it will not be targeted to any individual
        user.

        @param (boolean) "users" [required=false] True to notify all users,
        defaults to false, i.e. not targeted to all users.

        @param (boolean) "admins" [required=false] True to notify all admins,
        defaults to false, i.e. not targeted to all admins.

        @param (boolean) "dismissable" [required=false] True to allow users
        dimissing the notification. Defaults to true.

        @success (http-status-code) "server-success" 200
        @success (json) "success-json" A JSON object containing the updated
        notification object.
        @success-example "success-json" [exkey=notifications-update]
        placeholder text

        @error (http-status-code) "404" 404
        @error (content) "not-found" The requested notification is not found.
        @error-example "not-found"
            Not Found
        """
        notification = get_object_or_404(Notification, id=id)
        form = NotificationForm(data=request.data, instance=notification)
        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
示例#3
0
    def compose(self, request, id):
        """Compose a machine from Pod.

        All fields below are optional:

        :param cores: Minimum number of CPU cores.
        :type cores: unicode
        :param memory: Minimum amount of memory (MiB).
        :type memory: unicode
        :param cpu_speed: Minimum amount of CPU speed (MHz).
        :type cpu_speed: unicode
        :param architecture: Architecture for the machine. Must be an
            architecture that the pod supports.
        :param architecture: unicode
        :param storage: A list of storage constraint identifiers, in the form:
            <label>:<size>(<tag>[,<tag>[,...])][,<label>:...]
        :type storage: unicode
        :param hostname: Hostname for the newly composed machine.
        :type hostname: unicode
        :param domain: ID of domain to place the newly composed machine in.
        :type domain: unicode
        :param zone: ID of zone place the newly composed machine in.
        :type zone: unicode

        Returns 404 if the pod is not found.
        Returns 403 if the user does not have permission to compose machine.
        """
        pod = get_object_or_404(Pod, id=id)
        if Capabilities.COMPOSABLE not in pod.capabilities:
            raise MAASAPIValidationError("Pod does not support composability.")
        form = ComposeMachineForm(data=request.data, pod=pod, request=request)
        if form.is_valid():
            machine = form.compose()
            return {
                'system_id':
                machine.system_id,
                'resource_uri':
                reverse('machine_handler',
                        kwargs={'system_id': machine.system_id})
            }
        else:
            raise MAASAPIValidationError(form.errors)
示例#4
0
    def update(self, request, name):
        """@description-title Update a tag
        @description Update elements of a given tag.

        @param (url-string) "{name}" [required=true] The tag to update.
        @param-example "{name}" oldname
        @param (string) "name" [required=false] The new tag name. Because
        the name will be used in urls, it should be short.
        @param-example "name" virtual
        @param (string) "comment" [required=false] A description of what the
        the tag will be used for in natural language.
        @param-example "comment" The 'virtual' tag represents virtual
        machines.
        @param (string) "definition" [required=false] An XPATH query that is
        evaluated against the hardware_details stored for all nodes
        (i.e. the output of ``lshw -xml``).
        @param-example "definition"
            //node[&#64;id="display"]/'clock units="Hz"' > 1000000000

        @success (http-status-code) "200" 200
        @success (json) "success-json" A JSON tag object.
        @success-example "success-json" [exkey=update-tag] placeholder

        @error (http-status-code) "404" 404
        @error (content) "not-found" The requested tag name is not found.
        @error-example "not-found"
            Not Found
        """
        tag = Tag.objects.get_tag_or_404(name=name,
                                         user=request.user,
                                         to_edit=True)
        form = TagForm(request.data, instance=tag)
        if form.is_valid():
            try:
                new_tag = form.save(commit=False)
                new_tag.save()
                form.save_m2m()
            except DatabaseError as e:
                raise MAASAPIValidationError(e)
            return new_tag
        else:
            raise MAASAPIValidationError(form.errors)
示例#5
0
    def update(self, request, id):
        """Update a specific notification.

        See `NotificationsHandler.create` for field information.
        """
        notification = get_object_or_404(Notification, id=id)
        form = NotificationForm(data=request.data, instance=notification)
        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
示例#6
0
文件: spaces.py 项目: jamal-fuma/maas
    def create(self, request):
        """Create a space.

        :param name: Name of the space.
        :param description: Description of the space.
        """
        form = SpaceForm(data=request.data)
        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
示例#7
0
    def read(self, request):
        """List networks.

        :param node: Optionally, nodes which must be attached to any returned
            networks.  If more than one node is given, the result will be
            restricted to networks that these nodes have in common.
        """
        form = NetworksListingForm(data=request.GET)
        if not form.is_valid():
            raise MAASAPIValidationError(form.errors)
        return render_networks_json(form.filter_subnets(Subnet.objects.all()))
示例#8
0
    def create(self, request):
        """Create a domain.

        :param name: Name of the domain.
        :param authoritative: Class type of the domain.
        """
        form = DomainForm(data=request.data)
        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
示例#9
0
 def test_returns_http_response(self):
     error = factory.make_string()
     exception = MAASAPIValidationError(error)
     response = exception.make_http_response()
     self.assertEqual(
         (http.client.BAD_REQUEST, error),
         (
             response.status_code,
             response.content.decode(settings.DEFAULT_CHARSET),
         ),
     )
示例#10
0
    def update(self, request, system_id, id):
        """@description-title Update a bcache
        @description Update bcache on a machine.

        Specifying both a device and a partition for a given role (cache or
        backing) is not allowed.

        @param (string) "{system_id}" [required=true] The machine's system_id.
        @param (string) "{id}" [required=true] The bcache id.

        @param (string) "name" [required=false] Name of the Bcache.

        @param (string) "uuid" [required=false] UUID of the Bcache.

        @param (string) "cache_set" [required=false] Cache set to replace
        current one.

        @param (string) "backing_device" [required=false] Backing block device
        to replace current one.

        @param (string) "backing_partition" [required=false] Backing partition
        to replace current one.

        @param (string) "cache_mode" [required=false] Cache mode:
        ``WRITEBACK``, ``WRITETHROUGH``, ``WRITEAROUND``.

        @success (http-status-code) "server-success" 200
        @success (json) "success-json" A JSON object containing the new bcache
        device.
        @success-example "success-json" [exkey=bcache-placeholder] placeholder
        text

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

        @error (http-status-code) "409" 409
        @error (content) "not-ready" The requested machine is not ready.
        """
        bcache = Bcache.objects.get_object_or_404(system_id, id, request.user,
                                                  NodePermission.admin)
        node = bcache.get_node()
        if node.status != NODE_STATUS.READY:
            raise NodeStateViolation(
                "Cannot update Bcache because the machine is not Ready.")
        form = UpdateBcacheForm(bcache, data=request.data)
        if form.is_valid():
            create_audit_event(EVENT_TYPES.NODE, ENDPOINT.API, request,
                               system_id, "Updated bcache.")
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
示例#11
0
    def delete(self, request, name):
        """Delete a script."""
        if name.isdigit():
            script = get_object_or_404(Script, id=int(name))
        else:
            script = get_object_or_404(Script, name=name)

        if script.default:
            raise MAASAPIValidationError("Unable to delete default script")

        script.delete()
        return rc.DELETED
示例#12
0
 def test_if_message_is_single_item_list_returns_only_first_message(self):
     errors = [factory.make_string()]
     exception = MAASAPIValidationError(errors)
     response = exception.make_http_response()
     self.expectThat(
         response.get("Content-Type"),
         Equals("text/plain; charset=%s" % settings.DEFAULT_CHARSET),
     )
     self.expectThat(
         response.content.decode(settings.DEFAULT_CHARSET),
         Equals(errors[0]),
     )
示例#13
0
 def test_returns_json_response_if_message_is_a_list(self):
     errors = [factory.make_string(), factory.make_string()]
     exception = MAASAPIValidationError(errors)
     response = exception.make_http_response()
     self.expectThat(
         response.get("Content-Type"),
         Equals("application/json; charset=%s" % settings.DEFAULT_CHARSET),
     )
     self.expectThat(
         response.content.decode(settings.DEFAULT_CHARSET),
         Equals(json.dumps(errors)),
     )
示例#14
0
    def update(self, request, system_id):
        """@description-title Update a region controller
        @description Updates a region controller with the given system_id.

        @param (string) "{system_id}" [required=true] The region controller's
        system_id.

        @param (string) "power_type" [required=false] The new power type for
        this region controller. If you use the default value, power_parameters
        will be set to the empty string.  Available to admin users.  See the
        `Power types`_ section for a list of the available power types.

        @param (string) "power_parameters_{param1}" [required=true] The new
        value for the 'param1' power parameter. Note that this is dynamic as
        the available parameters depend on the selected value of the region
        controller's power_type.  Available to admin users. See the `Power
        types`_ section for a list of the available power parameters for each
        power type.

        @param (boolean) "power_parameters_skip_check" [required=false] Whether
        or not the new power parameters for this region controller should be
        checked against the expected power parameters for the region
        controller's power type ('true' or 'false').  The default is 'false'.

        @param (string) "zone" [required=false] Name of a valid physical zone
        in which to place this region controller.

        @success (http-status-code) "200" 200
        @success (json) "success-json" A JSON object containing the updated
        region controller object.
        @success-example (json) "success-json" [exkey=update] placeholder text

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

        @error (http-status-code) "403" 403
        @error (content) "no-perms" The user does not have permission to
        update the region controller.
        @error-example "no-perms"
            This method is reserved for admin users.
        """
        region = self.model.objects.get_node_or_404(system_id=system_id,
                                                    user=request.user,
                                                    perm=NodePermission.admin)
        form = ControllerForm(data=request.data, instance=region)

        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
示例#15
0
    def create(self, request):
        """@description-title Create a DNS resource
        @description Create a DNS resource.

        @param (string) "fqdn" [required=false] Hostname (with domain) for the
        dnsresource.  Either ``fqdn`` or ``name`` and ``domain`` must be
        specified.  ``fqdn`` is ignored if either ``name`` or ``domain`` is
        given.

        @param (string) "name" [required=true] Hostname (without domain).

        @param (string) "domain" [required=true] Domain (name or id).

        @param (string) "address_ttl" [required=false] Default TTL for entries
        in this zone.

        @param (string) "ip_addresses" [required=false] Address (ip or id) to
        assign to the dnsresource. This creates an A or AAAA record,
        for each of the supplied ip_addresses, IPv4 or IPv6, respectively.

        @success (http-status-code) "server-success" 200
        @success (json) "success-json" A JSON object containing the new DNS
        resource object.
        @success-example "success-json" [exkey=dnsresources-create] placeholder
        text
        """
        data = request.data.copy()
        fqdn = data.get('fqdn', None)
        name = data.get('name', None)
        domainname = data.get('domain', None)
        # If the user gave us fqdn and did not give us name/domain, expand
        # fqdn.
        if domainname is None and name is None and fqdn is not None:
            # Assume that we're working with an address, since we ignore
            # rrtype and rrdata.
            (name, domainname) = separate_fqdn(fqdn, 'A')
            data['domain'] = domainname
            data['name'] = name
        # If the domain is a name, make it an id.
        if domainname is not None:
            if domainname.isdigit():
                domain = Domain.objects.get_domain_or_404(
                    domainname, user=request.user, perm=NodePermission.view)
            else:
                domain = Domain.objects.get_domain_or_404(
                    "name:%s" % domainname, user=request.user,
                    perm=NodePermission.view)
            data['domain'] = domain.id
        form = DNSResourceForm(data=data, request=request)
        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
示例#16
0
    def create(self, request):
        """Create a fabric.

        :param name: Name of the fabric.
        :param description: Description of the fabric.
        :param class_type: Class type of the fabric.
        """
        form = FabricForm(data=request.data)
        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
示例#17
0
    def update(self, request, system_id):
        """@description-title Update a rack controller
        @description Updates a rack controller with the given system_id.

        @param (string) "description" [required=false] The new description for
        this given rack controller.

        @param (string) "power_type" [required=false] The new power type for
        the given rack controller. If you use the default value,
        power_parameters will be set to an empty string. See the
        `Power types`_ section for a list of available power types. Note that
        only admin users can set this parameter.

        @param (string) "power_parameters_{param}" [required=true] The new
        value for the 'param' power parameter. This is a dynamic parameter
        that depends on the rack controller's power_type. See the
        `Power types`_ section for a list of available parameters based on
        power type. Note that only admin users can set these parameters.

        @param (boolean) "power_parameters_skip_check" [required=false] If
        true, the new power parameters for the given rack controller will be
        checked against the expected parameters for the rack controller's power
        type. Default is false.

        @param (string) "zone" [required=false] The name of a valid zone in
        which to place the given rack controller.

        @param (string) "domain" [required=false] The domain for this
        controller. If not given the default domain is used.

        @success (http-status-code) "200" 200
        @success (content) "success-json" A JSON object containing the updated
        rack-controller object.
        @success-example "success-json" [exkey=update] placeholder

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

        @error (http-status-code) "403" 403
        @error (content) "no-perms" This method is reserved for admin users.
        """
        rack = self.model.objects.get_node_or_404(system_id=system_id,
                                                  user=request.user,
                                                  perm=NodePermission.admin)
        form = ControllerForm(data=request.data, instance=rack)

        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
示例#18
0
    def update(self, request, id):
        """\
        Update the specified subnet.

        Please see the documentation for the 'create' operation for detailed
        descriptions of each parameter.

        Optional parameters
        -------------------

        name
          Name of the subnet.

        description
          Description of the subnet.

        vlan
          VLAN this subnet belongs to.

        space
          Space this subnet is in.

        cidr
          The network CIDR for this subnet.

        gateway_ip
          The gateway IP address for this subnet.

        rdns_mode
          How reverse DNS is handled for this subnet.

        allow_dns
          Configure MAAS DNS to allow DNS resolution from this subnet.

        allow_proxy
          Configure maas-proxy to allow requests from this subnet.

        dns_servers
          Comma-seperated list of DNS servers for this subnet.

        managed
          If False, MAAS should not manage this subnet. (Default: True)

        Returns 404 if the subnet is not found.
        """
        subnet = Subnet.objects.get_subnet_or_404(id, request.user,
                                                  NodePermission.admin)
        form = SubnetForm(instance=subnet, data=request.data)
        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
示例#19
0
    def update(self, request, system_id, id):
        """@description-title Update a volume group
        @description Update a volume group with the given id on the machine
        with the given system_id.

        @param (string) "{system_id}" [required=true] The machine system_id
        containing the volume group.
        @param (int) "{id}" [required=true] The id of the volume group.

        @param (string) "name" [required=false] Name of the volume group.

        @param (string) "uuid" [required=false] UUID of the volume group.

        @param (string) "add_block_devices" [required=false] Block devices to
        add to the volume group.

        @param (string) "remove_block_devices" [required=false] Block devices
        to remove from the volume group.

        @param (string) "add_partitions" [required=false] Partitions to add to
        the volume group.

        @param (string) "remove_partitions" [required=false] Partitions to
        remove from the volume group.

        @success (http-status-code) "server-success" 200
        @success (json) "success-json" A JSON object containing the requested
        volume group.
        @success-example "success-json" [exkey=vol-groups-update]
        placeholder text

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

        @error (http-status-code) "409" 409
        @error (content) "not-ready" The requested machine is not ready.
        """
        volume_group = VolumeGroup.objects.get_object_or_404(
            system_id, id, request.user, NodePermission.admin
        )
        node = volume_group.get_node()
        if node.status != NODE_STATUS.READY:
            raise NodeStateViolation(
                "Cannot update volume group because the machine is not Ready."
            )
        form = UpdateVolumeGroupForm(volume_group, data=request.data)
        if not form.is_valid():
            raise MAASAPIValidationError(form.errors)
        else:
            return form.save()
示例#20
0
    def create(self, request):
        """Create a new commissioning script.

        Each commissioning script is identified by a unique name.

        By convention the name should consist of a two-digit number, a dash,
        and a brief descriptive identifier consisting only of ASCII
        characters.  You don't need to follow this convention, but not doing
        so opens you up to risks w.r.t. encoding and ordering.  The name must
        not contain any whitespace, quotes, or apostrophes.

        A commissioning machine will run each of the scripts in lexicographical
        order.  There are no promises about how non-ASCII characters are
        sorted, or even how upper-case letters are sorted relative to
        lower-case letters.  So where ordering matters, use unique numbers.

        Scripts built into MAAS will have names starting with "00-maas" or
        "99-maas" to ensure that they run first or last, respectively.

        Usually a commissioning script will be just that, a script.  Ideally a
        script should be ASCII text to avoid any confusion over encoding.  But
        in some cases a commissioning script might consist of a binary tool
        provided by a hardware vendor.  Either way, the script gets passed to
        the commissioning machine in the exact form in which it was uploaded.

        :param name: Unique identifying name for the script.  Names should
            follow the pattern of "25-burn-in-hard-disk" (all ASCII, and with
            numbers greater than zero, and generally no "weird" characters).
        :param content: A script file, to be uploaded in binary form.  Note:
            this is not a normal parameter, but a file upload.  Its filename
            is ignored; MAAS will know it by the name you pass to the request.
        """
        content = Bin(get_content_parameter(request))
        data = request.data.copy()
        data["script"] = content
        data["script_type"] = SCRIPT_TYPE.COMMISSIONING
        form = ScriptForm(data=data)
        if form.is_valid():
            script = form.save(request)
            return {
                "name":
                script.name,
                "content":
                b64encode(script.script.data.encode()),
                "deprecated":
                ("The commissioning-scripts endpoint is deprecated. "
                 "Please use the node-scripts endpoint."),
                "resource_uri":
                reverse("commissioning_script_handler", args=[script.name]),
            }
        else:
            raise MAASAPIValidationError(form.errors)
示例#21
0
def filtered_nodes_list_from_request(request, model=None):
    """List Nodes visible to the user, optionally filtered by criteria.

    Nodes are sorted by id (i.e. most recent last).

    :param hostname: An optional hostname. Only events relating to the node
        with the matching hostname will be returned. This can be specified
        multiple times to get events relating to more than one node.
    :param mac_address: An optional MAC address. Only events relating to the
        node owning the specified MAC address will be returned. This can be
        specified multiple times to get events relating to more than one node.
    :param id: An optional list of system ids.  Only events relating to the
        nodes with matching system ids will be returned.
    :param domain: An optional name for a dns domain. Only events relating to
        the nodes in the domain will be returned.
    :param zone: An optional name for a physical zone. Only events relating to
        the nodes in the zone will be returned.
    :param agent_name: An optional agent name.  Only events relating to the
        nodes with matching agent names will be returned.
    """
    # Get filters from request.
    match_ids = get_optional_list(request.GET, 'id')

    match_macs = get_optional_list(request.GET, 'mac_address')
    if match_macs is not None:
        invalid_macs = [mac for mac in match_macs if MAC_RE.match(mac) is None]
        if len(invalid_macs) != 0:
            raise MAASAPIValidationError("Invalid MAC address(es): %s" %
                                         ", ".join(invalid_macs))

    if model is None:
        model = Node
    # Fetch nodes and apply filters.
    nodes = model.objects.get_nodes(request.user,
                                    NODE_PERMISSION.VIEW,
                                    ids=match_ids)
    if match_macs is not None:
        nodes = nodes.filter(interface__mac_address__in=match_macs)
    match_hostnames = get_optional_list(request.GET, 'hostname')
    if match_hostnames is not None:
        nodes = nodes.filter(hostname__in=match_hostnames)
    match_domains = get_optional_list(request.GET, 'domain')
    if match_domains is not None:
        nodes = nodes.filter(domain__name__in=match_domains)
    match_zone_name = request.GET.get('zone', None)
    if match_zone_name is not None:
        nodes = nodes.filter(zone__name=match_zone_name)
    match_agent_name = request.GET.get('agent_name', None)
    if match_agent_name is not None:
        nodes = nodes.filter(agent_name=match_agent_name)

    return nodes.order_by('id')
示例#22
0
    def set_default_gateway(self, request, system_id, id):
        """@description-title Set the default gateway on a machine
        @description Set the given interface id on the given system_id as the
        default gateway.

        If this interface has more than one subnet with a gateway IP in the
        same IP address family then specifying the ID of the link on
        this interface is required.

        @param (string) "{system_id}" [required=true] A system_id.

        @param (int) "{id}" [required=true] An interface id.

        @param (int) "link_id" [required=false] ID of the link on this
        interface to select the default gateway IP address from.

        @success (http-status-code) "server-success" 200
        @success (json) "success-json" A JSON object containing the updated
        interface object.
        @success-example "success-json" [exkey=interfaces-set-def-gateway]
        placeholder text

        @error (http-status-code) "400" 400
        @error (content) "400" If the interface has no ``AUTO`` or ``STATIC``
        links.

        @error (http-status-code) "404" 404
        @error (content) "not-found" The requested machine or interface is not
        found.
        @error-example "not-found"
            Not Found
        """
        interface = Interface.objects.get_interface_or_404(
            system_id,
            id,
            request.user,
            NodePermission.admin,
            NodePermission.edit,
        )
        node = interface.get_node()
        raise_error_if_controller(node, "link subnet")
        if node.node_type == NODE_TYPE.MACHINE:
            # This node needs to be in the correct state to modify
            # the interface.
            raise_error_for_invalid_state_on_allocated_operations(
                node, request.user, "set default gateway")
        form = InterfaceSetDefaultGatwayForm(instance=interface,
                                             data=request.data)
        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
示例#23
0
    def update(self, request, **kwargs):
        """PUT request.  Update a model instance.

        If the instance is not found, return 404.
        """
        instance = self._get_instance_or_404(**kwargs)
        form = self.model_form(instance=instance, data=request.data)
        if hasattr(form, 'use_perms') and form.use_perms():
            if not form.has_perm(request.user):
                raise PermissionDenied()
        if not form.is_valid():
            raise MAASAPIValidationError(form.errors)
        return form.save()
示例#24
0
 def update(self, request, name):
     """Update a commissioning script."""
     script = get_object_or_404(Script, name=name)
     content = Bin(get_content_parameter(request))
     data = request.data.copy()
     data["script"] = content
     data["script_type"] = SCRIPT_TYPE.COMMISSIONING
     form = ScriptForm(instance=script, data=data)
     if form.is_valid():
         form.save(request)
         return rc.ALL_OK
     else:
         raise MAASAPIValidationError(form.errors)
示例#25
0
    def create(self, request):
        """Create a new physical zone.

        :param name: Identifier-style name for the new zone.
        :type name: unicode
        :param description: Free-form description of the new zone.
        :type description: unicode
        """
        form = ZoneForm(request.data)
        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
示例#26
0
    def create(self, request):
        """Create a static route.

        :param source: Source subnet for the route.
        :param destination: Destination subnet for the route.
        :param gateway_ip: IP address of the gateway on the source subnet.
        :param metric: Weight of the route on a deployed machine.
        """
        form = StaticRouteForm(data=request.data)
        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
示例#27
0
文件: pods.py 项目: pingli-study/maas
    def create(self, request):
        """@description-title Create a pod
        @description Create or discover a new pod.

        @param (string) "type" [required=true] The type of pod to create:
        ``rsd`` or ``virsh``.
        @param (string) "power_address" [required=true] Address that gives
        MAAS access to the pod's power control. For example:
        ``qemu+ssh://172.16.99.2/system``.
        @param (string) "power_user" [required=true] Username to use for
        power control of the pod. Required for ``rsd`` pods or ``virsh``
        pods that do not have SSH set up for public-key authentication.
        @param (string) "power_pass" [required=true] Password to use for
        power control of the pod. Required for ``rsd`` pods or ``virsh``
        pods that do not have SSH set up for public-key authentication.
        @param (string) "name" [required=false] The new pod's name.
        @param (string) "zone" [required=false] The new pod's zone.
        @param (string) "pool" [required=false] The name of the resource
        pool the new pod will belong to. Machines composed from this pod
        will be assigned to this resource pool by default.
        @param (string) "tags" [required=false] A tag or list of tags (
        comma delimited) to assign to the new pod.

        @success (http-status-code) "200" 200
        @success (json) "success-json" A JSON object containing a pod object.
        @success-example (json) "success-json" [exkey=create] placeholder text

        @error (http-status-code) "404" 404
        @error (content) "not-found" No pod with that ID can be found.
        @error-example "not-found"
            Not Found

        @error (http-status-code) "403" 403
        @error (content) "no-perms" The user does not have the permissions
        to delete the pod.
        @error-example (content) "no-perms"
            This method is reserved for admin users.

        @error (http-status-code) "503" 503
        @error (content) "failed-login" MAAS could not find the RSD
        pod or could not log into the virsh console.
        @error-example (content) "failed-login"
            Failed talking to pod: Failed to login to virsh console.
        """
        if not request.user.has_perm(PodPermission.create):
            raise PermissionDenied()
        form = PodForm(data=request.data, request=request)
        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
示例#28
0
    def create(self, request, system_id):
        """@description-title Set up a RAID
        @description Set up a RAID on a machine with the given system_id.

        @param (string) "{system_id}" [required=true] The system_id of the
        machine on which to set up the RAID.

        @param (string) "name" [required=false] Name of the RAID.

        @param (string) "uuid" [required=false] UUID of the RAID.

        @param (int) "level" [required=true] RAID level.

        @param (string) "block_devices" [required=false] Block devices to add
        to the RAID.

        @param (string) "spare_devices" [required=false] Spare block devices to
        add to the RAID.

        @param (string) "partitions" [required=false] Partitions to add to the
        RAID.

        @param (string) "spare_partitions" [required=false] Spare partitions to
        add to the RAID.

        @success (http-status-code) "200" 200
        @success (json) "success-json" A JSON object containing information
        about the new RAID.
        @success-example "success-json" [exkey=raids-placeholder] placeholder
        text

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

        @error (http-status-code) "409" 409
        @error (content) "not-ready" The requested machine is not ready.
        @error-example "not-ready"
            Cannot create RAID because the machine is not Ready.
        """
        machine = Machine.objects.get_node_or_404(system_id, request.user,
                                                  NodePermission.admin)
        if machine.status != NODE_STATUS.READY:
            raise NodeStateViolation(
                "Cannot create RAID because the machine is not Ready.")
        form = CreateRaidForm(machine, data=request.data)
        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
示例#29
0
    def revert(self, request, id):
        """Revert the value of a DHCP snippet to an earlier revision.

        :param to: What revision in the DHCP snippet's history to revert to.
            This can either be an ID or a negative number representing how far
            back to go.
        :type to: integer

        Returns 404 if the DHCP snippet is not found.
        """
        revert_to = request.data.get('to')
        if revert_to is None:
            raise MAASAPIValidationError('You must specify where to revert to')
        try:
            revert_to = int(revert_to)
        except ValueError:
            raise MAASAPIValidationError("%s is an invalid 'to' value" %
                                         revert_to)

        dhcp_snippet = DHCPSnippet.objects.get_dhcp_snippet_or_404(id)
        try:

            def gc_hook(value):
                dhcp_snippet.value = value
                dhcp_snippet.save()

            dhcp_snippet.value.revert(revert_to, gc_hook=gc_hook)
            create_audit_event(
                EVENT_TYPES.SETTINGS,
                ENDPOINT.API,
                request,
                None,
                description=("DHCP snippet '%s' reverted to revision '%s'" %
                             (dhcp_snippet.name, revert_to) +
                             " by '%(username)s'."))
            return dhcp_snippet
        except ValueError as e:
            raise MAASAPIValidationError(e.args[0])
示例#30
0
    def test(self, request, system_id):
        """@description-title Begin testing process for a node
        @description Begins the testing process for a given node.

        A node in the 'ready', 'allocated', 'deployed', 'broken', or any failed
        state may run tests. If testing is started and successfully passes from
        'broken' or any failed state besides 'failed commissioning' the node
        will be returned to a ready state. Otherwise the node will return to
        the state it was when testing started.

        @param (int) "enable_ssh" [required=false] Whether to enable SSH for
        the testing environment using the user's SSH key(s). 0 == false. 1 ==
        true.

        @param (string) "testing_scripts" [required=false] A comma-separated
        list of testing script names and tags to be run. By default all tests
        tagged 'commissioning' will be run.

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

        @error (http-status-code) "404" 404
        @error (content) "not-found" The requested node is not found.
        @error-example "not-found"
            Not Found
        """
        node = self.model.objects.get_node_or_404(
            system_id=system_id, user=request.user, perm=NodePermission.admin)
        form = TestForm(instance=node, user=request.user, data=request.data)
        if form.is_valid():
            try:
                return form.save()
            except NoScriptsFound:
                raise MAASAPIValidationError('No testing scripts found!')
        else:
            raise MAASAPIValidationError(form.errors)