Skip to content
This repository has been archived by the owner on Apr 12, 2018. It is now read-only.

Commit

Permalink
Merge pull request #29 from rakutentech/host-connection-info
Browse files Browse the repository at this point in the history
Add default host connection support and boot_delay option
  • Loading branch information
tkak committed Aug 13, 2015
2 parents 91f6716 + 4f677f5 commit 15a8af6
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 15 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ The following arguments are supported.
* `memory` - (Required) Memory size in MB.
* `disk` - (Required) Hard disk configuration. This can be specified multiple times for multiple disks. Structure is documented below.
* `network_interface` - (Required) Network configuration. This can be specified multiple times for multiple networks. Structure is documented below.

* `datacenter` - (Optional) Datacenter name
* `cluster` - (Optional) Cluster name, a cluster is a group of hosts.
* `resource_pool` - (Optional) Resource pool name.
Expand All @@ -94,6 +93,7 @@ The following arguments are supported.
* `domain` - (Optional) Domain configuration. By default, it's "vsphere.local".
* `dns_suffix` - (Optional) List of DNS suffix. By default, it's `["vsphere.local"]`.
* `dns_server` - (Optional) List of DNS server. By default, it's `["8.8.8.8", "8.8.4.4"]`.
* `boot_delay` - (Optional) Time in seconds to wait for DHCP. Only used if `network_interface.0` is not static.

Each `network_interface` supports the following:

Expand Down
92 changes: 78 additions & 14 deletions vsphere/resource_vsphere_virtual_machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"fmt"
"log"
"net"
"time"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/find"
Expand Down Expand Up @@ -166,6 +168,11 @@ func resourceVSphereVirtualMachine() *schema.Resource {
},
},
},

"boot_delay": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
},
},
}
}
Expand Down Expand Up @@ -230,11 +237,11 @@ func resourceVSphereVirtualMachineCreate(d *schema.ResourceData, meta interface{
for i := 0; i < networksCount; i++ {
prefix := fmt.Sprintf("network_interface.%d", i)
networks[i].label = d.Get(prefix + ".label").(string)
if v := d.Get(prefix + ".ip_address"); v != nil {
networks[i].ipAddress = d.Get(prefix + ".ip_address").(string)
if v, ok := d.GetOk(prefix + ".ip_address"); ok {
networks[i].ipAddress = v.(string)
}
if v := d.Get(prefix + ".subnet_mask"); v != nil {
networks[i].subnetMask = d.Get(prefix + ".subnet_mask").(string)
if v, ok := d.GetOk(prefix + ".subnet_mask"); ok {
networks[i].subnetMask = v.(string)
}
}
vm.networkInterfaces = networks
Expand All @@ -245,27 +252,27 @@ func resourceVSphereVirtualMachineCreate(d *schema.ResourceData, meta interface{
for i := 0; i < diskCount; i++ {
prefix := fmt.Sprintf("disk.%d", i)
if i == 0 {
if v := d.Get(prefix + ".template"); v != "" {
vm.template = d.Get(prefix + ".template").(string)
if v, ok := d.GetOk(prefix + ".template"); ok {
vm.template = v.(string)
} else {
if v := d.Get(prefix + ".size"); v != "" {
disks[i].size = int64(d.Get(prefix + ".size").(int))
if v, ok := d.GetOk(prefix + ".size"); ok {
disks[i].size = int64(v.(int))
} else {
return fmt.Errorf("If template argument is not specified, size argument is required.")
}
}
if v := d.Get(prefix + ".datastore"); v != "" {
vm.datastore = d.Get(prefix + ".datastore").(string)
if v, ok := d.GetOk(prefix + ".datastore"); ok {
vm.datastore = v.(string)
}
} else {
if v := d.Get(prefix + ".size"); v != "" {
disks[i].size = int64(d.Get(prefix + ".size").(int))
if v, ok := d.GetOk(prefix + ".size"); ok {
disks[i].size = int64(v.(int))
} else {
return fmt.Errorf("Size argument is required.")
}
}
if v := d.Get(prefix + ".iops"); v != "" {
disks[i].iops = int64(d.Get(prefix + ".iops").(int))
if v, ok := d.GetOk(prefix + ".iops"); ok {
disks[i].iops = int64(v.(int))
}
}
vm.hardDisks = disks
Expand All @@ -282,6 +289,24 @@ func resourceVSphereVirtualMachineCreate(d *schema.ResourceData, meta interface{
return fmt.Errorf("error: %s", err)
}
}

if _, ok := d.GetOk("network_interface.0.ip_address"); !ok {
if v, ok := d.GetOk("boot_delay"); ok {
stateConf := &resource.StateChangeConf{
Pending: []string{"pending"},
Target: "active",
Refresh: waitForNetworkingActive(client, vm.datacenter, vm.name),
Timeout: 600 * time.Second,
Delay: time.Duration(v.(int)) * time.Second,
MinTimeout: 2 * time.Second,
}

_, err := stateConf.WaitForState()
if err != nil {
return fmt.Errorf("error: %s", err)
}
}
}
d.SetId(vm.name)
log.Printf("[INFO] Created virtual machine: %s", d.Id())

Expand Down Expand Up @@ -368,6 +393,12 @@ func resourceVSphereVirtualMachineRead(d *schema.ResourceData, meta interface{})
d.Set("cpu", mvm.Summary.Config.NumCpu)
d.Set("datastore", rootDatastore)

// Initialize the connection info
d.SetConnInfo(map[string]string{
"type": "ssh",
"host": networkInterfaces[0]["ip_address"].(string),
})

return nil
}

Expand Down Expand Up @@ -425,3 +456,36 @@ func resourceVSphereVirtualMachineDelete(d *schema.ResourceData, meta interface{
d.SetId("")
return nil
}

func waitForNetworkingActive(client *govmomi.Client, datacenter, name string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
finder := find.NewFinder(client.Client, true)
dc, err := finder.Datacenter(context.TODO(), datacenter)
if err != nil {
log.Printf("[ERROR] %#v", err)
return nil, "", err
}

finder = finder.SetDatacenter(dc)
vm, err := finder.VirtualMachine(context.TODO(), name)
if err != nil {
log.Printf("[ERROR] %#v", err)
return nil, "", err
}

var mvm mo.VirtualMachine
collector := property.DefaultCollector(client.Client)
if err := collector.RetrieveOne(context.TODO(), vm.Reference(), []string{"summary"}, &mvm); err != nil {
log.Printf("[ERROR] %#v", err)
return nil, "", err
}

if mvm.Summary.Guest.IpAddress != "" {
log.Printf("[DEBUG] IP address with DHCP: %v", mvm.Summary.Guest.IpAddress)
return mvm.Summary, "active", err
} else {
log.Printf("[DEBUG] Waiting for IP address")
return nil, "pending", err
}
}
}

0 comments on commit 15a8af6

Please sign in to comment.