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

provider/cloudstack: add new provider option and some more... #2753

Merged
merged 3 commits into from
Jul 16, 2015
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
14 changes: 8 additions & 6 deletions builtin/providers/cloudstack/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@ import "github.com/xanzy/go-cloudstack/cloudstack"
// Config is the configuration structure used to instantiate a
// new CloudStack client.
type Config struct {
ApiURL string
ApiKey string
SecretKey string
Timeout int64
APIURL string
APIKey string
SecretKey string
HTTPGETOnly bool
Timeout int64
}

// Client() returns a new CloudStack client.
// NewClient returns a new CloudStack client.
func (c *Config) NewClient() (*cloudstack.CloudStackClient, error) {
cs := cloudstack.NewAsyncClient(c.ApiURL, c.ApiKey, c.SecretKey, false)
cs := cloudstack.NewAsyncClient(c.APIURL, c.APIKey, c.SecretKey, false)
cs.HTTPGETOnly = c.HTTPGETOnly
cs.AsyncTimeout(c.Timeout)
return cs, nil
}
16 changes: 12 additions & 4 deletions builtin/providers/cloudstack/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ func Provider() terraform.ResourceProvider {
DefaultFunc: schema.EnvDefaultFunc("CLOUDSTACK_SECRET_KEY", nil),
},

"http_get_only": &schema.Schema{
Type: schema.TypeBool,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("CLOUDSTACK_HTTP_GET_ONLY", false),
},

