|
|
|
|
@ -15,6 +15,7 @@ import (
|
|
|
|
|
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume"
|
|
|
|
|
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip"
|
|
|
|
|
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs"
|
|
|
|
|
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/schedulerhints"
|
|
|
|
|
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups"
|
|
|
|
|
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks"
|
|
|
|
|
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach"
|
|
|
|
|
@ -225,6 +226,48 @@ func resourceComputeInstanceV2() *schema.Resource {
|
|
|
|
|
},
|
|
|
|
|
Set: resourceComputeVolumeAttachmentHash,
|
|
|
|
|
},
|
|
|
|
|
"scheduler_hints": &schema.Schema{
|
|
|
|
|
Type: schema.TypeSet,
|
|
|
|
|
Optional: true,
|
|
|
|
|
Elem: &schema.Resource{
|
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
|
|
|
"group": &schema.Schema{
|
|
|
|
|
Type: schema.TypeString,
|
|
|
|
|
Optional: true,
|
|
|
|
|
ForceNew: true,
|
|
|
|
|
},
|
|
|
|
|
"different_host": &schema.Schema{
|
|
|
|
|
Type: schema.TypeList,
|
|
|
|
|
Optional: true,
|
|
|
|
|
ForceNew: true,
|
|
|
|
|
Elem: &schema.Schema{Type: schema.TypeString},
|
|
|
|
|
},
|
|
|
|
|
"same_host": &schema.Schema{
|
|
|
|
|
Type: schema.TypeList,
|
|
|
|
|
Optional: true,
|
|
|
|
|
ForceNew: true,
|
|
|
|
|
Elem: &schema.Schema{Type: schema.TypeString},
|
|
|
|
|
},
|
|
|
|
|
"query": &schema.Schema{
|
|
|
|
|
Type: schema.TypeList,
|
|
|
|
|
Optional: true,
|
|
|
|
|
ForceNew: true,
|
|
|
|
|
Elem: &schema.Schema{Type: schema.TypeString},
|
|
|
|
|
},
|
|
|
|
|
"target_cell": &schema.Schema{
|
|
|
|
|
Type: schema.TypeString,
|
|
|
|
|
Optional: true,
|
|
|
|
|
ForceNew: true,
|
|
|
|
|
},
|
|
|
|
|
"build_near_host_ip": &schema.Schema{
|
|
|
|
|
Type: schema.TypeString,
|
|
|
|
|
Optional: true,
|
|
|
|
|
ForceNew: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
Set: resourceComputeSchedulerHintsHash,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -290,6 +333,16 @@ func resourceComputeInstanceV2Create(d *schema.ResourceData, meta interface{}) e
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
schedulerHintsRaw := d.Get("scheduler_hints").(*schema.Set).List()
|
|
|
|
|
if len(schedulerHintsRaw) > 0 {
|
|
|
|
|
log.Printf("[DEBUG] schedulerhints: %+v", schedulerHintsRaw)
|
|
|
|
|
schedulerHints := resourceInstanceSchedulerHintsV2(d, schedulerHintsRaw[0].(map[string]interface{}))
|
|
|
|
|
createOpts = &schedulerhints.CreateOptsExt{
|
|
|
|
|
createOpts,
|
|
|
|
|
schedulerHints,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.Printf("[DEBUG] Create Options: %#v", createOpts)
|
|
|
|
|
server, err := servers.Create(computeClient, createOpts).Extract()
|
|
|
|
|
if err != nil {
|
|
|
|
|
@ -873,6 +926,40 @@ func resourceInstanceBlockDeviceV2(d *schema.ResourceData, bd map[string]interfa
|
|
|
|
|
return bfvOpts
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func resourceInstanceSchedulerHintsV2(d *schema.ResourceData, schedulerHintsRaw map[string]interface{}) schedulerhints.SchedulerHints {
|
|
|
|
|
differentHost := []string{}
|
|
|
|
|
if len(schedulerHintsRaw["different_host"].([]interface{})) > 0 {
|
|
|
|
|
for _, dh := range schedulerHintsRaw["different_host"].([]interface{}) {
|
|
|
|
|
differentHost = append(differentHost, dh.(string))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sameHost := []string{}
|
|
|
|
|
if len(schedulerHintsRaw["same_host"].([]interface{})) > 0 {
|
|
|
|
|
for _, sh := range schedulerHintsRaw["same_host"].([]interface{}) {
|
|
|
|
|
sameHost = append(sameHost, sh.(string))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
query := make([]interface{}, len(schedulerHintsRaw["query"].([]interface{})))
|
|
|
|
|
if len(schedulerHintsRaw["query"].([]interface{})) > 0 {
|
|
|
|
|
for _, q := range schedulerHintsRaw["query"].([]interface{}) {
|
|
|
|
|
query = append(query, q.(string))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
schedulerHints := schedulerhints.SchedulerHints{
|
|
|
|
|
Group: schedulerHintsRaw["group"].(string),
|
|
|
|
|
DifferentHost: differentHost,
|
|
|
|
|
SameHost: sameHost,
|
|
|
|
|
Query: query,
|
|
|
|
|
TargetCell: schedulerHintsRaw["target_cell"].(string),
|
|
|
|
|
BuildNearHostIP: schedulerHintsRaw["build_near_host_ip"].(string),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return schedulerHints
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getImageID(client *gophercloud.ServiceClient, d *schema.ResourceData) (string, error) {
|
|
|
|
|
imageId := d.Get("image_id").(string)
|
|
|
|
|
|
|
|
|
|
@ -959,6 +1046,29 @@ func resourceComputeVolumeAttachmentHash(v interface{}) int {
|
|
|
|
|
return hashcode.String(buf.String())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func resourceComputeSchedulerHintsHash(v interface{}) int {
|
|
|
|
|
var buf bytes.Buffer
|
|
|
|
|
m := v.(map[string]interface{})
|
|
|
|
|
|
|
|
|
|
if m["group"] != nil {
|
|
|
|
|
buf.WriteString(fmt.Sprintf("%s-", m["group"].(string)))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if m["target_cell"] != nil {
|
|
|
|
|
buf.WriteString(fmt.Sprintf("%s-", m["target_cell"].(string)))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if m["build_host_near_ip"] != nil {
|
|
|
|
|
buf.WriteString(fmt.Sprintf("%s-", m["build_host_near_ip"].(string)))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buf.WriteString(fmt.Sprintf("%s-", m["different_host"].([]interface{})))
|
|
|
|
|
buf.WriteString(fmt.Sprintf("%s-", m["same_host"].([]interface{})))
|
|
|
|
|
buf.WriteString(fmt.Sprintf("%s-", m["query"].([]interface{})))
|
|
|
|
|
|
|
|
|
|
return hashcode.String(buf.String())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func attachVolumesToInstance(computeClient *gophercloud.ServiceClient, blockClient *gophercloud.ServiceClient, serverId string, vols []interface{}) error {
|
|
|
|
|
if len(vols) > 0 {
|
|
|
|
|
for _, v := range vols {
|
|
|
|
|
|