incus-mirror/cmd/incusd/instance_bitmap.go
Stéphane Graber 5a4709d663
incusd: Document baseline error codes for endpoints using SmartError
Signed-off-by: Stéphane Graber <stgraber@stgraber.org>
2026-07-28 18:32:51 -04:00

123 lines
3.0 KiB
Go

package main
import (
"encoding/json"
"errors"
"fmt"
"net/http"
internalInstance "github.com/lxc/incus/v7/internal/instance"
deviceConfig "github.com/lxc/incus/v7/internal/server/device/config"
"github.com/lxc/incus/v7/internal/server/instance"
"github.com/lxc/incus/v7/internal/server/instance/instancetype"
"github.com/lxc/incus/v7/internal/server/request"
"github.com/lxc/incus/v7/internal/server/response"
"github.com/lxc/incus/v7/shared/api"
)
// swagger:operation POST /1.0/instances/{name}/bitmaps instances instance_bitmaps_post
//
// Create a bitmap
//
// Creates a new bitmap.
//
// ---
// consumes:
// - application/json
// produces:
// - application/json
// parameters:
// - in: path
// name: name
// description: Instance name
// type: string
// required: true
// - in: query
// name: project
// description: Project name
// type: string
// example: default
// - in: body
// name: bitmap
// description: Bitmap request
// required: false
// schema:
// $ref: "#/definitions/StorageVolumeBitmapsPost"
// responses:
// "200":
// $ref: "#/responses/EmptySyncResponse"
// "400":
// $ref: "#/responses/BadRequest"
// "403":
// $ref: "#/responses/Forbidden"
// "404":
// $ref: "#/responses/NotFound"
// "409":
// $ref: "#/responses/Conflict"
// "500":
// $ref: "#/responses/InternalServerError"
func instanceBitmapsPost(d *Daemon, r *http.Request) response.Response {
s := d.State()
projectName := request.ProjectParam(r)
cname, err := pathVar(r, "name")
if err != nil {
return response.SmartError(err)
}
if internalInstance.IsSnapshot(cname) {
return response.BadRequest(errors.New("Invalid instance name"))
}
// Handle requests targeted to an instance on a different node
resp, err := forwardedResponseIfInstanceIsRemote(s, r, projectName, cname)
if err != nil {
return response.SmartError(err)
}
if resp != nil {
return resp
}
inst, err := instance.LoadByProjectAndName(s, projectName, cname)
if err != nil {
return response.SmartError(err)
}
if !inst.IsRunning() {
return response.BadRequest(fmt.Errorf("Creating bitmaps requires the instance to be running"))
}
if inst.Type() != instancetype.VM {
return response.BadRequest(fmt.Errorf("Only VMs are supported."))
}
req := api.StorageVolumeBitmapsPost{}
err = json.NewDecoder(r.Body).Decode(&req)
if err != nil {
return response.BadRequest(err)
}
rootDiskName, _, err := internalInstance.GetRootDiskDevice(inst.ExpandedDevices().CloneNative())
if err != nil {
return response.BadRequest(fmt.Errorf("Failed getting instance root disk: %w", err))
}
devNames := []string{rootDiskName}
err = inst.ForEachDependentDiskType(func(dev deviceConfig.DeviceNamed) error {
devNames = append(devNames, dev.Name)
return nil
})
if err != nil {
return response.SmartError(err)
}
err = inst.CreateBitmap(devNames, req)
if err != nil {
return response.SmartError(err)
}
return response.EmptySyncResponse
}