예제 #1
0
    def update(self, request, system_id, id):
        """Update block device on a machine.

        Machines must have a status of Ready to have access to all options.
        Machines with Deployed status can only have the name, model, serial,
        and/or id_path updated for a block device. This is intented to allow a
        bad block device to be replaced while the machine remains deployed.

        Fields for physical block device:

        :param name: Name of the block device.
        :param model: Model of the block device.
        :param serial: Serial number of the block device.
        :param id_path: (optional) Only used if model and serial cannot be \
            provided. This should be a path that is fixed and doesn't change \
            depending on the boot order or kernel version.
        :param size: Size of the block device.
        :param block_size: Block size of the block device.

        Fields for virtual block device:

        :param name: Name of the block device.
        :param uuid: UUID of the block device.
        :param size: Size of the block device. (Only allowed for logical \
            volumes.)

        Returns 404 if the machine or block device is not found.
        Returns 403 if the user is not allowed to update the block device.
        Returns 409 if the machine is not Ready.
        """
        device = BlockDevice.objects.get_block_device_or_404(
            system_id, id, request.user, NODE_PERMISSION.ADMIN)
        node = device.get_node()
        if node.status not in [NODE_STATUS.READY, NODE_STATUS.DEPLOYED]:
            raise NodeStateViolation(
                "Cannot update block device because the machine is not Ready.")
        if node.status == NODE_STATUS.DEPLOYED:
            if device.type == 'physical':
                form = UpdateDeployedPhysicalBlockDeviceForm(instance=device,
                                                             data=request.data)
            else:
                raise NodeStateViolation(
                    "Cannot update virtual block device because the machine "
                    "is Deployed.")
        else:
            if device.type == 'physical':
                form = UpdatePhysicalBlockDeviceForm(instance=device,
                                                     data=request.data)
            elif device.type == 'virtual':
                form = UpdateVirtualBlockDeviceForm(instance=device,
                                                    data=request.data)
            else:
                raise ValueError('Cannot update block device of type %s' %
                                 device.type)
        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
예제 #2
0
파일: bcache.py 프로젝트: th3architect/maas
    def delete(self, request, system_id, id):
        """@description-title Delete a bcache
        @description Delete bcache on a machine.

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

        @success (http-status-code) "server-success" 204

        @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 delete Bcache because the machine is not Ready.")
        bcache.delete()
        create_audit_event(
            EVENT_TYPES.NODE,
            ENDPOINT.API,
            request,
            system_id,
            "Deleted bcache.",
        )
        return rc.DELETED
예제 #3
0
파일: bcache.py 프로젝트: jamal-fuma/maas
    def create(self, request, system_id):
        """Creates a Bcache.

        :param name: Name of the Bcache.
        :param uuid: UUID of the Bcache.
        :param cache_set: Cache set.
        :param backing_device: Backing block device.
        :param backing_partition: Backing partition.
        :param cache_mode: Cache mode (WRITEBACK, WRITETHROUGH, WRITEAROUND).

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

        Returns 404 if the machine is not found.
        Returns 409 if 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 Bcache because the machine is not Ready.")
        form = CreateBcacheForm(machine, data=request.data)
        if form.is_valid():
            create_audit_event(
                EVENT_TYPES.NODE, ENDPOINT.API, request,
                system_id, "Created bcache.")
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
예제 #4
0
파일: bcache.py 프로젝트: jamal-fuma/maas
    def update(self, request, system_id, id):
        """Update bcache on a machine.

        :param name: Name of the Bcache.
        :param uuid: UUID of the Bcache.
        :param cache_set: Cache set to replace current one.
        :param backing_device: Backing block device to replace current one.
        :param backing_partition: Backing partition to replace current one.
        :param cache_mode: Cache mode (writeback, writethrough, writearound).

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

        Returns 404 if the machine or the bcache is not found.
        Returns 409 if the 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)
예제 #5
0
    def delete(self, request, system_id, id):
        """@description-title Delete volume group
        @description Delete a volume group with the given id from 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.

        @success (http-status-code) "server-success" 204

        @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 delete volume group because the machine is not Ready.")
        volume_group.delete()
        return rc.DELETED