"timeout": &schema.Schema{
Type: schema.TypeInt,
Required: true,
Expand All @@ -45,6 +51,7 @@ func Provider() terraform.ResourceProvider {
"cloudstack_network_acl_rule": resourceCloudStackNetworkACLRule(),
"cloudstack_nic": resourceCloudStackNIC(),
"cloudstack_port_forward": resourceCloudStackPortForward(),
"cloudstack_secondary_ipaddress": resourceCloudStackSecondaryIPAddress(),
"cloudstack_ssh_keypair": resourceCloudStackSSHKeyPair(),
"cloudstack_template": resourceCloudStackTemplate(),
"cloudstack_vpc": resourceCloudStackVPC(),
Expand All @@ -59,10 +66,11 @@ func Provider() terraform.ResourceProvider {

func providerConfigure(d *schema.ResourceData) (interface{}, error) {
config := Config{
ApiURL: d.Get("api_url").(string),
ApiKey: d.Get("api_key").(string),
SecretKey: d.Get("secret_key").(string),
Timeout: int64(d.Get("timeout").(int)),
APIURL: d.Get("api_url").(string),
APIKey: d.Get("api_key").(string),
SecretKey: d.Get("secret_key").(string),
HTTPGETOnly: d.Get("http_get_only").(bool),
Timeout: int64(d.Get("timeout").(int)),
}

return config.NewClient()
Expand Down
2 changes: 1 addition & 1 deletion builtin/providers/cloudstack/resource_cloudstack_disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ func resourceCloudStackDiskRead(d *schema.ResourceData, meta interface{}) error
}

d.Set("device", retrieveDeviceName(v.Deviceid, c.Name))
d.Set("virtual_machine", v.Vmname)
setValueOrUUID(d, "virtual_machine", v.Vmname, v.Virtualmachineid)
}

return nil
Expand Down
32 changes: 23 additions & 9 deletions builtin/providers/cloudstack/resource_cloudstack_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,14 @@ func resourceCloudStackInstanceCreate(d *schema.ResourceData, meta interface{})
return e.Error()
}

// Retrieve the zone UUID
zoneid, e := retrieveUUID(cs, "zone", d.Get("zone").(string))
if e != nil {
return e.Error()
}

// Retrieve the zone object
zone, _, err := cs.Zone.GetZoneByName(d.Get("zone").(string))
zone, _, err := cs.Zone.GetZoneByID(zoneid)
if err != nil {
return err
}
Expand Down Expand Up @@ -168,12 +174,18 @@ func resourceCloudStackInstanceCreate(d *schema.ResourceData, meta interface{})
if userData, ok := d.GetOk("user_data"); ok {
ud := base64.StdEncoding.EncodeToString([]byte(userData.(string)))

// deployVirtualMachine uses POST, so max userdata is 32K
// https://github.com/xanzy/go-cloudstack/commit/c767de689df1faedfec69233763a7c5334bee1f6
if len(ud) > 32768 {
// deployVirtualMachine uses POST by default, so max userdata is 32K
maxUD := 32768

if cs.HTTPGETOnly {
// deployVirtualMachine using GET instead, so max userdata is 2K
maxUD = 2048
}

if len(ud) > maxUD {
return fmt.Errorf(
"The supplied user_data contains %d bytes after encoding, "+
"this exeeds the limit of 32768 bytes", len(ud))
"this exeeds the limit of %d bytes", len(ud), maxUD)
}

p.SetUserdata(ud)
Expand Down Expand Up @@ -204,7 +216,6 @@ func resourceCloudStackInstanceRead(d *schema.ResourceData, meta interface{}) er
if err != nil {
if count == 0 {
log.Printf("[DEBUG] Instance %s does no longer exist", d.Get("name").(string))
// Clear out all details so it's obvious the instance is gone
d.SetId("")
return nil
}
Expand All @@ -216,13 +227,13 @@ func resourceCloudStackInstanceRead(d *schema.ResourceData, meta interface{}) er
d.Set("name", vm.Name)
d.Set("display_name", vm.Displayname)
d.Set("ipaddress", vm.Nic[0].Ipaddress)
d.Set("zone", vm.Zonename)
//NB cloudstack sometimes sends back the wrong keypair name, so dont update it

setValueOrUUID(d, "network", vm.Nic[0].Networkname, vm.Nic[0].Networkid)
setValueOrUUID(d, "service_offering", vm.Serviceofferingname, vm.Serviceofferingid)
setValueOrUUID(d, "template", vm.Templatename, vm.Templateid)
setValueOrUUID(d, "project", vm.Project, vm.Projectid)
setValueOrUUID(d, "zone", vm.Zonename, vm.Zoneid)

return nil
}
Expand Down Expand Up @@ -256,7 +267,8 @@ func resourceCloudStackInstanceUpdate(d *schema.ResourceData, meta interface{})
// Attributes that require reboot to update
if d.HasChange("service_offering") || d.HasChange("keypair") {
// Before we can actually make these changes, the virtual machine must be stopped
_, err := cs.VirtualMachine.StopVirtualMachine(cs.VirtualMachine.NewStopVirtualMachineParams(d.Id()))
_, err := cs.VirtualMachine.StopVirtualMachine(
cs.VirtualMachine.NewStopVirtualMachineParams(d.Id()))
if err != nil {
return fmt.Errorf(
"Error stopping instance %s before making changes: %s", name, err)
Expand Down Expand Up @@ -299,12 +311,14 @@ func resourceCloudStackInstanceUpdate(d *schema.ResourceData, meta interface{})
}

// Start the virtual machine again
_, err = cs.VirtualMachine.StartVirtualMachine(cs.VirtualMachine.NewStartVirtualMachineParams(d.Id()))
_, err = cs.VirtualMachine.StartVirtualMachine(
cs.VirtualMachine.NewStartVirtualMachineParams(d.Id()))
if err != nil {
return fmt.Errorf(
"Error starting instance %s after making changes", name)
}
}

d.Partial(false)
return resourceCloudStackInstanceRead(d, meta)
}
Expand Down
4 changes: 2 additions & 2 deletions builtin/providers/cloudstack/resource_cloudstack_ipaddress.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func resourceCloudStackIPAddressRead(d *schema.ResourceData, meta interface{}) e
return err
}

d.Set("network", n.Name)
setValueOrUUID(d, "network", n.Name, f.Associatednetworkid)
}

if _, ok := d.GetOk("vpc"); ok {
Expand All @@ -115,7 +115,7 @@ func resourceCloudStackIPAddressRead(d *schema.ResourceData, meta interface{}) e
return err
}

