2014-12-10 22:20:52 +01:00
|
|
|
package cloudstack
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"regexp"
|
2015-07-16 17:40:04 +02:00
|
|
|
"time"
|
2014-12-10 22:20:52 +01:00
|
|
|
|
2015-04-29 11:21:37 +02:00
|
|
|
"github.com/hashicorp/terraform/helper/schema"
|
2014-12-10 22:20:52 +01:00
|
|
|
"github.com/xanzy/go-cloudstack/cloudstack"
|
|
|
|
)
|
|
|
|
|
2016-01-21 08:57:59 +01:00
|
|
|
// Define a regexp for parsing the port
|
|
|
|
var splitPorts = regexp.MustCompile(`^(\d+)(?:-(\d+))?$`)
|
|
|
|
|
2014-12-10 22:20:52 +01:00
|
|
|
type retrieveError struct {
|
|
|
|
name string
|
|
|
|
value string
|
|
|
|
err error
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *retrieveError) Error() error {
|
2015-10-05 14:05:21 +02:00
|
|
|
return fmt.Errorf("Error retrieving ID of %s %s: %s", e.name, e.value, e.err)
|
2014-12-10 22:20:52 +01:00
|
|
|
}
|
|
|
|
|
2015-10-05 14:05:21 +02:00
|
|
|
func setValueOrID(d *schema.ResourceData, key string, value string, id string) {
|
2016-04-21 17:31:53 +02:00
|
|
|
if cloudstack.IsID(d.Get(key).(string)) {
|
2015-10-05 14:05:21 +02:00
|
|
|
// If the given id is an empty string, check if the configured value matches
|
|
|
|
// the UnlimitedResourceID in which case we set id to UnlimitedResourceID
|
2016-04-21 17:31:53 +02:00
|
|
|
if id == "" && d.Get(key).(string) == cloudstack.UnlimitedResourceID {
|
|
|
|
id = cloudstack.UnlimitedResourceID
|
2015-10-05 14:05:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
d.Set(key, id)
|
2015-04-29 11:21:37 +02:00
|
|
|
} else {
|
|
|
|
d.Set(key, value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-25 19:42:01 +02:00
|
|
|
func retrieveID(cs *cloudstack.CloudStackClient, name string, value string, opts ...cloudstack.OptionFunc) (id string, e *retrieveError) {
|
2015-10-05 14:05:21 +02:00
|
|
|
// If the supplied value isn't a ID, try to retrieve the ID ourselves
|
2016-04-21 17:31:53 +02:00
|
|
|
if cloudstack.IsID(value) {
|
2014-12-10 22:20:52 +01:00
|
|
|
return value, nil
|
|
|
|
}
|
|
|
|
|
2015-10-05 14:05:21 +02:00
|
|
|
log.Printf("[DEBUG] Retrieving ID of %s: %s", name, value)
|
2014-12-10 22:20:52 +01:00
|
|
|
|
2016-09-01 10:48:49 +02:00
|
|
|
// Ignore counts, since an error is returned if there is no exact match
|
2014-12-10 22:20:52 +01:00
|
|
|
var err error
|
|
|
|
switch name {
|
|
|
|
case "disk_offering":
|
2016-09-01 10:48:49 +02:00
|
|
|
id, _, err = cs.DiskOffering.GetDiskOfferingID(value)
|
2014-12-10 22:20:52 +01:00
|
|
|
case "service_offering":
|
2016-09-01 10:48:49 +02:00
|
|
|
id, _, err = cs.ServiceOffering.GetServiceOfferingID(value)
|
2014-12-10 22:20:52 +01:00
|
|
|
case "network_offering":
|
2016-09-01 10:48:49 +02:00
|
|
|
id, _, err = cs.NetworkOffering.GetNetworkOfferingID(value)
|
2015-10-05 14:05:21 +02:00
|
|
|
case "project":
|
2016-09-01 10:48:49 +02:00
|
|
|
id, _, err = cs.Project.GetProjectID(value)
|
2014-12-10 22:20:52 +01:00
|
|
|
case "vpc_offering":
|
2016-09-01 10:48:49 +02:00
|
|
|
id, _, err = cs.VPC.GetVPCOfferingID(value)
|
2014-12-10 22:20:52 +01:00
|
|
|
case "zone":
|
2016-09-01 10:48:49 +02:00
|
|
|
id, _, err = cs.Zone.GetZoneID(value)
|
2015-04-11 17:50:06 +02:00
|
|
|
case "os_type":
|
|
|
|
p := cs.GuestOS.NewListOsTypesParams()
|
|
|
|
p.SetDescription(value)
|
|
|
|
l, e := cs.GuestOS.ListOsTypes(p)
|
|
|
|
if e != nil {
|
|
|
|
err = e
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if l.Count == 1 {
|
2015-10-05 14:05:21 +02:00
|
|
|
id = l.OsTypes[0].Id
|
2015-04-11 17:50:06 +02:00
|
|
|
break
|
|
|
|
}
|
2015-10-05 14:05:21 +02:00
|
|
|
err = fmt.Errorf("Could not find ID of OS Type: %s", value)
|
2014-12-10 22:20:52 +01:00
|
|
|
default:
|
2015-10-05 14:05:21 +02:00
|
|
|
return id, &retrieveError{name: name, value: value,
|
2014-12-10 22:20:52 +01:00
|
|
|
err: fmt.Errorf("Unknown request: %s", name)}
|
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
2015-10-05 14:05:21 +02:00
|
|
|
return id, &retrieveError{name: name, value: value, err: err}
|
2014-12-10 22:20:52 +01:00
|
|
|
}
|
|
|
|
|
2015-10-05 14:05:21 +02:00
|
|
|
return id, nil
|
2014-12-10 22:20:52 +01:00
|
|
|
}
|
|
|
|
|
2015-10-05 14:05:21 +02:00
|
|
|
func retrieveTemplateID(cs *cloudstack.CloudStackClient, zoneid, value string) (id string, e *retrieveError) {
|
|
|
|
// If the supplied value isn't a ID, try to retrieve the ID ourselves
|
2016-04-21 17:31:53 +02:00
|
|
|
if cloudstack.IsID(value) {
|
2015-03-09 14:02:18 +01:00
|
|
|
return value, nil
|
|
|
|
}
|
|
|
|
|
2015-10-05 14:05:21 +02:00
|
|
|
log.Printf("[DEBUG] Retrieving ID of template: %s", value)
|
2015-03-09 14:02:18 +01:00
|
|
|
|
2016-09-01 10:48:49 +02:00
|
|
|
// Ignore count, since an error is returned if there is no exact match
|
|
|
|
id, _, err := cs.Template.GetTemplateID(value, "executable", zoneid)
|
2015-03-09 14:02:18 +01:00
|
|
|
if err != nil {
|
2015-10-05 14:05:21 +02:00
|
|
|
return id, &retrieveError{name: "template", value: value, err: err}
|
2015-03-09 14:02:18 +01:00
|
|
|
}
|
|
|
|
|
2015-10-05 14:05:21 +02:00
|
|
|
return id, nil
|
2015-03-09 14:02:18 +01:00
|
|
|
}
|
|
|
|
|
2015-07-16 17:40:04 +02:00
|
|
|
// RetryFunc is the function retried n times
|
|
|
|
type RetryFunc func() (interface{}, error)
|
|
|
|
|
|
|
|
// Retry is a wrapper around a RetryFunc that will retry a function
|
|
|
|
// n times or until it succeeds.
|
|
|
|
func Retry(n int, f RetryFunc) (interface{}, error) {
|
|
|
|
var lastErr error
|
|
|
|
|
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
r, err := f()
|
2015-12-01 00:36:33 +01:00
|
|
|
if err == nil || err == cloudstack.AsyncTimeoutErr {
|
|
|
|
return r, err
|
2015-07-16 17:40:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
lastErr = err
|
|
|
|
time.Sleep(30 * time.Second)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, lastErr
|
|
|
|
}
|
2015-12-03 11:10:42 +01:00
|
|
|
|
2016-02-26 23:01:56 +01:00
|
|
|
// If there is a project supplied, we retrieve and set the project id
|
2016-04-21 17:31:53 +02:00
|
|
|
func setProjectid(p cloudstack.ProjectIDSetter, cs *cloudstack.CloudStackClient, d *schema.ResourceData) error {
|
2016-02-26 23:01:56 +01:00
|
|
|
if project, ok := d.GetOk("project"); ok {
|
|
|
|
projectid, e := retrieveID(cs, "project", project.(string))
|
|
|
|
if e != nil {
|
|
|
|
return e.Error()
|
|
|
|
}
|
|
|
|
p.SetProjectid(projectid)
|
|
|
|
}
|
2016-02-26 23:44:53 +01:00
|
|
|
|
2016-02-26 23:01:56 +01:00
|
|
|
return nil
|
|
|
|
}
|