예제 #6
0
파일: partitions.py 프로젝트: zhangrb/maas
    def delete(self, request, system_id, device_id, id):
        """@description-title Delete a partition
        @description Delete the partition from machine system_id and device
        device_id with the given partition id.

        @param (string) "{system_id}" [required=true] The system_id.
        @param (int) "{device_id}" [required=true] The block device_id.
        @param (int) "{id}" [required=true] The partition id.

        @success (http-status-code) "server-success" 204

        @error (http-status-code) "404" 404
        @error (content) "not-found" The requested machine, device or partition
        is not found.
        @error-example "not-found"
            Not Found
        """
        device = BlockDevice.objects.get_block_device_or_404(
            system_id, device_id, request.user, NodePermission.admin)
        partition_table = get_object_or_404(PartitionTable,
                                            block_device=device)
        partition = get_partition_by_id_or_name__or_404(id, partition_table)
        node = device.get_node()
        if node.status != NODE_STATUS.READY:
            raise NodeStateViolation(
                "Cannot delete block device because the node is not Ready.")
        partition.delete()
        return rc.DELETED
예제 #7
0
    def update(self, request, system_id, id):
        """Read volume group on a machine.

        :param name: Name of the volume group.
        :param uuid: UUID of the volume group.
        :param add_block_devices: Block devices to add to the volume group.
        :param remove_block_devices: Block devices to remove from the
            volume group.
        :param add_partitions: Partitions to add to the volume group.
        :param remove_partitions: Partitions to remove from the volume group.

        Returns 404 if the machine or volume group is not found.
        Returns 409 if the 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()
예제 #8
0
    def delete(self, request, system_id, id):
        """@description-title Delete a RAID
        @description Delete a RAID with the given id on a machine with the
        given system_id.

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

        @success (http-status-code) "204" 204

        @error (http-status-code) "404" 404
        @error (content) "not-found" The requested machine or RAID 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.
        """
        raid = RAID.objects.get_object_or_404(system_id, id, request.user,
                                              NodePermission.admin)
        node = raid.get_node()
        if node.status != NODE_STATUS.READY:
            raise NodeStateViolation(
                "Cannot delete RAID because the machine is not Ready.")
        raid.delete()
        return rc.DELETED
예제 #9
0
    def delete_logical_volume(self, request, system_id, id):
        """Delete a logical volume in the volume group.

        :param id: ID of the logical volume.

        Returns 403 if no logical volume with id.
        Returns 404 if the machine or volume group is not found.
        Returns 409 if the 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 delete logical volume because the machine is not "
                "Ready.")
        volume_id = get_mandatory_param(request.data, 'id')
        try:
            logical_volume = volume_group.virtual_devices.get(id=volume_id)
        except VirtualBlockDevice.DoesNotExist:
            # Ignore if it doesn't exists, we still return DELETED.
            pass
        else:
            logical_volume.delete()
        return rc.DELETED
예제 #10
0
    def delete(self, request, system_id, id):
        """@description-title Delete a block device
        @description Delete block device on a given machine.

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

        @success (http-status-code) "204" 204

        @error (http-status-code) "403" 403
        @error (content) "no-perms" The user does not have permissions to
        delete the block device.

        @error (http-status-code) "404" 404
        @error (content) "not-found" The requested machine or block device 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.
        """
        device = BlockDevice.objects.get_block_device_or_404(
            system_id, id, request.user, NodePermission.admin)
        node = device.get_node()
        if node.status != NODE_STATUS.READY:
            raise NodeStateViolation(
                "Cannot delete block device because the machine is not Ready.")
        device.delete()
        return rc.DELETED
