From 821cf79a47dee1af559f5ed07d734e76a36219d0 Mon Sep 17 00:00:00 2001 From: Grant Gongaware Date: Tue, 10 Jul 2018 10:25:46 -0700 Subject: [PATCH 01/11] suppress diff on sensitive data when empty --- proxmox/resource_vm_qemu.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index e46d8be..f3b0432 100644 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -2,13 +2,14 @@ package proxmox import ( "fmt" - pxapi "github.com/Telmate/proxmox-api-go/proxmox" - "github.com/hashicorp/terraform/helper/schema" "log" "path" "strconv" "strings" "time" + + pxapi "github.com/Telmate/proxmox-api-go/proxmox" + "github.com/hashicorp/terraform/helper/schema" ) func resourceVmQemu() *schema.Resource { @@ -110,6 +111,9 @@ func resourceVmQemu() *schema.Resource { Optional: true, Sensitive: true, DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + if old == "" { + return true + } return strings.TrimSpace(old) == strings.TrimSpace(new) }, }, From d200eddfcde99a1d157990112a31796677228a6c Mon Sep 17 00:00:00 2001 From: Grant Gongaware Date: Tue, 10 Jul 2018 10:37:45 -0700 Subject: [PATCH 02/11] auto-formatted updates --- proxmox/preprovision.go | 4 ++-- proxmox/provider.go | 5 +++-- proxmox/provisioner.go | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/proxmox/preprovision.go b/proxmox/preprovision.go index 3669dde..f83f0e9 100644 --- a/proxmox/preprovision.go +++ b/proxmox/preprovision.go @@ -2,11 +2,11 @@ package proxmox import ( "fmt" + "github.com/hashicorp/terraform/communicator" "github.com/hashicorp/terraform/communicator/remote" "github.com/hashicorp/terraform/helper/schema" - // "github.com/hashicorp/terraform/terraform" - // "github.com/mitchellh/go-linereader" + "io" "log" "strconv" diff --git a/proxmox/provider.go b/proxmox/provider.go index 3933300..cce6b12 100644 --- a/proxmox/provider.go +++ b/proxmox/provider.go @@ -2,11 +2,12 @@ package proxmox import ( "fmt" - pxapi "github.com/Telmate/proxmox-api-go/proxmox" - "github.com/hashicorp/terraform/helper/schema" "regexp" "strconv" "sync" + + pxapi "github.com/Telmate/proxmox-api-go/proxmox" + "github.com/hashicorp/terraform/helper/schema" ) type providerConfiguration struct { diff --git a/proxmox/provisioner.go b/proxmox/provisioner.go index 55a6743..b295831 100644 --- a/proxmox/provisioner.go +++ b/proxmox/provisioner.go @@ -3,10 +3,11 @@ package proxmox import ( "context" "fmt" + "time" + pxapi "github.com/Telmate/proxmox-api-go/proxmox" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/terraform" - "time" ) func Provisioner() terraform.ResourceProvisioner { From ac80ff229d8b811c0a5b458e23519cc2cd7953be Mon Sep 17 00:00:00 2001 From: Grant Gongaware Date: Tue, 10 Jul 2018 14:50:35 -0700 Subject: [PATCH 03/11] -support optional insecure TLS proxmox nodes -restore previous ssh key behavior (works in 0.11.x) --- README.md | 1 + proxmox/provider.go | 16 +++++++++++++--- proxmox/provisioner.go | 2 +- proxmox/resource_vm_qemu.go | 20 +++++++++----------- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 2774ab0..8a92fb2 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ terraform apply main.tf: ``` provider "proxmox" { + pm_tls_insecure = true } resource "proxmox_vm_qemu" "test" { diff --git a/proxmox/provider.go b/proxmox/provider.go index cce6b12..960777f 100644 --- a/proxmox/provider.go +++ b/proxmox/provider.go @@ -1,6 +1,7 @@ package proxmox import ( + "crypto/tls" "fmt" "regexp" "strconv" @@ -47,6 +48,11 @@ func Provider() *schema.Provider { Optional: true, Default: 4, }, + "pm_tls_insecure": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, }, ResourcesMap: map[string]*schema.Resource{ @@ -61,7 +67,7 @@ func Provider() *schema.Provider { } func providerConfigure(d *schema.ResourceData) (interface{}, error) { - client, err := getClient(d.Get("pm_api_url").(string), d.Get("pm_user").(string), d.Get("pm_password").(string)) + client, err := getClient(d.Get("pm_api_url").(string), d.Get("pm_user").(string), d.Get("pm_password").(string), d.Get("pm_tls_insecure").(bool)) if err != nil { return nil, err } @@ -76,8 +82,12 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) { }, nil } -func getClient(pm_api_url string, pm_user string, pm_password string) (*pxapi.Client, error) { - client, _ := pxapi.NewClient(pm_api_url, nil, nil) +func getClient(pm_api_url string, pm_user string, pm_password string, pm_tls_insecure bool) (*pxapi.Client, error) { + tlsconf := &tls.Config{InsecureSkipVerify: true} + if !pm_tls_insecure { + tlsconf = nil + } + client, _ := pxapi.NewClient(pm_api_url, nil, tlsconf) err := client.Login(pm_user, pm_password) if err != nil { return nil, err diff --git a/proxmox/provisioner.go b/proxmox/provisioner.go index b295831..462a7d5 100644 --- a/proxmox/provisioner.go +++ b/proxmox/provisioner.go @@ -44,7 +44,7 @@ func applyFn(ctx context.Context) error { vmr.SetNode(targetNode) client := currentClient if client == nil { - client, err = getClient(connInfo["pm_api_url"], connInfo["pm_user"], connInfo["pm_password"]) + client, err = getClient(connInfo["pm_api_url"], connInfo["pm_user"], connInfo["pm_password"], connInfo["pm_tls_insecure"] == "true") if err != nil { return err } diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index f3b0432..d14d968 100644 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -111,9 +111,6 @@ func resourceVmQemu() *schema.Resource { Optional: true, Sensitive: true, DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - if old == "" { - return true - } return strings.TrimSpace(old) == strings.TrimSpace(new) }, }, @@ -244,14 +241,15 @@ func resourceVmQemuCreate(d *schema.ResourceData, meta interface{}) error { pmParallelEnd(pconf) d.SetConnInfo(map[string]string{ - "type": "ssh", - "host": d.Get("ssh_forward_ip").(string), - "port": sshPort, - "user": d.Get("ssh_user").(string), - "private_key": d.Get("ssh_private_key").(string), - "pm_api_url": client.ApiUrl, - "pm_user": client.Username, - "pm_password": client.Password, + "type": "ssh", + "host": d.Get("ssh_forward_ip").(string), + "port": sshPort, + "user": d.Get("ssh_user").(string), + "private_key": d.Get("ssh_private_key").(string), + "pm_api_url": client.ApiUrl, + "pm_user": client.Username, + "pm_password": client.Password, + "pm_tls_insecure": "true", // TODO - pass pm_tls_insecure state around, but if we made it this far, default insecure }) switch d.Get("os_type").(string) { From 821ceb8d0d7955b12dc8ea4c20144c16aa8a695b Mon Sep 17 00:00:00 2001 From: Grant Gongaware Date: Wed, 11 Jul 2018 15:14:26 -0700 Subject: [PATCH 04/11] switch to /cluster/nextid instead of maxid --- proxmox/provider.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/proxmox/provider.go b/proxmox/provider.go index 960777f..a3d6fa1 100644 --- a/proxmox/provider.go +++ b/proxmox/provider.go @@ -76,7 +76,7 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) { Client: client, MaxParallel: d.Get("pm_parallel").(int), CurrentParallel: 0, - MaxVmId: 0, + MaxVmId: -1, Mutex: &mut, Cond: sync.NewCond(&mut), }, nil @@ -97,13 +97,10 @@ func getClient(pm_api_url string, pm_user string, pm_password string, pm_tls_ins func nextVmId(pconf *providerConfiguration) (nextId int, err error) { pconf.Mutex.Lock() - if pconf.MaxVmId == 0 { - pconf.MaxVmId, err = pxapi.MaxVmId(pconf.Client) - if err != nil { - return 0, err - } + pconf.MaxVmId, err = pconf.Client.GetNextID(pconf.MaxVmId + 1) + if err != nil { + return 0, err } - pconf.MaxVmId++ nextId = pconf.MaxVmId pconf.Mutex.Unlock() return nextId, nil From 83722fe9b91a6937cef271288ed0d388814f7a70 Mon Sep 17 00:00:00 2001 From: Grant Gongaware Date: Fri, 13 Jul 2018 10:25:37 -0700 Subject: [PATCH 05/11] untested cloud-init support --- README.md | 61 +++++++++++++++-- proxmox/provider.go | 9 +-- proxmox/provisioner.go | 8 +-- proxmox/resource_vm_qemu.go | 133 +++++++++++++++++++++++++++++++----- 4 files changed, 182 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 8a92fb2..335a9bd 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,45 @@ provider "proxmox" { pm_tls_insecure = true } -resource "proxmox_vm_qemu" "test" { +/* Uses cloud-init options from Proxmox 5.2 */ +resource "proxmox_vm_qemu" "cloudinit-test" { + name = "tftest1.xyz.com" + desc = "tf description" + target_node = "proxmox1-xx" + + clone = "ci-ubuntu-template" + storage = "local" + cores = 3 + sockets = 1 + memory = 2560 + disk_gb = 4 + nic = "virtio" + bridge = "vmbr0" + + ssh_user = "root" + ssh_private_key = <] [,gw6=] [,ip=] [,ip6=] +* ipconfig1 - optional, same as ipconfig0 format + +### Preprovision (internal alternative to Cloud-Init) There is a pre-provision phase which is used to set a hostname, intialize eth0, and resize the VM disk to available space. This is done over SSH with the ssh_forward_ip, ssh_user and ssh_private_key. diff --git a/proxmox/provider.go b/proxmox/provider.go index a3d6fa1..ac372ca 100644 --- a/proxmox/provider.go +++ b/proxmox/provider.go @@ -15,11 +15,12 @@ type providerConfiguration struct { Client *pxapi.Client MaxParallel int CurrentParallel int - MaxVmId int + MaxVMID int Mutex *sync.Mutex Cond *sync.Cond } +// Provider - Terrafrom properties for proxmox func Provider() *schema.Provider { return &schema.Provider{ @@ -76,7 +77,7 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) { Client: client, MaxParallel: d.Get("pm_parallel").(int), CurrentParallel: 0, - MaxVmId: -1, + MaxVMID: -1, Mutex: &mut, Cond: sync.NewCond(&mut), }, nil @@ -97,11 +98,11 @@ func getClient(pm_api_url string, pm_user string, pm_password string, pm_tls_ins func nextVmId(pconf *providerConfiguration) (nextId int, err error) { pconf.Mutex.Lock() - pconf.MaxVmId, err = pconf.Client.GetNextID(pconf.MaxVmId + 1) + pconf.MaxVMID, err = pconf.Client.GetNextID(pconf.MaxVMID + 1) if err != nil { return 0, err } - nextId = pconf.MaxVmId + nextId = pconf.MaxVMID pconf.Mutex.Unlock() return nextId, nil } diff --git a/proxmox/provisioner.go b/proxmox/provisioner.go index 462a7d5..0c7a7db 100644 --- a/proxmox/provisioner.go +++ b/proxmox/provisioner.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform/terraform" ) +// Provisioner - Terrafrom properties for proxmox-provisioner func Provisioner() terraform.ResourceProvisioner { return &schema.Provisioner{ Schema: map[string]*schema.Schema{ @@ -27,7 +28,7 @@ func Provisioner() terraform.ResourceProvisioner { } } -var currentClient *pxapi.Client = nil +var currentClient *pxapi.Client func applyFn(ctx context.Context) error { data := ctx.Value(schema.ProvConfigDataKey).(*schema.ResourceData) @@ -36,11 +37,11 @@ func applyFn(ctx context.Context) error { connInfo := state.Ephemeral.ConnInfo act := data.Get("action").(string) - targetNode, _, vmId, err := parseResourceId(state.ID) + targetNode, _, vmID, err := parseResourceId(state.ID) if err != nil { return err } - vmr := pxapi.NewVmRef(vmId) + vmr := pxapi.NewVmRef(vmID) vmr.SetNode(targetNode) client := currentClient if client == nil { @@ -69,5 +70,4 @@ func applyFn(ctx context.Context) error { default: return fmt.Errorf("Unkown action: %s", act) } - return nil } diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index d14d968..bee0d97 100644 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "path" + "regexp" "strconv" "strings" "time" @@ -38,6 +39,7 @@ func resourceVmQemu() *schema.Resource { "target_node": { Type: schema.TypeString, Required: true, + ForceNew: true, }, "ssh_forward_ip": { Type: schema.TypeString, @@ -46,15 +48,22 @@ func resourceVmQemu() *schema.Resource { "iso": { Type: schema.TypeString, Optional: true, + ForceNew: true, }, "clone": { Type: schema.TypeString, Optional: true, + ForceNew: true, }, "storage": { Type: schema.TypeString, Required: true, }, + "storage_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, "qemu_os": { Type: schema.TypeString, Optional: true, @@ -119,16 +128,61 @@ func resourceVmQemu() *schema.Resource { Optional: true, Default: false, }, + "mac": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + if old == "" { + return false // macaddr auto-generates and its ok + } + return strings.TrimSpace(old) == strings.TrimSpace(new) + }, + }, + "ci_wait": { // how long to wait before provision + Type: schema.TypeInt, + Optional: true, + Default: 30, + }, + "ciuser": { + Type: schema.TypeString, + Optional: true, + }, + "cipassword": { + Type: schema.TypeString, + Optional: true, + }, + "searchdomain": { + Type: schema.TypeString, + Optional: true, + }, + "nameserver": { + Type: schema.TypeString, + Optional: true, + }, + "sshkeys": { + Type: schema.TypeString, + Optional: true, + }, + "ipconfig0": { + Type: schema.TypeString, + Optional: true, + }, + "ipconfig1": { + Type: schema.TypeString, + Optional: true, + }, }, } } +var rxIPconfig = regexp.MustCompile("ip6?=([0-9a-fA-F:\\.]+)") + func resourceVmQemuCreate(d *schema.ResourceData, meta interface{}) error { pconf := meta.(*providerConfiguration) pmParallelBegin(pconf) client := pconf.Client vmName := d.Get("name").(string) - disk_gb := d.Get("disk_gb").(float64) + diskGB := d.Get("disk_gb").(float64) config := pxapi.ConfigQemu{ Name: vmName, Description: d.Get("desc").(string), @@ -136,11 +190,19 @@ func resourceVmQemuCreate(d *schema.ResourceData, meta interface{}) error { Memory: d.Get("memory").(int), QemuCores: d.Get("cores").(int), QemuSockets: d.Get("sockets").(int), - DiskSize: disk_gb, + DiskSize: diskGB, QemuOs: d.Get("qemu_os").(string), QemuNicModel: d.Get("nic").(string), QemuBrige: d.Get("bridge").(string), QemuVlanTag: d.Get("vlan").(int), + QemuMacAddr: d.Get("mac").(string), + CIuser: d.Get("ciuser").(string), + CIpassword: d.Get("cipassword").(string), + Searchdomain: d.Get("searchdomain").(string), + Nameserver: d.Get("nameserver").(string), + Sshkeys: d.Get("sshkeys").(string), + Ipconfig0: d.Get("ipconfig0").(string), + Ipconfig1: d.Get("ipconfig1").(string), } log.Print("[DEBUG] checking for duplicate name") dupVmr, _ := client.GetVmRefByName(vmName) @@ -185,7 +247,7 @@ func resourceVmQemuCreate(d *schema.ResourceData, meta interface{}) error { // give sometime to proxmox to catchup time.Sleep(5 * time.Second) - err = prepareDiskSize(client, vmr, disk_gb) + err = prepareDiskSize(client, vmr, diskGB) if err != nil { pmParallelEnd(pconf) return err @@ -213,7 +275,7 @@ func resourceVmQemuCreate(d *schema.ResourceData, meta interface{}) error { // give sometime to proxmox to catchup time.Sleep(5 * time.Second) - err = prepareDiskSize(client, vmr, disk_gb) + err = prepareDiskSize(client, vmr, diskGB) if err != nil { pmParallelEnd(pconf) return err @@ -230,11 +292,25 @@ func resourceVmQemuCreate(d *schema.ResourceData, meta interface{}) error { pmParallelEnd(pconf) return err } - log.Print("[DEBUG] setting up SSH forward") - sshPort, err := pxapi.SshForwardUsernet(vmr, client) - if err != nil { - pmParallelEnd(pconf) - return err + + sshPort := "22" + sshHost := "" + if config.HasCloudInit() { + if d.Get("ssh_forward_ip") != nil { + sshHost = d.Get("ssh_forward_ip").(string) + } else { + // parse IP address out of ipconfig0 + ipMatch := rxIPconfig.FindStringSubmatch(d.Get("ipconfig0").(string)) + sshHost = ipMatch[1] + } + } else { + log.Print("[DEBUG] setting up SSH forward") + sshPort, err = pxapi.SshForwardUsernet(vmr, client) + if err != nil { + pmParallelEnd(pconf) + return err + } + sshHost = d.Get("ssh_forward_ip").(string) } // Done with proxmox API, end parallel and do the SSH things @@ -242,7 +318,7 @@ func resourceVmQemuCreate(d *schema.ResourceData, meta interface{}) error { d.SetConnInfo(map[string]string{ "type": "ssh", - "host": d.Get("ssh_forward_ip").(string), + "host": sshHost, "port": sshPort, "user": d.Get("ssh_user").(string), "private_key": d.Get("ssh_private_key").(string), @@ -270,6 +346,10 @@ func resourceVmQemuCreate(d *schema.ResourceData, meta interface{}) error { return err } + case "cloud-init": + // wait for OS too boot awhile... + time.Sleep(time.Duration(d.Get("ci_wait").(int)) * time.Second) + default: return fmt.Errorf("Unknown os_type: %s", d.Get("os_type").(string)) } @@ -287,7 +367,7 @@ func resourceVmQemuUpdate(d *schema.ResourceData, meta interface{}) error { return err } vmName := d.Get("name").(string) - disk_gb := d.Get("disk_gb").(float64) + diskGB := d.Get("disk_gb").(float64) config := pxapi.ConfigQemu{ Name: vmName, Description: d.Get("desc").(string), @@ -295,11 +375,19 @@ func resourceVmQemuUpdate(d *schema.ResourceData, meta interface{}) error { Memory: d.Get("memory").(int), QemuCores: d.Get("cores").(int), QemuSockets: d.Get("sockets").(int), - DiskSize: disk_gb, + DiskSize: diskGB, QemuOs: d.Get("qemu_os").(string), QemuNicModel: d.Get("nic").(string), QemuBrige: d.Get("bridge").(string), QemuVlanTag: d.Get("vlan").(int), + QemuMacAddr: d.Get("mac").(string), + CIuser: d.Get("ciuser").(string), + CIpassword: d.Get("cipassword").(string), + Searchdomain: d.Get("searchdomain").(string), + Nameserver: d.Get("nameserver").(string), + Sshkeys: d.Get("sshkeys").(string), + Ipconfig0: d.Get("ipconfig0").(string), + Ipconfig1: d.Get("ipconfig1").(string), } err = config.UpdateConfig(vmr, client) @@ -311,7 +399,7 @@ func resourceVmQemuUpdate(d *schema.ResourceData, meta interface{}) error { // give sometime to proxmox to catchup time.Sleep(5 * time.Second) - prepareDiskSize(client, vmr, disk_gb) + prepareDiskSize(client, vmr, diskGB) // give sometime to proxmox to catchup time.Sleep(5 * time.Second) @@ -361,6 +449,7 @@ func resourceVmQemuRead(d *schema.ResourceData, meta interface{}) error { d.Set("name", config.Name) d.Set("desc", config.Description) d.Set("storage", config.Storage) + d.Set("storage_type", config.StorageType) d.Set("memory", config.Memory) d.Set("cores", config.QemuCores) d.Set("sockets", config.QemuSockets) @@ -369,6 +458,16 @@ func resourceVmQemuRead(d *schema.ResourceData, meta interface{}) error { d.Set("nic", config.QemuNicModel) d.Set("bridge", config.QemuBrige) d.Set("vlan", config.QemuVlanTag) + d.Set("mac", config.QemuMacAddr) + + d.Set("ciuser", config.CIuser) + d.Set("cipassword", config.CIpassword) + d.Set("searchdomain", config.Searchdomain) + d.Set("nameserver", config.Nameserver) + d.Set("sshkeys", config.Sshkeys) + d.Set("ipconfig0", config.Ipconfig0) + d.Set("ipconfig1", config.Ipconfig1) + pmParallelEnd(pconf) return nil } @@ -397,14 +496,14 @@ func resourceVmQemuDelete(d *schema.ResourceData, meta interface{}) error { return err } -func prepareDiskSize(client *pxapi.Client, vmr *pxapi.VmRef, disk_gb float64) error { +func prepareDiskSize(client *pxapi.Client, vmr *pxapi.VmRef, diskGB float64) error { clonedConfig, err := pxapi.NewConfigQemuFromApi(vmr, client) if err != nil { return err } - if disk_gb > clonedConfig.DiskSize { - log.Print("[DEBUG] resizing disk") - _, err = client.ResizeQemuDisk(vmr, "virtio0", int(disk_gb-clonedConfig.DiskSize)) + if diskGB > clonedConfig.DiskSize { + log.Print("[DEBUG] resizing disk " + clonedConfig.StorageType) + _, err = client.ResizeQemuDisk(vmr, clonedConfig.StorageType+"0", int(diskGB-clonedConfig.DiskSize)) if err != nil { return err } From 27fba3be5c9282efc9688b41d5ec0fc35add5a0b Mon Sep 17 00:00:00 2001 From: Grant Gongaware Date: Mon, 16 Jul 2018 09:10:23 -0700 Subject: [PATCH 06/11] ssh_forward_ip optional with cloud-init --- proxmox/resource_vm_qemu.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index bee0d97..bb2fcfb 100644 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -43,7 +43,7 @@ func resourceVmQemu() *schema.Resource { }, "ssh_forward_ip": { Type: schema.TypeString, - Required: true, + Optional: true, }, "iso": { Type: schema.TypeString, @@ -348,6 +348,7 @@ func resourceVmQemuCreate(d *schema.ResourceData, meta interface{}) error { case "cloud-init": // wait for OS too boot awhile... + log.Print("[DEBUG] sleeping for OS bootup...") time.Sleep(time.Duration(d.Get("ci_wait").(int)) * time.Second) default: From a14c33d85754fcf21ff452de29251550a4663787 Mon Sep 17 00:00:00 2001 From: Grant Gongaware Date: Mon, 16 Jul 2018 11:57:46 -0700 Subject: [PATCH 07/11] fix sshHost, disk resize, and allow sparse mac, storage_type & qemu_os-type parameters --- proxmox/resource_vm_qemu.go | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index bb2fcfb..864c241 100644 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -3,6 +3,7 @@ package proxmox import ( "fmt" "log" + "math" "path" "regexp" "strconv" @@ -62,12 +63,24 @@ func resourceVmQemu() *schema.Resource { "storage_type": { Type: schema.TypeString, Optional: true, - ForceNew: true, + ForceNew: false, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + if new == "" { + return true // empty template ok + } + return strings.TrimSpace(old) == strings.TrimSpace(new) + }, }, "qemu_os": { Type: schema.TypeString, Optional: true, Default: "l26", + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + if old == "" { + return true // reading empty ok + } + return strings.TrimSpace(old) == strings.TrimSpace(new) + }, }, "memory": { Type: schema.TypeInt, @@ -84,6 +97,12 @@ func resourceVmQemu() *schema.Resource { "disk_gb": { Type: schema.TypeFloat, Required: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + // bigger ok + oldf, _ := strconv.ParseFloat(old, 64) + newf, _ := strconv.ParseFloat(new, 64) + return oldf >= newf + }, }, "nic": { Type: schema.TypeString, @@ -132,8 +151,8 @@ func resourceVmQemu() *schema.Resource { Type: schema.TypeString, Optional: true, DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - if old == "" { - return false // macaddr auto-generates and its ok + if new == "" { + return true // macaddr auto-generates and its ok } return strings.TrimSpace(old) == strings.TrimSpace(new) }, @@ -162,6 +181,9 @@ func resourceVmQemu() *schema.Resource { "sshkeys": { Type: schema.TypeString, Optional: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + return strings.TrimSpace(old) == strings.TrimSpace(new) + }, }, "ipconfig0": { Type: schema.TypeString, @@ -298,7 +320,8 @@ func resourceVmQemuCreate(d *schema.ResourceData, meta interface{}) error { if config.HasCloudInit() { if d.Get("ssh_forward_ip") != nil { sshHost = d.Get("ssh_forward_ip").(string) - } else { + } + if sshHost == "" { // parse IP address out of ipconfig0 ipMatch := rxIPconfig.FindStringSubmatch(d.Get("ipconfig0").(string)) sshHost = ipMatch[1] @@ -504,7 +527,8 @@ func prepareDiskSize(client *pxapi.Client, vmr *pxapi.VmRef, diskGB float64) err } if diskGB > clonedConfig.DiskSize { log.Print("[DEBUG] resizing disk " + clonedConfig.StorageType) - _, err = client.ResizeQemuDisk(vmr, clonedConfig.StorageType+"0", int(diskGB-clonedConfig.DiskSize)) + diffSize := int(math.Ceil(diskGB - clonedConfig.DiskSize)) + _, err = client.ResizeQemuDisk(vmr, clonedConfig.StorageType+"0", diffSize) if err != nil { return err } From fb9d595c5347958bf72bea5c570e1e4c5c6dc225 Mon Sep 17 00:00:00 2001 From: Grant Gongaware Date: Thu, 19 Jul 2018 09:53:00 -0700 Subject: [PATCH 08/11] suppress ci_wait change to default for backward compatibility --- proxmox/resource_vm_qemu.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index 864c241..dfc7acd 100644 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -161,6 +161,12 @@ func resourceVmQemu() *schema.Resource { Type: schema.TypeInt, Optional: true, Default: 30, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + if old == "" { + return true // old empty ok + } + return strings.TrimSpace(old) == strings.TrimSpace(new) + }, }, "ciuser": { Type: schema.TypeString, From 860c150f8da7528c38dc12992958b4ccda16de90 Mon Sep 17 00:00:00 2001 From: Grant Gongaware Date: Tue, 2 Oct 2018 12:13:09 -0700 Subject: [PATCH 09/11] support a manual port setting for ssh_forward_ip --- proxmox/resource_vm_qemu.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index dfc7acd..3f059e7 100644 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -331,6 +331,13 @@ func resourceVmQemuCreate(d *schema.ResourceData, meta interface{}) error { // parse IP address out of ipconfig0 ipMatch := rxIPconfig.FindStringSubmatch(d.Get("ipconfig0").(string)) sshHost = ipMatch[1] + + } + // Check if we got a speficied port + if strings.Contains(sshHost, ":") { + sshParts := strings.Split(sshHost, ":") + sshHost = sshParts[0] + sshPort = sshParts[1] } } else { log.Print("[DEBUG] setting up SSH forward") From a07b9bd3187512d8017310c33e33950b21f016b7 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 10 Oct 2018 14:12:10 -0400 Subject: [PATCH 10/11] Documents for copying the provider so it works Just a quick document to help people setup the provider if terraform doesn't find it. --- docs/terraforminit.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 docs/terraforminit.md diff --git a/docs/terraforminit.md b/docs/terraforminit.md new file mode 100644 index 0000000..5c89d0a --- /dev/null +++ b/docs/terraforminit.md @@ -0,0 +1,27 @@ +# How to get terraform to recognize third party provider + +The default installation of terraform has no way of finding custom third party providers. This document shows you how to locate providers so that `terraform init` can find them and copy them to your working terraform directory when creating a new project. + +## Locate the provider binaries + +Assuming you have followed other directions the deafult locations for these binaries (on a mac at least) are as follows: + +```bash +which terraform-provider-proxmox +~/go-workspace/bin/terraform-provider-proxmox +which terraform-provisioner-proxmox +~/go-workspace/bin/terraform-provisioner-proxmox +``` + +## Copy provider binaries + +You need to copy these binaries to the ~/.terraform.d directory which will also need to have a plugins directory created: + +```shell +cd ~/.terraform.d +mkdir plugins +cd plugins +cp ~/go-workspace/bin/terraform-provider-proxmox . +cp ~/go-workspace/bin/terraform-provisioner-proxmox . +``` +Once this is done, simply create a new terraform directory and do usual terraforming (terraform init etc) From 3f07e92a3d7164535426a28574bda02c55791336 Mon Sep 17 00:00:00 2001 From: Grant Gongaware Date: Fri, 9 Nov 2018 08:55:50 -0800 Subject: [PATCH 11/11] #25 fix Project no longer builds --- proxmox/provisioner.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/proxmox/provisioner.go b/proxmox/provisioner.go index 0c7a7db..d8e4d96 100644 --- a/proxmox/provisioner.go +++ b/proxmox/provisioner.go @@ -61,9 +61,8 @@ func applyFn(ctx context.Context) error { return err } time.Sleep(10 * time.Second) - vmParams := map[string]string{ - "net1": data.Get("net1").(string), - } + var vmParams map[string]interface{} + vmParams["net1"] = data.Get("net1").(string) _, err = client.SetVmConfig(vmr, vmParams) time.Sleep(10 * time.Second) return err