Added protection for api limiting

This commit is contained in:
Brett Mack 2015-11-02 16:39:56 +00:00
parent 8376a5a160
commit 965882bfdf
5 changed files with 155 additions and 180 deletions

View File

@ -4,9 +4,7 @@ import (
"fmt" "fmt"
"github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/schema"
"github.com/opencredo/vmware-govcd" "github.com/opencredo/vmware-govcd"
"regexp"
"strings" "strings"
"time"
) )
func resourceVcdDNAT() *schema.Resource { func resourceVcdDNAT() *schema.Resource {
@ -48,41 +46,30 @@ func resourceVcdDNATCreate(d *schema.ResourceData, meta interface{}) error {
// operation we must wait until we can aquire a lock on the client // operation we must wait until we can aquire a lock on the client
vcd_client.Mutex.Lock() vcd_client.Mutex.Lock()
defer vcd_client.Mutex.Unlock() defer vcd_client.Mutex.Unlock()
var task govcd.Task
portString := getPortString(d.Get("port").(int)) portString := getPortString(d.Get("port").(int))
edgeGateway, err := vcd_client.OrgVdc.FindEdgeGateway(d.Get("edge_gateway").(string))
if err != nil {
return fmt.Errorf("Unable to find edge gateway: %#v", err)
}
// Creating a loop to offer further protection from the edge gateway erroring // Creating a loop to offer further protection from the edge gateway erroring
// due to being busy eg another person is using another client so wouldn't be // due to being busy eg another person is using another client so wouldn't be
// constrained by out lock. If the edge gateway reurns with a busy error, wait // constrained by out lock. If the edge gateway reurns with a busy error, wait
// 3 seconds and then try again. Continue until a non-busy error or success // 3 seconds and then try again. Continue until a non-busy error or success
for {
err := vcd_client.OrgVdc.Refresh()
if err != nil {
return fmt.Errorf("Error refreshing vdc: %#v", err)
}
edgeGateway, err := vcd_client.OrgVdc.FindEdgeGateway(d.Get("edge_gateway").(string)) err = retryCall(4, func() error {
task, err := edgeGateway.AddNATMapping("DNAT", d.Get("external_ip").(string),
if err != nil {
return fmt.Errorf("Unable to find edge gateway: %#v", err)
}
task, err = edgeGateway.AddNATMapping("DNAT", d.Get("external_ip").(string),
d.Get("internal_ip").(string), d.Get("internal_ip").(string),
portString) portString)
if err != nil { if err != nil {
if v, _ := regexp.MatchString("is busy completing an operation.$", err.Error()); v { return fmt.Errorf("Error setting DNAT rules: %#v", err)
time.Sleep(3 * time.Second)
continue
} else {
return fmt.Errorf("Error setting DNAT rules: %#v", err)
}
} }
break
}
err := task.WaitTaskCompletion() return task.WaitTaskCompletion()
})
if err != nil { if err != nil {
return fmt.Errorf("Error completing tasks: %#v", err) return fmt.Errorf("Error completing tasks: %#v", err)
} }
@ -129,41 +116,23 @@ func resourceVcdDNATDelete(d *schema.ResourceData, meta interface{}) error {
// operation we must wait until we can aquire a lock on the client // operation we must wait until we can aquire a lock on the client
vcd_client.Mutex.Lock() vcd_client.Mutex.Lock()
defer vcd_client.Mutex.Unlock() defer vcd_client.Mutex.Unlock()
var task govcd.Task
portString := getPortString(d.Get("port").(int)) portString := getPortString(d.Get("port").(int))
// Creating a loop to offer further protection from the edge gateway erroring edgeGateway, err := vcd_client.OrgVdc.FindEdgeGateway(d.Get("edge_gateway").(string))
// due to being busy eg another person is using another client so wouldn't be
// constrained by out lock. If the edge gateway reurns with a busy error, wait
// 3 seconds and then try again. Continue until a non-busy error or success
for {
err := vcd_client.OrgVdc.Refresh()
if err != nil {
return fmt.Errorf("Error refreshing vdc: %#v", err)
}
edgeGateway, err := vcd_client.OrgVdc.FindEdgeGateway(d.Get("edge_gateway").(string)) if err != nil {
return fmt.Errorf("Unable to find edge gateway: %#v", err)
if err != nil { }
return fmt.Errorf("Unable to find edge gateway: %#v", err) err = retryCall(4, func() error {
} task, err := edgeGateway.RemoveNATMapping("DNAT", d.Get("external_ip").(string),
task, err = edgeGateway.RemoveNATMapping("DNAT", d.Get("external_ip").(string),
d.Get("internal_ip").(string), d.Get("internal_ip").(string),
portString) portString)
if err != nil { if err != nil {
if v, _ := regexp.MatchString("is busy completing an operation.$", err.Error()); v { return fmt.Errorf("Error setting DNAT rules: %#v", err)
time.Sleep(3 * time.Second)
continue
} else {
return fmt.Errorf("Error setting DNAT rules: %#v", err)
}
} }
break
}
err := task.WaitTaskCompletion() return task.WaitTaskCompletion()
})
if err != nil { if err != nil {
return fmt.Errorf("Error completing tasks: %#v", err) return fmt.Errorf("Error completing tasks: %#v", err)
} }

View File

@ -6,12 +6,10 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/schema"
"github.com/opencredo/vmware-govcd" "github.com/opencredo/vmware-govcd"
types "github.com/opencredo/vmware-govcd/types/v56" types "github.com/opencredo/vmware-govcd/types/v56"
"strings" "strings"
"time"
) )
func resourceVcdNetwork() *schema.Resource { func resourceVcdNetwork() *schema.Resource {
@ -151,29 +149,33 @@ func resourceVcdNetworkCreate(d *schema.ResourceData, meta interface{}) error {
} }
log.Printf("[INFO] NETWORK: %#v", newnetwork) log.Printf("[INFO] NETWORK: %#v", newnetwork)
err = vcd_client.OrgVdc.CreateOrgVDCNetwork(newnetwork)
err = retryCall(4, func() error {
return vcd_client.OrgVdc.CreateOrgVDCNetwork(newnetwork)
})
if err != nil { if err != nil {
return fmt.Errorf("Error: %#v", err) return fmt.Errorf("Error: %#v", err)
} }
err = vcd_client.OrgVdc.Refresh()
if err != nil {
return fmt.Errorf("Error refreshing vdc: %#v", err)
}
network, err := vcd_client.OrgVdc.FindVDCNetwork(d.Get("name").(string))
if err != nil {
return fmt.Errorf("Error finding network: %#v", err)
}
if dhcp, ok := d.GetOk("dhcp_pool"); ok { if dhcp, ok := d.GetOk("dhcp_pool"); ok {
err := vcd_client.OrgVdc.Refresh() err = retryCall(4, func() error {
if err != nil { task, err := edgeGateway.AddDhcpPool(network.OrgVDCNetwork, dhcp.(*schema.Set).List())
return fmt.Errorf("Error refreshing vdc: %#v", err) if err != nil {
} return fmt.Errorf("Error adding DHCP pool: %#v", err)
}
network, err := vcd_client.OrgVdc.FindVDCNetwork(d.Get("name").(string)) return task.WaitTaskCompletion()
if err != nil { })
return fmt.Errorf("Error finding network: %#v", err)
}
task, err := edgeGateway.AddDhcpPool(network.OrgVDCNetwork, dhcp.(*schema.Set).List())
if err != nil {
return fmt.Errorf("Error adding DHCP pool: %#v", err)
}
err = task.WaitTaskCompletion()
if err != nil { if err != nil {
return fmt.Errorf("Error completing tasks: %#v", err) return fmt.Errorf("Error completing tasks: %#v", err)
} }
@ -233,16 +235,12 @@ func resourceVcdNetworkDelete(d *schema.ResourceData, meta interface{}) error {
return fmt.Errorf("Error finding network: %#v", err) return fmt.Errorf("Error finding network: %#v", err)
} }
err = resource.Retry(3*time.Minute, func() error { err = retryCall(4, func() error {
task, err := network.Delete() task, err := network.Delete()
if err != nil { if err != nil {
return fmt.Errorf("Error Deleting Network: %#v", err) return fmt.Errorf("Error Deleting Network: %#v", err)
} }
err = task.WaitTaskCompletion() return task.WaitTaskCompletion()
if err != nil {
return fmt.Errorf("Error completing tasks: %#v", err)
}
return nil
}) })
if err != nil { if err != nil {
return err return err

View File

@ -4,8 +4,6 @@ import (
"fmt" "fmt"
"github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/schema"
"github.com/opencredo/vmware-govcd" "github.com/opencredo/vmware-govcd"
"regexp"
"time"
) )
func resourceVcdSNAT() *schema.Resource { func resourceVcdSNAT() *schema.Resource {
@ -42,42 +40,27 @@ func resourceVcdSNATCreate(d *schema.ResourceData, meta interface{}) error {
// operation we must wait until we can aquire a lock on the client // operation we must wait until we can aquire a lock on the client
vcd_client.Mutex.Lock() vcd_client.Mutex.Lock()
defer vcd_client.Mutex.Unlock() defer vcd_client.Mutex.Unlock()
var task govcd.Task
// Creating a loop to offer further protection from the edge gateway erroring // Creating a loop to offer further protection from the edge gateway erroring
// due to being busy eg another person is using another client so wouldn't be // due to being busy eg another person is using another client so wouldn't be
// constrained by out lock. If the edge gateway reurns with a busy error, wait // constrained by out lock. If the edge gateway reurns with a busy error, wait
// 3 seconds and then try again. Continue until a non-busy error or success // 3 seconds and then try again. Continue until a non-busy error or success
for { edgeGateway, err := vcd_client.OrgVdc.FindEdgeGateway(d.Get("edge_gateway").(string))
err := vcd_client.OrgVdc.Refresh() if err != nil {
if err != nil { return fmt.Errorf("Unable to find edge gateway: %#v", err)
return fmt.Errorf("Error refreshing vdc: %#v", err)
}
edgeGateway, err := vcd_client.OrgVdc.FindEdgeGateway(d.Get("edge_gateway").(string))
if err != nil {
return fmt.Errorf("Unable to find edge gateway: %#v", err)
}
task, err = edgeGateway.AddNATMapping("SNAT", d.Get("internal_ip").(string),
d.Get("external_ip").(string),
"any")
if err != nil {
if v, _ := regexp.MatchString("is busy completing an operation.$", err.Error()); v {
time.Sleep(3 * time.Second)
continue
} else {
return fmt.Errorf("Error setting SNAT rules: %#v", err)
}
}
break
} }
err := task.WaitTaskCompletion() err = retryCall(4, func() error {
task, err := edgeGateway.AddNATMapping("SNAT", d.Get("internal_ip").(string),
d.Get("external_ip").(string),
"any")
if err != nil {
return fmt.Errorf("Error setting SNAT rules: %#v", err)
}
return task.WaitTaskCompletion()
})
if err != nil { if err != nil {
return fmt.Errorf("Error completing tasks: %#v", err) return err
} }
d.SetId(d.Get("internal_ip").(string)) d.SetId(d.Get("internal_ip").(string))
@ -120,42 +103,24 @@ func resourceVcdSNATDelete(d *schema.ResourceData, meta interface{}) error {
// operation we must wait until we can aquire a lock on the client // operation we must wait until we can aquire a lock on the client
vcd_client.Mutex.Lock() vcd_client.Mutex.Lock()
defer vcd_client.Mutex.Unlock() defer vcd_client.Mutex.Unlock()
var task govcd.Task
// Creating a loop to offer further protection from the edge gateway erroring edgeGateway, err := vcd_client.OrgVdc.FindEdgeGateway(d.Get("edge_gateway").(string))
// due to being busy eg another person is using another client so wouldn't be if err != nil {
// constrained by out lock. If the edge gateway reurns with a busy error, wait return fmt.Errorf("Unable to find edge gateway: %#v", err)
// 3 seconds and then try again. Continue until a non-busy error or success }
for {
err := vcd_client.OrgVdc.Refresh()
if err != nil {
return fmt.Errorf("Error refreshing vdc: %#v", err)
}
edgeGateway, err := vcd_client.OrgVdc.FindEdgeGateway(d.Get("edge_gateway").(string)) err = retryCall(4, func() error {
task, err := edgeGateway.RemoveNATMapping("SNAT", d.Get("internal_ip").(string),
if err != nil {
return fmt.Errorf("Unable to find edge gateway: %#v", err)
}
task, err = edgeGateway.RemoveNATMapping("SNAT", d.Get("internal_ip").(string),
d.Get("external_ip").(string), d.Get("external_ip").(string),
"") "")
if err != nil { if err != nil {
if v, _ := regexp.MatchString("is busy completing an operation.$", err.Error()); v { return fmt.Errorf("Error setting SNAT rules: %#v", err)
time.Sleep(3 * time.Second)
continue
} else {
return fmt.Errorf("Error setting SNAT rules: %#v", err)
}
} }
break return task.WaitTaskCompletion()
})
if err != nil {
return err
} }
err := task.WaitTaskCompletion()
if err != nil {
return fmt.Errorf("Error completing tasks: %#v", err)
}
return nil return nil
} }

View File

@ -2,12 +2,10 @@ package vcd
import ( import (
"fmt" "fmt"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/schema"
"github.com/opencredo/vmware-govcd" "github.com/opencredo/vmware-govcd"
types "github.com/opencredo/vmware-govcd/types/v56" types "github.com/opencredo/vmware-govcd/types/v56"
"log" "log"
"time"
) )
func resourceVcdVApp() *schema.Resource { func resourceVcdVApp() *schema.Resource {
@ -135,11 +133,16 @@ func resourceVcdVAppCreate(d *schema.ResourceData, meta interface{}) error {
}, },
} }
err = resource.Retry(4*time.Minute, func() error { err = retryCall(4, func() error {
err = vcd_client.OrgVdc.InstantiateVAppTemplate(createvapp) e := vcd_client.OrgVdc.InstantiateVAppTemplate(createvapp)
if err != nil { if e != nil {
return fmt.Errorf("Error: %#v", err) return fmt.Errorf("Error: %#v", e)
}
e = vcd_client.OrgVdc.Refresh()
if e != nil {
return fmt.Errorf("Error: %#v", e)
} }
return nil return nil
}) })
@ -147,72 +150,106 @@ func resourceVcdVAppCreate(d *schema.ResourceData, meta interface{}) error {
return err return err
} }
err = vcd_client.OrgVdc.Refresh() // err = resource.Retry(4*time.Minute, func() error {
if err != nil { // err = vcd_client.OrgVdc.InstantiateVAppTemplate(createvapp)
return fmt.Errorf("Error: %#v", err) //
} // if err != nil {
// return fmt.Errorf("Error: %#v", err)
// }
// return nil
// })
// if err != nil {
// return err
// }
vapp, err := vcd_client.OrgVdc.FindVAppByName(d.Get("name").(string)) vapp, err := vcd_client.OrgVdc.FindVAppByName(d.Get("name").(string))
task, err := vapp.ChangeMemorySize(d.Get("memory").(int))
err = task.WaitTaskCompletion() err = retryCall(4, func() error {
task, err := vapp.ChangeMemorySize(d.Get("memory").(int))
if err != nil {
return fmt.Errorf("Error changing memory size: %#v", err)
}
return task.WaitTaskCompletion()
})
if err != nil { if err != nil {
return fmt.Errorf("Error changing memory size: %#v", err) return err
} }
task, err = vapp.ChangeCPUcount(d.Get("cpus").(int)) err = retryCall(4, func() error {
err = task.WaitTaskCompletion() task, err := vapp.ChangeCPUcount(d.Get("cpus").(int))
if err != nil {
return fmt.Errorf("Error changing cpu count: %#v", err)
}
return task.WaitTaskCompletion()
})
if err != nil { if err != nil {
return fmt.Errorf("Error changing cpu count: %#v", err) return fmt.Errorf("Error completing task: %#v", err)
} }
task, err = vapp.ChangeVMName(d.Get("name").(string)) err = retryCall(4, func() error {
if err != nil { task, err := vapp.ChangeVMName(d.Get("name").(string))
return fmt.Errorf("Error with vm name change: %#v", err) if err != nil {
} return fmt.Errorf("Error with vm name change: %#v", err)
}
err = task.WaitTaskCompletion() return task.WaitTaskCompletion()
})
if err != nil { if err != nil {
return fmt.Errorf("Error changing vmname: %#v", err) return fmt.Errorf("Error changing vmname: %#v", err)
} }
task, err = vapp.ChangeNetworkConfig(d.Get("network_name").(string), d.Get("ip").(string)) err = retryCall(4, func() error {
if err != nil { task, err := vapp.ChangeNetworkConfig(d.Get("network_name").(string), d.Get("ip").(string))
return fmt.Errorf("Error with Networking change: %#v", err) if err != nil {
} return fmt.Errorf("Error with Networking change: %#v", err)
err = task.WaitTaskCompletion() }
return task.WaitTaskCompletion()
})
if err != nil { if err != nil {
return fmt.Errorf("Error changing network: %#v", err) return fmt.Errorf("Error changing network: %#v", err)
} }
metadata := d.Get("metadata").(map[string]interface{}) err = retryCall(4, func() error {
for k, v := range metadata { metadata := d.Get("metadata").(map[string]interface{})
task, err = vapp.AddMetadata(k, v.(string)) for k, v := range metadata {
if err != nil { task, err := vapp.AddMetadata(k, v.(string))
return fmt.Errorf("Error adding metadata: %#v", err) if err != nil {
} return fmt.Errorf("Error adding metadata: %#v", err)
err = task.WaitTaskCompletion() }
if err != nil { err = task.WaitTaskCompletion()
return fmt.Errorf("Error completing tasks: %#v", err) if err != nil {
return fmt.Errorf("Error completing tasks: %#v", err)
}
} }
return nil
})
if err != nil {
return fmt.Errorf("Error adding metadata: %#v", err)
} }
if initscript, ok := d.GetOk("initscript"); ok { if initscript, ok := d.GetOk("initscript"); ok {
task, err = vapp.RunCustomizationScript(d.Get("name").(string), initscript.(string)) err = retryCall(4, func() error {
if err != nil { task, err := vapp.RunCustomizationScript(d.Get("name").(string), initscript.(string))
return fmt.Errorf("Error with setting init script: %#v", err) if err != nil {
} return fmt.Errorf("Error with setting init script: %#v", err)
err = task.WaitTaskCompletion() }
return task.WaitTaskCompletion()
})
if err != nil { if err != nil {
return fmt.Errorf("Error completing tasks: %#v", err) return fmt.Errorf("Error completing tasks: %#v", err)
} }
} }
if d.Get("power_on").(bool) { if d.Get("power_on").(bool) {
task, err = vapp.PowerOn() err = retryCall(4, func() error {
if err != nil { task, err := vapp.PowerOn()
return fmt.Errorf("Error Powering Up: %#v", err) if err != nil {
} return fmt.Errorf("Error Powering Up: %#v", err)
err = task.WaitTaskCompletion() }
return task.WaitTaskCompletion()
})
if err != nil { if err != nil {
return fmt.Errorf("Error completing tasks: %#v", err) return fmt.Errorf("Error completing tasks: %#v", err)
} }

View File

@ -1,8 +1,10 @@
package vcd package vcd
import ( import (
"github.com/hashicorp/terraform/helper/resource"
types "github.com/opencredo/vmware-govcd/types/v56" types "github.com/opencredo/vmware-govcd/types/v56"
"strconv" "strconv"
"time"
) )
func expandIpRange(configured []interface{}) (types.IPRanges, error) { func expandIpRange(configured []interface{}) (types.IPRanges, error) {
@ -101,3 +103,7 @@ func getPortString(port int) string {
portstring := strconv.Itoa(port) portstring := strconv.Itoa(port)
return portstring return portstring
} }
func retryCall(min int, f resource.RetryFunc) error {
return resource.Retry(time.Duration(min)*time.Minute, f)
}