예제 #11
0
    def set_owner_data(self, request, system_id):
        """@description-title Set key=value data
        @description Set key=value data for the current owner.

        Pass any key=value form data to this method to add, modify, or remove.
        A key is removed when the value for that key is set to an empty string.

        This operation will not remove any previous keys unless explicitly
        passed with an empty string. All owner data is removed when the machine
        is no longer allocated to a user.

        @param (string) "key" [required=true] ``key`` can be any string value.

        @success (http-status-code) "204" 204

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

        @error (http-status-code) "403" 403
        @error (content) "no-perms" The user does not have set the zone.
        """
        node = self.model.objects.get_node_or_404(user=request.user,
                                                  system_id=system_id,
                                                  perm=NodePermission.edit)
        if node.owner_id != request.user.id:
            raise NodeStateViolation(
                "Cannot set owner data: it hasn't been allocated.")
        owner_data = {
            key: None if value == "" else value
            for key, value in request.POST.items() if key != "op"
        }
        OwnerData.objects.set_owner_data(node, owner_data)
        return node
예제 #12
0
    def update(self, request, system_id, id):
        """Update RAID on a machine.

        :param name: Name of the RAID.
        :param uuid: UUID of the RAID.
        :param add_block_devices: Block devices to add to the RAID.
        :param remove_block_devices: Block devices to remove from the RAID.
        :param add_spare_devices: Spare block devices to add to the RAID.
        :param remove_spare_devices: Spare block devices to remove
               from the RAID.
        :param add_partitions: Partitions to add to the RAID.
        :param remove_partitions: Partitions to remove from the RAID.
        :param add_spare_partitions: Spare partitions to add to the RAID.
        :param remove_spare_partitions: Spare partitions to remove from the
               RAID.

        Returns 404 if the machine or RAID is not found.
        Returns 409 if the machine is not Ready.
        """
        raid = RAID.objects.get_object_or_404(system_id, id, request.user,
                                              NodePermission.admin)
        node = raid.get_node()
        if node.status != NODE_STATUS.READY:
            raise NodeStateViolation(
                "Cannot update RAID because the machine is not Ready.")
        form = UpdateRaidForm(raid, data=request.data)
        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
예제 #13
0
    def delete(self, request, system_id, id):
        """@description-title Delete a bcache set
        @description Delete bcache cache set on a machine.

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

        @success (http-status-code) "server-success" 204

        @error (http-status-code) "400" 400
        @error (content) "not-ready" The cache set is in use.

        @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.
        """
        cache_set = CacheSet.objects.get_cache_set_or_404(
            system_id, id, request.user, NodePermission.admin)
        node = cache_set.get_node()
        if node.status != NODE_STATUS.READY:
            raise NodeStateViolation(
                "Cannot delete cache set because the machine is not Ready.")
        if cache_set.filesystemgroup_set.exists():
            raise MAASAPIBadRequest(
                "Cannot delete cache set; it's currently in use.")
        else:
            cache_set.delete()
            create_audit_event(EVENT_TYPES.NODE, ENDPOINT.API, request,
                               system_id, "Deleted bcache cache set.")
            return rc.DELETED
예제 #14
0
파일: bcache.py 프로젝트: th3architect/maas
    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)
예제 #15
0
def raise_error_for_invalid_state_on_allocated_operations(
        node, user, operation):
    if node.status not in [NODE_STATUS.READY, NODE_STATUS.ALLOCATED]:
        raise NodeStateViolation(
            "Cannot %s block device because the machine is not Ready "
            "or Allocated." % operation)
    if node.status == NODE_STATUS.READY and not user.is_superuser:
        raise PermissionDenied(
            "Cannot %s block device because you don't have the "
            "permissions on a Ready machine." % operation)
