Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Snapshot addons #313

Merged
merged 9 commits into from
Mar 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cli/command/create/create-snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ var (
if err != nil {
return
}
err = config.CreateSnapshot(client, vmr)
err = config.Create(client, vmr)
if err != nil {
return
}
Expand Down
2 changes: 1 addition & 1 deletion cli/command/delete/delete-snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var (
RunE: func(cmd *cobra.Command, args []string) (err error) {
id := cli.ValidateIntIDset(args, "GuestID")
snapName := cli.RequiredIDset(args, 1, "SnapshotName")
_, err = proxmox.DeleteSnapshot(cli.NewClient(), proxmox.NewVmRef(id), proxmox.SnapshotName(snapName))
_, err = proxmox.SnapshotName(snapName).Delete(cli.NewClient(), proxmox.NewVmRef(id))
if err != nil {
return
}
Expand Down
2 changes: 1 addition & 1 deletion cli/command/guest/guest-rollback.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var guest_rollbackCmd = &cobra.Command{
RunE: func(cmd *cobra.Command, args []string) (err error) {
vmr := proxmox.NewVmRef(cli.ValidateIntIDset(args, "GuestID"))
snapName := cli.RequiredIDset(args, 1, "SnapshotName")
_, err = proxmox.RollbackSnapshot(cli.NewClient(), vmr, snapName)
_, err = proxmox.SnapshotName(snapName).Rollback(cli.NewClient(), vmr)
if err == nil {
fmt.Fprintf(GuestCmd.OutOrStdout(), "Guest with id (%d) has been rolled back to snapshot (%s)\n", vmr.VmId(), snapName)
}
Expand Down
2 changes: 1 addition & 1 deletion cli/command/update/update-snapshotdescription.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var update_snapshotCmd = &cobra.Command{
id := cli.ValidateIntIDset(args, "GuestID")
snapName := cli.RequiredIDset(args, 1, "SnapshotName")
des := cli.OptionalIDset(args, 2)
err = proxmox.UpdateSnapshotDescription(cli.NewClient(), proxmox.NewVmRef(id), proxmox.SnapshotName(snapName), des)
err = proxmox.SnapshotName(snapName).UpdateDescription(cli.NewClient(), proxmox.NewVmRef(id), des)
if err != nil {
return
}
Expand Down
2 changes: 1 addition & 1 deletion proxmox/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,7 @@ func (c *Client) ListQemuSnapshot(vmr *VmRef) (taskResponse map[string]interface

// DEPRECATED superseded by RollbackSnapshot()
func (c *Client) RollbackQemuVm(vmr *VmRef, snapshot string) (exitStatus string, err error) {
return RollbackSnapshot(c, vmr, snapshot)
return RollbackSnapshot(c, vmr, SnapshotName(snapshot))
}

// DEPRECATED SetVmConfig - send config options
Expand Down
109 changes: 75 additions & 34 deletions proxmox/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,31 @@ func (config ConfigSnapshot) mapToApiValues() map[string]interface{} {
}
}

func (config ConfigSnapshot) CreateSnapshot(c *Client, vmr *VmRef) (err error) {
err = c.CheckVmRef(vmr)
if err != nil {
// Creates a snapshot and validates the input
func (config ConfigSnapshot) Create(c *Client, vmr *VmRef) (err error) {
if err = c.CheckVmRef(vmr); err != nil {
return
}
err = config.Validate()
if err != nil {
if err = config.Validate(); err != nil {
return
}
return config.Create_Unsafe(c, vmr)
}

// Create a snapshot without validating the input, use ConfigSnapshot.Create() to validate the input.
func (config ConfigSnapshot) Create_Unsafe(c *Client, vmr *VmRef) error {
params := config.mapToApiValues()
_, err = c.PostWithTask(params, "/nodes/"+vmr.node+"/"+vmr.vmType+"/"+strconv.Itoa(vmr.vmId)+"/snapshot/")
_, err := c.PostWithTask(params, "/nodes/"+vmr.node+"/"+vmr.vmType+"/"+strconv.Itoa(vmr.vmId)+"/snapshot/")
if err != nil {
params, _ := json.Marshal(&params)
return fmt.Errorf("error creating Snapshot: %v, (params: %v)", err, string(params))
}
return
return nil
}

// deprecated use ConfigSnapshot.Create() instead
func (config ConfigSnapshot) CreateSnapshot(c *Client, vmr *VmRef) error {
return config.Create(c, vmr)
}

func (config ConfigSnapshot) Validate() error {
Expand All @@ -48,44 +57,25 @@ func (config ConfigSnapshot) Validate() error {
type rawSnapshots []interface{}

func ListSnapshots(c *Client, vmr *VmRef) (rawSnapshots, error) {
err := c.CheckVmRef(vmr)
if err != nil {
if err := c.CheckVmRef(vmr); err != nil {
return nil, err
}
return c.GetItemConfigInterfaceArray("/nodes/"+vmr.node+"/"+vmr.vmType+"/"+strconv.Itoa(vmr.vmId)+"/snapshot/", "Guest", "SNAPSHOTS")
}

// Can only be used to update the description of an already existing snapshot
// Updates the description of the specified snapshot, same as SnapshotName.UpdateDescription()
func UpdateSnapshotDescription(c *Client, vmr *VmRef, snapshot SnapshotName, description string) (err error) {
err = c.CheckVmRef(vmr)
if err != nil {
return
}
err = snapshot.Validate()
if err != nil {
return
}
return c.Put(map[string]interface{}{"description": description}, "/nodes/"+vmr.node+"/"+vmr.vmType+"/"+strconv.Itoa(vmr.vmId)+"/snapshot/"+string(snapshot)+"/config")
return snapshot.UpdateDescription(c, vmr, description)
}

// Deletes a snapshot, same as SnapshotName.Delete()
func DeleteSnapshot(c *Client, vmr *VmRef, snapshot SnapshotName) (exitStatus string, err error) {
err = c.CheckVmRef(vmr)
if err != nil {
return
}
err = snapshot.Validate()
if err != nil {
return
}
return c.DeleteWithTask("/nodes/" + vmr.node + "/" + vmr.vmType + "/" + strconv.Itoa(vmr.vmId) + "/snapshot/" + string(snapshot))
return snapshot.Delete(c, vmr)
}

func RollbackSnapshot(c *Client, vmr *VmRef, snapshot string) (exitStatus string, err error) {
err = c.CheckVmRef(vmr)
if err != nil {
return
}
return c.PostWithTask(nil, "/nodes/"+vmr.node+"/"+vmr.vmType+"/"+strconv.Itoa(vmr.vmId)+"/snapshot/"+snapshot+"/rollback")
// Rollback to a snapshot, same as SnapshotName.Rollback()
func RollbackSnapshot(c *Client, vmr *VmRef, snapshot SnapshotName) (exitStatus string, err error) {
return snapshot.Rollback(c, vmr)
}

// Used for formatting the output when retrieving snapshots
Expand Down Expand Up @@ -155,6 +145,57 @@ const (
SnapshotName_Error_StartNoLetter string = "SnapshotName must start with a letter"
)

// Deletes the specified snapshot, validates the input
func (snap SnapshotName) Delete(c *Client, vmr *VmRef) (exitStatus string, err error) {
if err = c.CheckVmRef(vmr); err != nil {
return
}
if err = snap.Validate(); err != nil {
return
}
// TODO check if snapshot exists
return snap.Delete_Unsafe(c, vmr)
}

// Deletes the specified snapshot without validating the input, use SnapshotName.Delete() to validate the input.
func (snap SnapshotName) Delete_Unsafe(c *Client, vmr *VmRef) (exitStatus string, err error) {
return c.DeleteWithTask("/nodes/" + vmr.node + "/" + vmr.vmType + "/" + strconv.Itoa(vmr.vmId) + "/snapshot/" + string(snap))
}

// Rollback to the specified snapshot, validates the input
func (snap SnapshotName) Rollback(c *Client, vmr *VmRef) (exitStatus string, err error) {
if err = c.CheckVmRef(vmr); err != nil {
return
}
if err = snap.Validate(); err != nil {
return
}
// TODO check if snapshot exists
return snap.Rollback_Unsafe(c, vmr)
}

// Rollback to the specified snapshot without validating the input, use SnapshotName.Rollback() to validate the input.
func (snap SnapshotName) Rollback_Unsafe(c *Client, vmr *VmRef) (exitStatus string, err error) {
return c.PostWithTask(nil, "/nodes/"+vmr.node+"/"+vmr.vmType+"/"+strconv.FormatInt(int64(vmr.vmId), 10)+"/snapshot/"+string(snap)+"/rollback")
}

// Updates the description of the specified snapshot, validates the input
func (snap SnapshotName) UpdateDescription(c *Client, vmr *VmRef, description string) (err error) {
if err = c.CheckVmRef(vmr); err != nil {
return
}
if err = snap.Validate(); err != nil {
return
}
// TODO check if snapshot exists
return snap.UpdateDescription_Unsafe(c, vmr, description)
}

// Updates the description of the specified snapshot without validating the input, use SnapshotName.UpdateDescription() to validate the input.
func (snap SnapshotName) UpdateDescription_Unsafe(c *Client, vmr *VmRef, description string) error {
return c.Put(map[string]interface{}{"description": description}, "/nodes/"+vmr.node+"/"+vmr.vmType+"/"+strconv.Itoa(vmr.vmId)+"/snapshot/"+string(snap)+"/config")
}

func (name SnapshotName) Validate() error {
regex, _ := regexp.Compile(`^([a-zA-Z])([a-z]|[A-Z]|[0-9]|_|-){2,39}$`)
if !regex.Match([]byte(name)) {
Expand Down
Loading