Fix issue #3033 and update tweak several cloudstack resources

- Added a retry loop for attaching disks as this something was tried to
fast when the VM was still booting
- Fix issue #3033
- Update docs for latest updates and done some minor refactoring
(styling)
This commit is contained in:
Sander van Harmelen 2015-08-21 16:59:35 +02:00
parent cb49c8da3d
commit 6b8d37e938
9 changed files with 102 additions and 94 deletions

View File

@ -56,17 +56,17 @@ func resourceCloudStackDisk() *schema.Resource {
Optional: true, Optional: true,
}, },
"zone": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"project": &schema.Schema{ "project": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
}, },
"zone": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
}, },
} }
} }
@ -80,17 +80,6 @@ func resourceCloudStackDiskCreate(d *schema.ResourceData, meta interface{}) erro
// Create a new parameter struct // Create a new parameter struct
p := cs.Volume.NewCreateVolumeParams(name) p := cs.Volume.NewCreateVolumeParams(name)
// If there is a project supplied, we retreive and set the project id
if project, ok := d.GetOk("project"); ok {
// Retrieve the project UUID
projectid, e := retrieveUUID(cs, "project", project.(string))
if e != nil {
return e.Error()
}
// Set the default project ID
p.SetProjectid(projectid)
}
// Retrieve the disk_offering UUID // Retrieve the disk_offering UUID
diskofferingid, e := retrieveUUID(cs, "disk_offering", d.Get("disk_offering").(string)) diskofferingid, e := retrieveUUID(cs, "disk_offering", d.Get("disk_offering").(string))
if e != nil { if e != nil {
@ -104,6 +93,17 @@ func resourceCloudStackDiskCreate(d *schema.ResourceData, meta interface{}) erro
p.SetSize(int64(d.Get("size").(int))) p.SetSize(int64(d.Get("size").(int)))
} }
// If there is a project supplied, we retreive and set the project id
if project, ok := d.GetOk("project"); ok {
// Retrieve the project UUID
projectid, e := retrieveUUID(cs, "project", project.(string))
if e != nil {
return e.Error()
}
// Set the default project ID
p.SetProjectid(projectid)
}
// Retrieve the zone UUID // Retrieve the zone UUID
zoneid, e := retrieveUUID(cs, "zone", d.Get("zone").(string)) zoneid, e := retrieveUUID(cs, "zone", d.Get("zone").(string))
if e != nil { if e != nil {
@ -125,6 +125,7 @@ func resourceCloudStackDiskCreate(d *schema.ResourceData, meta interface{}) erro
d.SetPartial("disk_offering") d.SetPartial("disk_offering")
d.SetPartial("size") d.SetPartial("size")
d.SetPartial("virtual_machine") d.SetPartial("virtual_machine")
d.SetPartial("project")
d.SetPartial("zone") d.SetPartial("zone")
if d.Get("attach").(bool) { if d.Get("attach").(bool) {
@ -160,8 +161,8 @@ func resourceCloudStackDiskRead(d *schema.ResourceData, meta interface{}) error
d.Set("size", int(v.Size/(1024*1024*1024))) // Needed to get GB's again d.Set("size", int(v.Size/(1024*1024*1024))) // Needed to get GB's again
setValueOrUUID(d, "disk_offering", v.Diskofferingname, v.Diskofferingid) setValueOrUUID(d, "disk_offering", v.Diskofferingname, v.Diskofferingid)
setValueOrUUID(d, "zone", v.Zonename, v.Zoneid)
setValueOrUUID(d, "project", v.Project, v.Projectid) setValueOrUUID(d, "project", v.Project, v.Projectid)
setValueOrUUID(d, "zone", v.Zonename, v.Zoneid)
if v.Attached != "" { if v.Attached != "" {
// Get the virtual machine details // Get the virtual machine details
@ -319,12 +320,12 @@ func resourceCloudStackDiskAttach(d *schema.ResourceData, meta interface{}) erro
} }
// Attach the new volume // Attach the new volume
r, err := cs.Volume.AttachVolume(p) r, err := Retry(4, retryableAttachVolumeFunc(cs, p))
if err != nil { if err != nil {
return err return err
} }
d.SetId(r.Id) d.SetId(r.(*cloudstack.AttachVolumeResponse).Id)
return nil return nil
} }
@ -386,6 +387,18 @@ func isAttached(cs *cloudstack.CloudStackClient, id string) (bool, error) {
return v.Attached != "", nil return v.Attached != "", nil
} }
func retryableAttachVolumeFunc(
cs *cloudstack.CloudStackClient,
p *cloudstack.AttachVolumeParams) func() (interface{}, error) {
return func() (interface{}, error) {
r, err := cs.Volume.AttachVolume(p)
if err != nil {
return nil, err
}
return r, nil
}
}
func retrieveDeviceID(device string) int64 { func retrieveDeviceID(device string) int64 {
switch device { switch device {
case "/dev/xvdb", "D:": case "/dev/xvdb", "D:":
@ -426,87 +439,73 @@ func retrieveDeviceName(device int64, os string) string {
case 1: case 1:
if os == "Windows" { if os == "Windows" {
return "D:" return "D:"
} else {
return "/dev/xvdb"
} }
return "/dev/xvdb"
case 2: case 2:
if os == "Windows" { if os == "Windows" {
return "E:" return "E:"
} else {
return "/dev/xvdc"
} }
return "/dev/xvdc"
case 4: case 4:
if os == "Windows" { if os == "Windows" {
return "F:" return "F:"
} else {
return "/dev/xvde"
} }
return "/dev/xvde"
case 5: case 5:
if os == "Windows" { if os == "Windows" {
return "G:" return "G:"
} else {
return "/dev/xvdf"
} }
return "/dev/xvdf"
case 6: case 6:
if os == "Windows" { if os == "Windows" {
return "H:" return "H:"
} else {
return "/dev/xvdg"
} }
return "/dev/xvdg"
case 7: case 7:
if os == "Windows" { if os == "Windows" {
return "I:" return "I:"
} else {
return "/dev/xvdh"
} }
return "/dev/xvdh"
case 8: case 8:
if os == "Windows" { if os == "Windows" {
return "J:" return "J:"
} else {
return "/dev/xvdi"
} }
return "/dev/xvdi"
case 9: case 9:
if os == "Windows" { if os == "Windows" {
return "K:" return "K:"
} else {
return "/dev/xvdj"
} }
return "/dev/xvdj"
case 10: case 10:
if os == "Windows" { if os == "Windows" {
return "L:" return "L:"
} else {
return "/dev/xvdk"
} }
return "/dev/xvdk"
case 11: case 11:
if os == "Windows" { if os == "Windows" {
return "M:" return "M:"
} else {
return "/dev/xvdl"
} }
return "/dev/xvdl"
case 12: case 12:
if os == "Windows" { if os == "Windows" {
return "N:" return "N:"
} else {
return "/dev/xvdm"
} }
return "/dev/xvdm"
case 13: case 13:
if os == "Windows" { if os == "Windows" {
return "O:" return "O:"
} else {
return "/dev/xvdn"
} }
return "/dev/xvdn"
case 14: case 14:
if os == "Windows" { if os == "Windows" {
return "P:" return "P:"
} else {
return "/dev/xvdo"
} }
return "/dev/xvdo"
case 15: case 15:
if os == "Windows" { if os == "Windows" {
return "Q:" return "Q:"
} else {
return "/dev/xvdp"
} }
return "/dev/xvdp"
default: default:
return "unknown" return "unknown"
} }

View File

@ -28,16 +28,16 @@ func resourceCloudStackIPAddress() *schema.Resource {
ForceNew: true, ForceNew: true,
}, },
"ipaddress": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"project": &schema.Schema{ "project": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
}, },
"ipaddress": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
}, },
} }
} }
@ -52,17 +52,6 @@ func resourceCloudStackIPAddressCreate(d *schema.ResourceData, meta interface{})
// Create a new parameter struct // Create a new parameter struct
p := cs.Address.NewAssociateIpAddressParams() p := cs.Address.NewAssociateIpAddressParams()
// If there is a project supplied, we retreive and set the project id
if project, ok := d.GetOk("project"); ok {
// Retrieve the project UUID
projectid, e := retrieveUUID(cs, "project", project.(string))
if e != nil {
return e.Error()
}
// Set the default project ID
p.SetProjectid(projectid)
}
if network, ok := d.GetOk("network"); ok { if network, ok := d.GetOk("network"); ok {
// Retrieve the network UUID // Retrieve the network UUID
networkid, e := retrieveUUID(cs, "network", network.(string)) networkid, e := retrieveUUID(cs, "network", network.(string))
@ -85,6 +74,17 @@ func resourceCloudStackIPAddressCreate(d *schema.ResourceData, meta interface{})
p.SetVpcid(vpcid) p.SetVpcid(vpcid)
} }
// If there is a project supplied, we retreive and set the project id
if project, ok := d.GetOk("project"); ok {
// Retrieve the project UUID
projectid, e := retrieveUUID(cs, "project", project.(string))
if e != nil {
return e.Error()
}
// Set the default project ID
p.SetProjectid(projectid)
}
// Associate a new IP address // Associate a new IP address
r, err := cs.Address.AssociateIpAddress(p) r, err := cs.Address.AssociateIpAddress(p)
if err != nil { if err != nil {

View File

@ -52,17 +52,17 @@ func resourceCloudStackNetwork() *schema.Resource {
ForceNew: true, ForceNew: true,
}, },
"zone": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"project": &schema.Schema{ "project": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
}, },
"zone": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
}, },
} }
} }
@ -93,17 +93,6 @@ func resourceCloudStackNetworkCreate(d *schema.ResourceData, meta interface{}) e
// Create a new parameter struct // Create a new parameter struct
p := cs.Network.NewCreateNetworkParams(displaytext.(string), name, networkofferingid, zoneid) p := cs.Network.NewCreateNetworkParams(displaytext.(string), name, networkofferingid, zoneid)
// If there is a project supplied, we retreive and set the project id
if project, ok := d.GetOk("project"); ok {
// Retrieve the project UUID
projectid, e := retrieveUUID(cs, "project", project.(string))
if e != nil {
return e.Error()
}
// Set the default project ID
p.SetProjectid(projectid)
}
// Get the network details from the CIDR // Get the network details from the CIDR
m, err := parseCIDR(d.Get("cidr").(string)) m, err := parseCIDR(d.Get("cidr").(string))
if err != nil { if err != nil {
@ -136,6 +125,17 @@ func resourceCloudStackNetworkCreate(d *schema.ResourceData, meta interface{}) e
} }
} }
// If there is a project supplied, we retreive and set the project id
if project, ok := d.GetOk("project"); ok {
// Retrieve the project UUID
projectid, e := retrieveUUID(cs, "project", project.(string))
if e != nil {
return e.Error()
}
// Set the default project ID
p.SetProjectid(projectid)
}
// Create the new network // Create the new network
r, err := cs.Network.CreateNetwork(p) r, err := cs.Network.CreateNetwork(p)
if err != nil { if err != nil {
@ -168,8 +168,8 @@ func resourceCloudStackNetworkRead(d *schema.ResourceData, meta interface{}) err
d.Set("cidr", n.Cidr) d.Set("cidr", n.Cidr)
setValueOrUUID(d, "network_offering", n.Networkofferingname, n.Networkofferingid) setValueOrUUID(d, "network_offering", n.Networkofferingname, n.Networkofferingid)
setValueOrUUID(d, "zone", n.Zonename, n.Zoneid)
setValueOrUUID(d, "project", n.Project, n.Projectid) setValueOrUUID(d, "project", n.Project, n.Projectid)
setValueOrUUID(d, "zone", n.Zonename, n.Zoneid)
return nil return nil
} }