예제 #16
0
파일: api.py 프로젝트: cloudbase/maas
    def signal(self, request, version=None, mac=None):
        """Signal commissioning status.

        A commissioning node can call this to report progress of the
        commissioning process to the metadata server.

        Calling this from a node that is not Commissioning, Ready, or
        Failed Tests is an error.  Signaling completion more than once is not
        an error; all but the first successful call are ignored.

        :param status: A commissioning status code.  This can be "OK" (to
            signal that commissioning has completed successfully), or "FAILED"
            (to signal failure), or "WORKING" (for progress reports).
        :param script_result: If this call uploads files, this parameter must
            be provided and will be stored as the return value for the script
            which produced these files.
        :param error: An optional error string.  If given, this will be stored
            (overwriting any previous error string), and displayed in the MAAS
            UI.  If not given, any previous error string will be cleared.
        """
        node = get_queried_node(request, for_mac=mac)
        status = get_mandatory_param(request.POST, 'status')
        if node.status not in self.signalable_states:
            raise NodeStateViolation(
                "Node wasn't commissioning (status is %s)"
                % NODE_STATUS_CHOICES_DICT[node.status])

        if status not in self.signaling_statuses:
            raise MAASAPIBadRequest(
                "Unknown commissioning status: '%s'" % status)

        if node.status != NODE_STATUS.COMMISSIONING:
            # Already registered.  Nothing to be done.
            return rc.ALL_OK

        self._store_commissioning_results(node, request)
        store_node_power_parameters(node, request)

        target_status = self.signaling_statuses.get(status)
        if target_status in (None, node.status):
            # No status change.  Nothing to be done.
            return rc.ALL_OK

        node.status = target_status
        # When moving to a terminal state, remove the allocation.
        node.owner = None
        node.error = request.POST.get('error', '')

        # When moving to a successful terminal state, recalculate tags.
        populate_tags_for_single_node(Tag.objects.all(), node)

        # Done.
        node.save()
        return rc.ALL_OK
예제 #17
0
 def _preflight_special_filesystem_modifications(self, op, machine):
     """Check that `machine` is okay for special fs modifications."""
     if reload_object(self.user).is_superuser:
         statuses_permitted = {NODE_STATUS.READY, NODE_STATUS.ALLOCATED}
     else:
         statuses_permitted = {NODE_STATUS.ALLOCATED}
     if machine.status not in statuses_permitted:
         status_names = sorted(title for value, title in NODE_STATUS_CHOICES
                               if value in statuses_permitted)
         raise NodeStateViolation(
             "Cannot %s the filesystem because the machine is not %s." %
             (op, " or ".join(status_names)))
예제 #18
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()
예제 #19
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)
예제 #20
0
    def delete(self, request, system_id, id):
        """Delete RAID on a machine.

        Returns 404 if the machine or RAID is not found.
        Returns 409 if the machine is not Ready.
        """
        raid = RAID.objects.get_object_or_404(system_id, id, request.user,
                                              NodePermission.admin)
        node = raid.get_node()
        if node.status != NODE_STATUS.READY:
            raise NodeStateViolation(
                "Cannot delete RAID because the machine is not Ready.")
        raid.delete()
        return rc.DELETED
예제 #21
0
파일: bcache.py 프로젝트: zeronewb/maas
    def delete(self, request, system_id, id):
        """Delete bcache on a machine.

        Returns 404 if the machine or bcache is not found.
        Returns 409 if the machine is not Ready.
        """
        bcache = Bcache.objects.get_object_or_404(system_id, id, request.user,
                                                  NODE_PERMISSION.ADMIN)
        node = bcache.get_node()
        if node.status != NODE_STATUS.READY:
            raise NodeStateViolation(
                "Cannot delete Bcache because the machine is not Ready.")
        bcache.delete()
        return rc.DELETED
예제 #22
0
    def delete(self, request, system_id, id):
        """Delete volume group on a machine.

        Returns 404 if the machine or volume group is not found.
        Returns 409 if the 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 delete volume group because the machine is not Ready.")
        volume_group.delete()
        return rc.DELETED
예제 #23
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:
            node.start(request.user, user_data=user_data, comment=comment)
        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
예제 #24
0
    def delete(self, request, system_id, id):
        """Delete block device on a machine.

        Returns 404 if the machine or block device is not found.
        Returns 403 if the user is not allowed to delete the block device.
        Returns 409 if the machine is not Ready.
        """
        device = BlockDevice.objects.get_block_device_or_404(
            system_id, id, request.user, NODE_PERMISSION.ADMIN)
        node = device.get_node()
        if node.status != NODE_STATUS.READY:
            raise NodeStateViolation(
                "Cannot delete block device because the machine is not Ready.")
        device.delete()
        return rc.DELETED
예제 #25
0
파일: node.py 프로젝트: cloudbase/maas
 def clean_status(self):
     """Check a node's status transition against the node-status FSM."""
     old_status = get_db_state(self, 'status')
     if self.status == old_status:
         # No transition is always a safe transition.
         pass
     elif self.status in NODE_TRANSITIONS.get(old_status, ()):
         # Valid transition.
         pass
     else:
         # Transition not permitted.
         error_text = "Invalid transition: %s -> %s." % (
             NODE_STATUS_CHOICES_DICT.get(old_status, "Unknown"),
             NODE_STATUS_CHOICES_DICT.get(self.status, "Unknown"),
         )
         raise NodeStateViolation(error_text)