d.Set("vpc", v.Name)
setValueOrUUID(d, "vpc", v.Name, f.Vpcid)
}

return nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,21 +157,23 @@ func resourceCloudStackNetworkACLRuleCreateRule(
p.SetIcmptype(rule["icmp_type"].(int))
p.SetIcmpcode(rule["icmp_code"].(int))

r, err := cs.NetworkACL.CreateNetworkACL(p)
r, err := Retry(4, retryableACLCreationFunc(cs, p))
if err != nil {
return err
}
uuids["icmp"] = r.Id

uuids["icmp"] = r.(*cloudstack.CreateNetworkACLResponse).Id
rule["uuids"] = uuids
}

// If the protocol is ALL set the needed parameters
if rule["protocol"].(string) == "all" {
r, err := cs.NetworkACL.CreateNetworkACL(p)
r, err := Retry(4, retryableACLCreationFunc(cs, p))
if err != nil {
return err
}
uuids["all"] = r.Id

uuids["all"] = r.(*cloudstack.CreateNetworkACLResponse).Id
rule["uuids"] = uuids
}

Expand Down Expand Up @@ -206,15 +208,15 @@ func resourceCloudStackNetworkACLRuleCreateRule(
p.SetStartport(startPort)
p.SetEndport(endPort)

r, err := cs.NetworkACL.CreateNetworkACL(p)
r, err := Retry(4, retryableACLCreationFunc(cs, p))
if err != nil {
return err
}

ports.Add(port)
rule["ports"] = ports

uuids[port.(string)] = r.Id
uuids[port.(string)] = r.(*cloudstack.CreateNetworkACLResponse).Id
rule["uuids"] = uuids
}
}
Expand Down Expand Up @@ -593,3 +595,15 @@ func verifyNetworkACLRuleParams(d *schema.ResourceData, rule map[string]interfac

return nil
}

func retryableACLCreationFunc(
cs *cloudstack.CloudStackClient,
p *cloudstack.CreateNetworkACLParams) func() (interface{}, error) {
return func() (interface{}, error) {
r, err := cs.NetworkACL.CreateNetworkACL(p)
if err != nil {
return nil, err
}
return r, nil
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ resource "cloudstack_vpc" "foobar" {
resource "cloudstack_network_acl" "foo" {
name = "terraform-acl"
description = "terraform-acl-text"
vpc = "${cloudstack_vpc.foobar.name}"
vpc = "${cloudstack_vpc.foobar.id}"
}

resource "cloudstack_network_acl_rule" "foo" {
Expand Down
17 changes: 14 additions & 3 deletions builtin/providers/cloudstack/resource_cloudstack_port_forward.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,12 @@ func resourceCloudStackPortForwardCreateForward(
}

// Retrieve the virtual_machine UUID
vm, _, err := cs.VirtualMachine.GetVirtualMachineByName(forward["virtual_machine"].(string))
virtualmachineid, e := retrieveUUID(cs, "virtual_machine", forward["virtual_machine"].(string))
if e != nil {
return e.Error()
}

vm, _, err := cs.VirtualMachine.GetVirtualMachineByID(virtualmachineid)
if err != nil {
return err
}
Expand Down Expand Up @@ -186,7 +191,13 @@ func resourceCloudStackPortForwardRead(d *schema.ResourceData, meta interface{})
forward["protocol"] = r.Protocol
forward["private_port"] = privPort
forward["public_port"] = pubPort
forward["virtual_machine"] = r.Virtualmachinename

if isUUID(forward["virtual_machine"].(string)) {
forward["virtual_machine"] = r.Virtualmachineid
} else {
forward["virtual_machine"] = r.Virtualmachinename
}

forwards.Add(forward)
}
}
Expand Down Expand Up @@ -219,7 +230,7 @@ func resourceCloudStackPortForwardRead(d *schema.ResourceData, meta interface{})
}
}

for uuid, _ := range uuids {
for uuid := range uuids {
// Make a dummy forward to hold the unknown UUID
forward := map[string]interface{}{
"protocol": "N/A",
Expand Down
Loading