View File

@ -224,10 +224,7 @@ func resourceCloudStackPortForwardRead(d *schema.ResourceData, meta interface{})
// Delete all expected UUIDs from the uuids map // Delete all expected UUIDs from the uuids map
for _, forward := range forwards.List() { for _, forward := range forwards.List() {
forward := forward.(map[string]interface{}) forward := forward.(map[string]interface{})
delete(uuids, forward["uuid"].(string))
for _, id := range forward["uuids"].(map[string]interface{}) {
delete(uuids, id.(string))
}
} }
for uuid := range uuids { for uuid := range uuids {

View File

@ -40,16 +40,17 @@ func resourceCloudStackVPC() *schema.Resource {
ForceNew: true, ForceNew: true,
}, },
"zone": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"project": &schema.Schema{ "project": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
}, },
"zone": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
}, },
} }
} }
@ -80,7 +81,7 @@ func resourceCloudStackVPCCreate(d *schema.ResourceData, meta interface{}) error
// Create a new parameter struct // Create a new parameter struct
p := cs.VPC.NewCreateVPCParams(d.Get("cidr").(string), displaytext.(string), name, vpcofferingid, zoneid) p := cs.VPC.NewCreateVPCParams(d.Get("cidr").(string), displaytext.(string), name, vpcofferingid, zoneid)
// If there is a project supplied, we retreive and set the project id // If there is a project supplied, we retreive and set the project id
if project, ok := d.GetOk("project"); ok { if project, ok := d.GetOk("project"); ok {
// Retrieve the project UUID // Retrieve the project UUID
projectid, e := retrieveUUID(cs, "project", project.(string)) projectid, e := retrieveUUID(cs, "project", project.(string))
@ -122,8 +123,6 @@ func resourceCloudStackVPCRead(d *schema.ResourceData, meta interface{}) error {
d.Set("display_text", v.Displaytext) d.Set("display_text", v.Displaytext)
d.Set("cidr", v.Cidr) d.Set("cidr", v.Cidr)
setValueOrUUID(d, "zone", v.Zonename, v.Zoneid)
// Get the VPC offering details // Get the VPC offering details
o, _, err := cs.VPC.GetVPCOfferingByID(v.Vpcofferingid) o, _, err := cs.VPC.GetVPCOfferingByID(v.Vpcofferingid)
if err != nil { if err != nil {
@ -132,6 +131,7 @@ func resourceCloudStackVPCRead(d *schema.ResourceData, meta interface{}) error {
setValueOrUUID(d, "vpc_offering", o.Name, v.Vpcofferingid) setValueOrUUID(d, "vpc_offering", o.Name, v.Vpcofferingid)
setValueOrUUID(d, "project", v.Project, v.Projectid) setValueOrUUID(d, "project", v.Project, v.Projectid)
setValueOrUUID(d, "zone", v.Zonename, v.Zoneid)
return nil return nil
} }

View File

@ -47,6 +47,9 @@ The following arguments are supported:
* `virtual_machine` - (Optional) The name or ID of the virtual machine to which you * `virtual_machine` - (Optional) The name or ID of the virtual machine to which you
want to attach the disk volume. want to attach the disk volume.
* `project` - (Optional) The name or ID of the project to deploy this
instance to. Changing this forces a new resource to be created.
* `zone` - (Required) The name or ID of the zone where this disk volume will be available. * `zone` - (Required) The name or ID of the zone where this disk volume will be available.
Changing this forces a new resource to be created. Changing this forces a new resource to be created.

View File

@ -28,6 +28,9 @@ The following arguments are supported:
* `vpc` - (Optional) The name or ID of the VPC for which an IP address should * `vpc` - (Optional) The name or ID of the VPC for which an IP address should
be acquired and associated. Changing this forces a new resource to be created. be acquired and associated. Changing this forces a new resource to be created.
* `project` - (Optional) The name or ID of the project to deploy this
instance to. Changing this forces a new resource to be created.
*NOTE: Either `network` or `vpc` should have a value!* *NOTE: Either `network` or `vpc` should have a value!*
## Attributes Reference ## Attributes Reference

View File

@ -43,6 +43,9 @@ The following arguments are supported:
* `aclid` - (Optional) The ID of a network ACL that should be attached to the * `aclid` - (Optional) The ID of a network ACL that should be attached to the
network. Changing this forces a new resource to be created. network. Changing this forces a new resource to be created.
* `project` - (Optional) The name or ID of the project to deploy this
instance to. Changing this forces a new resource to be created.
* `zone` - (Required) The name or ID of the zone where this disk volume will be * `zone` - (Required) The name or ID of the zone where this disk volume will be
available. Changing this forces a new resource to be created. available. Changing this forces a new resource to be created.

View File

@ -37,6 +37,9 @@ The following arguments are supported:
* `vpc_offering` - (Required) The name or ID of the VPC offering to use for this VPC. * `vpc_offering` - (Required) The name or ID of the VPC offering to use for this VPC.
Changing this forces a new resource to be created. Changing this forces a new resource to be created.
* `project` - (Optional) The name or ID of the project to deploy this
instance to. Changing this forces a new resource to be created.
* `zone` - (Required) The name or ID of the zone where this disk volume will be * `zone` - (Required) The name or ID of the zone where this disk volume will be
available. Changing this forces a new resource to be created. available. Changing this forces a new resource to be created.