예제 #26
0
    def delete(self, request, system_id, device_id, id):
        """Delete partition.

        Returns 404 if the node, block device, or partition are not found.
        """
        device = BlockDevice.objects.get_block_device_or_404(
            system_id, device_id, request.user, NODE_PERMISSION.ADMIN)
        partition_table = get_object_or_404(PartitionTable,
                                            block_device=device)
        partition = get_partition_by_id_or_name__or_404(id, partition_table)
        node = device.get_node()
        if node.status != NODE_STATUS.READY:
            raise NodeStateViolation(
                "Cannot delete block device because the node is not Ready.")
        partition.delete()
        return rc.DELETED
예제 #27
0
    def create(self, request, system_id):
        """@description-title Create a VMFS datastore.
        @description Create a VMFS datastore belonging to a machine with the
        given system_id.

        Note that at least one valid block device or partition is required.

        @param (string) "{system_id}" [required=true] The machine system_id on
        which to create the VMFS datastore.

        @param (string) "name" [required=true] Name of the VMFS datastore.

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

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

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

        @success (http-status-code) "server-success" 200
        @success (json) "success-json" A JSON object containing the new VMFS
        datastore.
        @success-example "success-json" [exkey=vmfs-datastores-create]
        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.
        """
        machine = Machine.objects.get_node_or_404(
            system_id, request.user, NodePermission.admin
        )
        if machine.status != NODE_STATUS.READY:
            raise NodeStateViolation(
                "Cannot create VMFS group because the machine is not Ready."
            )
        form = CreateVMFSForm(machine, data=request.data)
        if not form.is_valid():
            raise MAASAPIValidationError(form.errors)
        else:
            return form.save()
예제 #28
0
    def update(self, request, system_id, id):
        """@description-title Update a bcache set
        @description Update bcache cache set on a machine.

        Note: specifying both a cache_device and a cache_partition is not
        allowed.

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

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

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

        @success (http-status-code) "server-success" 200
        @success (json) "success-json" A JSON object containing a bcache set.
        @success-example "success-json" [exkey=bcache-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.
        """
        cache_set = CacheSet.objects.get_cache_set_or_404(
            system_id, id, request.user, NodePermission.admin)
        node = cache_set.get_node()
        if node.status != NODE_STATUS.READY:
            raise NodeStateViolation(
                "Cannot update cache set because the machine is not Ready.")
        form = UpdateCacheSetForm(cache_set, data=request.data)
        if form.is_valid():
            create_audit_event(
                EVENT_TYPES.NODE,
                ENDPOINT.API,
                request,
                system_id,
                "Updated bcache cache set.",
            )
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
예제 #29
0
파일: bcache.py 프로젝트: jamal-fuma/maas
    def delete(self, request, system_id, id):
        """Delete bcache on a machine.

        Returns 404 if the machine or bcache is not found.
        Returns 409 if the 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 delete Bcache because the machine is not Ready.")
        bcache.delete()
        create_audit_event(
            EVENT_TYPES.NODE, ENDPOINT.API, request,
            system_id, "Deleted bcache.")
        return rc.DELETED
예제 #30
0
    def create_logical_volume(self, request, system_id, id):
        """@description-title Create a logical volume
        @description Create a logical volume in the 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=true] Name of the logical volume.

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

        @param (string) "size" [required=true] Size of the logical volume. Must
        be larger than or equal to 4,194,304 bytes. E.g. ``4194304``.

        @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-create-log-vol]
        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 create logical volume because the machine is not "
                "Ready."
            )
        form = CreateLogicalVolumeForm(volume_group, data=request.data)
        if not form.is_valid():
            raise MAASAPIValidationError(form.errors)
        else:
            return form.save()