Skip to content

Commit

Permalink
Merge pull request #1146 from machiiine/fix-768
Browse files Browse the repository at this point in the history
feature: clone qemu vm based on vmid
  • Loading branch information
Tinyblargon authored Nov 10, 2024
2 parents f52c575 + 73cfb13 commit f3c2be3
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 11 deletions.
3 changes: 2 additions & 1 deletion docs/resources/vm_qemu.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ The following arguments are supported in the top level resource block.
| `bootdisk` | `str` | | Enable booting from specified disk. You shouldn't need to change it under most circumstances. |
| `agent` | `int` | `0` | Set to `1` to enable the QEMU Guest Agent. Note, you must run the [`qemu-guest-agent`](https://pve.proxmox.com/wiki/Qemu-guest-agent) daemon in the guest for this to have any effect. |
| `pxe` | `bool` | `false` | If set to `true`, enable PXE boot of the VM. Also requires a `boot` order be set with Network included (eg `boot = "order=scsi0;net0"`). Note that `pxe` is mutually exclusive with `clone` modes. |
| `clone` | `str` | | The base VM from which to clone to create the new VM. Note that `clone` is mutually exclusive with `pxe` modes. |
| `clone` | `str` | | The base VM name from which to clone to create the new VM. Note that `clone` is mutually exclusive with `clone_id` and `pxe` modes. |
| `clone_id` | `int` | | The base VM id from which to clone to create the new VM. Note that `clone_id` is mutually exclusive with `clone` and `pxe` modes. |
| `full_clone` | `bool` | `true` | Set to `true` to create a full clone, or `false` to create a linked clone. See the [docs about cloning](https://pve.proxmox.com/pve-docs/chapter-qm.html#qm_copy_and_clone) for more info. Only applies when `clone` is set. |
| `hastate` | `str` | | Requested HA state for the resource. One of "started", "stopped", "enabled", "disabled", or "ignored". See the [docs about HA](https://pve.proxmox.com/pve-docs/chapter-ha-manager.html#ha_manager_resource_config) for more info. |
| `hagroup` | `str` | | The HA group identifier the resource belongs to (requires `hastate` to be set!). See the [docs about HA](https://pve.proxmox.com/pve-docs/chapter-ha-manager.html#ha_manager_resource_config) for more info. |
Expand Down
40 changes: 30 additions & 10 deletions proxmox/resource_vm_qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"log"
"math/rand"
Expand Down Expand Up @@ -208,6 +209,12 @@ func resourceVmQemu() *schema.Resource {
ForceNew: true,
ConflictsWith: []string{"pxe"},
},
"clone_id": {
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
ConflictsWith: []string{"clone", "pxe"},
},
"full_clone": {
Type: schema.TypeBool,
Optional: true,
Expand Down Expand Up @@ -869,6 +876,27 @@ func resourceVmQemu() *schema.Resource {
return thisResource
}

func getSourceVmr(client *pxapi.Client, name string, id int, targetNode string) (*pxapi.VmRef, error) {
if name != "" {
sourceVmrs, err := client.GetVmRefsByName(name)
if err != nil {
return nil, err
}
// Prefer source VM on the same node
sourceVmr := sourceVmrs[0]
for _, candVmr := range sourceVmrs {
if candVmr.Node() == targetNode {
sourceVmr = candVmr
}
}
return sourceVmr, nil
} else if id != 0 {
return client.GetVmRefById(id)
}

return nil, errors.New("either 'clone' name or 'clone_id' must be specified")
}

func resourceVmQemuCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
// create a logger for this function
logger, _ := CreateSubLogger("resource_vm_create")
Expand Down Expand Up @@ -997,26 +1025,18 @@ func resourceVmQemuCreate(ctx context.Context, d *schema.ResourceData, meta inte
vmr.SetPool(d.Get("pool").(string))

// check if clone, or PXE boot
if d.Get("clone").(string) != "" {
if d.Get("clone").(string) != "" || d.Get("clone_id").(int) != 0 {
fullClone := 1
if !d.Get("full_clone").(bool) {
fullClone = 0
}
config.FullClone = &fullClone

sourceVmrs, err := client.GetVmRefsByName(d.Get("clone").(string))
sourceVmr, err := getSourceVmr(client, d.Get("clone").(string), d.Get("clone_id").(int), vmr.Node())
if err != nil {
return append(diags, diag.FromErr(err)...)
}

// prefer source Vm located on same node
sourceVmr := sourceVmrs[0]
for _, candVmr := range sourceVmrs {
if candVmr.Node() == vmr.Node() {
sourceVmr = candVmr
}
}

log.Print("[DEBUG][QemuVmCreate] cloning VM")
logger.Debug().Str("vmid", d.Id()).Msgf("Cloning VM")
err = config.CloneVm(sourceVmr, vmr, client)
Expand Down

0 comments on commit f3c2be3

Please sign in to comment.