|
|
|
@ -35,12 +35,12 @@ import (
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func resourceResgroupCreate(d *schema.ResourceData, m interface{}) error {
|
|
|
|
|
log.Printf("resourceResgroupCreate: called for res group name %q, tenant name %q",
|
|
|
|
|
d.Get("name").(string), d.Get("tenant").(string))
|
|
|
|
|
log.Debugf("resourceResgroupCreate: called for res group name %q, account name %q",
|
|
|
|
|
d.Get("name").(string), d.Get("account").(string))
|
|
|
|
|
|
|
|
|
|
rg := &ResgroupConfig{
|
|
|
|
|
Name: d.Get("name").(string),
|
|
|
|
|
TenantName: d.Get("tenant").(string),
|
|
|
|
|
AccountName: d.Get("account").(string),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// validate that we have all parameters required to create the new Resource Group
|
|
|
|
@ -49,35 +49,55 @@ func resourceResgroupCreate(d *schema.ResourceData, m interface{}) error {
|
|
|
|
|
if arg_set {
|
|
|
|
|
rg.Location = arg_value.(string)
|
|
|
|
|
} else {
|
|
|
|
|
return fmt.Errorf("Cannot create new resource group %q for tenant %q: missing location parameter.",
|
|
|
|
|
rg.Name, rg.TenantName)
|
|
|
|
|
return fmt.Errorf("Cannot create new RG %q for account %q: missing location parameter.",
|
|
|
|
|
rg.Name, rg.AccountName)
|
|
|
|
|
}
|
|
|
|
|
// tenant ID is required to create new resource group
|
|
|
|
|
// obtain Tenant ID by tenant name - it should not be zero on success
|
|
|
|
|
tenant_id, err := utilityGetTenantIdByName(rg.TenantName, m)
|
|
|
|
|
// account ID is required to create new resource group
|
|
|
|
|
// obtain Account ID by account name - it should not be zero on success
|
|
|
|
|
account_id, err := utilityGetAccountIdByName(rg.AccountName, m)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
rg.TenantID = tenant_id
|
|
|
|
|
rg.AccountID = account_id
|
|
|
|
|
|
|
|
|
|
set_quotas := false
|
|
|
|
|
arg_value, arg_set = d.GetOk("quotas")
|
|
|
|
|
if arg_set {
|
|
|
|
|
log.Printf("resourceResgroupCreate: calling makeQuotaConfig")
|
|
|
|
|
log.Debugf("resourceResgroupCreate: calling makeQuotaConfig")
|
|
|
|
|
rg.Quota, _ = makeQuotaConfig(arg_value.([]interface{}))
|
|
|
|
|
set_quotas = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
controller := m.(*ControllerCfg)
|
|
|
|
|
log.Printf("resourceResgroupCreate: called by user %q for Resource group name %q, for tenant %q / ID %d, location %q",
|
|
|
|
|
log.Debugf("resourceResgroupCreate: called by user %q for RG name %q, for account %q / ID %d, location %q",
|
|
|
|
|
controller.getdecortUsername(),
|
|
|
|
|
rg.Name, d.Get("tenant"), rg.TenantID, rg.Location)
|
|
|
|
|
rg.Name, d.Get("account").(string), rg.AccountID, rg.Location)
|
|
|
|
|
/*
|
|
|
|
|
type ResgroupCreateParam struct {
|
|
|
|
|
AccountID int `json:"accountId"`
|
|
|
|
|
GridId int `json:"gid"`
|
|
|
|
|
Name string `json:"name"`
|
|
|
|
|
Ram int `json:"maxMemoryCapacity"`
|
|
|
|
|
Disk int `json:"maxVDiskCapacity"`
|
|
|
|
|
Cpu int `json:"maxCPUCapacity"`
|
|
|
|
|
NetTraffic int `json:"maxNetworkPeerTransfer"`
|
|
|
|
|
ExtIPs int `json:"maxNumPublicIP"`
|
|
|
|
|
Owner string `json:"owner"`
|
|
|
|
|
DefNet string `json:"def_net"`
|
|
|
|
|
IPCidr string `json:"ipcidr"`
|
|
|
|
|
Desc string `json:"decs"`
|
|
|
|
|
Reason string `json:"reason"`
|
|
|
|
|
ExtNetID int `json:"extNetId"`
|
|
|
|
|
ExtIP string `json:"extIp"`
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
url_values := &url.Values{}
|
|
|
|
|
url_values.Add("accountId", fmt.Sprintf("%d", rg.TenantID))
|
|
|
|
|
url_values.Add("accountId", fmt.Sprintf("%d", rg.AccountID))
|
|
|
|
|
url_values.Add("name", rg.Name)
|
|
|
|
|
url_values.Add("location", rg.Location)
|
|
|
|
|
url_values.Add("access", controller.getdecortUsername())
|
|
|
|
|
url_values.Add("gid", rg.Location)
|
|
|
|
|
url_values.Add("owner", controller.getdecortUsername())
|
|
|
|
|
url_values.Add("def_net", "NONE")
|
|
|
|
|
// pass quota values as set
|
|
|
|
|
if set_quotas {
|
|
|
|
|
url_values.Add("maxCPUCapacity", fmt.Sprintf("%d", rg.Quota.Cpu))
|
|
|
|
@ -89,7 +109,7 @@ func resourceResgroupCreate(d *schema.ResourceData, m interface{}) error {
|
|
|
|
|
// pass externalnetworkid if set
|
|
|
|
|
arg_value, arg_set = d.GetOk("extnet_id")
|
|
|
|
|
if arg_set {
|
|
|
|
|
url_values.Add("externalnetworkid", fmt.Sprintf("%d", arg_value))
|
|
|
|
|
url_values.Add("extNetId", fmt.Sprintf("%d", arg_value))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
api_resp, err := controller.decortAPICall("POST", ResgroupCreateAPI, url_values)
|
|
|
|
@ -97,15 +117,15 @@ func resourceResgroupCreate(d *schema.ResourceData, m interface{}) error {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
d.SetId(api_resp) // cloudspaces/create API plainly returns ID of the newly creted resource group on success
|
|
|
|
|
d.SetId(api_resp) // rg/create API returns ID of the newly creted resource group on success
|
|
|
|
|
rg.ID, _ = strconv.Atoi(api_resp)
|
|
|
|
|
|
|
|
|
|
return resourceResgroupRead(d, m)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func resourceResgroupRead(d *schema.ResourceData, m interface{}) error {
|
|
|
|
|
log.Printf("resourceResgroupRead: called for res group name %q, tenant name %q",
|
|
|
|
|
d.Get("name").(string), d.Get("tenant").(string))
|
|
|
|
|
log.Debugf("resourceResgroupRead: called for RG name %q, account name %q",
|
|
|
|
|
d.Get("name").(string), d.Get("account").(string))
|
|
|
|
|
rg_facts, err := utilityResgroupCheckPresence(d, m)
|
|
|
|
|
if rg_facts == "" {
|
|
|
|
|
// if empty string is returned from utilityResgroupCheckPresence then there is no
|
|
|
|
@ -119,13 +139,13 @@ func resourceResgroupRead(d *schema.ResourceData, m interface{}) error {
|
|
|
|
|
|
|
|
|
|
func resourceResgroupUpdate(d *schema.ResourceData, m interface{}) error {
|
|
|
|
|
// this method will only update quotas, if any are set
|
|
|
|
|
log.Printf("resourceResgroupUpdate: called for res group name %q, tenant name %q",
|
|
|
|
|
d.Get("name").(string), d.Get("tenant").(string))
|
|
|
|
|
log.Debugf("resourceResgroupUpdate: called for RG name %q, account name %q",
|
|
|
|
|
d.Get("name").(string), d.Get("account").(string))
|
|
|
|
|
|
|
|
|
|
quota_value, arg_set := d.GetOk("quotas")
|
|
|
|
|
if !arg_set {
|
|
|
|
|
// if there are no quotas set explicitly in the resource configuration - no change will be done
|
|
|
|
|
log.Printf("resourceResgroupUpdate: quotas are not set in the resource config - no update on this resource will be done")
|
|
|
|
|
log.Debugf("resourceResgroupUpdate: quotas are not set in the resource config - no update on this resource will be done")
|
|
|
|
|
return resourceResgroupRead(d, m)
|
|
|
|
|
}
|
|
|
|
|
quotaconfig_new, _ := makeQuotaConfig(quota_value.([]interface{}))
|
|
|
|
@ -142,66 +162,68 @@ func resourceResgroupUpdate(d *schema.ResourceData, m interface{}) error {
|
|
|
|
|
|
|
|
|
|
if quotaconfig_new.Cpu != quotaconfig_old.Cpu {
|
|
|
|
|
do_update = true
|
|
|
|
|
log.Printf("resourceResgroupUpdate: Cpu diff %d <- %d", quotaconfig_new.Cpu, quotaconfig_old.Cpu)
|
|
|
|
|
log.Debugf("resourceResgroupUpdate: Cpu diff %d <- %d", quotaconfig_new.Cpu, quotaconfig_old.Cpu)
|
|
|
|
|
url_values.Add("maxCPUCapacity", fmt.Sprintf("%d", quotaconfig_new.Cpu))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if quotaconfig_new.Disk != quotaconfig_old.Disk {
|
|
|
|
|
do_update = true
|
|
|
|
|
log.Printf("resourceResgroupUpdate: Disk diff %d <- %d", quotaconfig_new.Disk, quotaconfig_old.Disk)
|
|
|
|
|
log.Debugf("resourceResgroupUpdate: Disk diff %d <- %d", quotaconfig_new.Disk, quotaconfig_old.Disk)
|
|
|
|
|
url_values.Add("maxVDiskCapacity", fmt.Sprintf("%d", quotaconfig_new.Disk))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if quotaconfig_new.Ram != quotaconfig_old.Ram {
|
|
|
|
|
do_update = true
|
|
|
|
|
log.Printf("resourceResgroupUpdate: Ram diff %f <- %f", quotaconfig_new.Ram, quotaconfig_old.Ram)
|
|
|
|
|
log.Debugf("resourceResgroupUpdate: Ram diff %f <- %f", quotaconfig_new.Ram, quotaconfig_old.Ram)
|
|
|
|
|
url_values.Add("maxMemoryCapacity", fmt.Sprintf("%f", quotaconfig_new.Ram))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if quotaconfig_new.NetTraffic != quotaconfig_old.NetTraffic {
|
|
|
|
|
do_update = true
|
|
|
|
|
log.Printf("resourceResgroupUpdate: NetTraffic diff %d <- %d", quotaconfig_new.NetTraffic, quotaconfig_old.NetTraffic)
|
|
|
|
|
log.Debugf("resourceResgroupUpdate: NetTraffic diff %d <- %d", quotaconfig_new.NetTraffic, quotaconfig_old.NetTraffic)
|
|
|
|
|
url_values.Add("maxNetworkPeerTransfer", fmt.Sprintf("%d", quotaconfig_new.NetTraffic))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if quotaconfig_new.ExtIPs != quotaconfig_old.ExtIPs {
|
|
|
|
|
do_update = true
|
|
|
|
|
log.Printf("resourceResgroupUpdate: ExtIPs diff %d <- %d", quotaconfig_new.ExtIPs, quotaconfig_old.ExtIPs)
|
|
|
|
|
log.Debugf("resourceResgroupUpdate: ExtIPs diff %d <- %d", quotaconfig_new.ExtIPs, quotaconfig_old.ExtIPs)
|
|
|
|
|
url_values.Add("maxNumPublicIP", fmt.Sprintf("%d", quotaconfig_new.ExtIPs))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if do_update {
|
|
|
|
|
log.Printf("resourceResgroupUpdate: some new quotas are set - updating the resource")
|
|
|
|
|
log.Debugf("resourceResgroupUpdate: some new quotas are set - updating the resource")
|
|
|
|
|
_, err := controller.decortAPICall("POST", ResgroupUpdateAPI, url_values)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
log.Printf("resourceResgroupUpdate: no difference in quotas between old and new state - no update on this resource will be done")
|
|
|
|
|
log.Debugf("resourceResgroupUpdate: no difference in quotas between old and new state - no update on this resource will be done")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return resourceResgroupRead(d, m)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func resourceResgroupDelete(d *schema.ResourceData, m interface{}) error {
|
|
|
|
|
// NOTE: this method destroys target resource group with flag "permanently", so there is no way to
|
|
|
|
|
// restore the destroyed resource group as well all VMs that existed in it
|
|
|
|
|
log.Printf("resourceResgroupDelete: called for res group name %q, tenant name %q",
|
|
|
|
|
d.Get("name").(string), d.Get("tenant").(string))
|
|
|
|
|
|
|
|
|
|
vm_facts, err := utilityResgroupCheckPresence(d, m)
|
|
|
|
|
if vm_facts == "" {
|
|
|
|
|
// the target VM does not exist - in this case according to Terraform best practice
|
|
|
|
|
// NOTE: this method forcibly destroys target resource group with flag "permanently", so there is no way to
|
|
|
|
|
// restore the destroyed resource group as well all Computes & VINSes that existed in it
|
|
|
|
|
log.Debugf("resourceResgroupDelete: called for RG name %q, account name %q",
|
|
|
|
|
d.Get("name").(string), d.Get("account").(string))
|
|
|
|
|
|
|
|
|
|
rg_facts, err := utilityResgroupCheckPresence(d, m)
|
|
|
|
|
if rg_facts == "" {
|
|
|
|
|
// the target RG does not exist - in this case according to Terraform best practice
|
|
|
|
|
// we exit from Destroy method without error
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
params := &url.Values{}
|
|
|
|
|
params.Add("cloudspaceId", d.Id())
|
|
|
|
|
params.Add("rgId", d.Id())
|
|
|
|
|
params.Add("force", "true")
|
|
|
|
|
params.Add("permanently", "true")
|
|
|
|
|
params.Add("reason", "Destroyed by DECORT Terraform provider")
|
|
|
|
|
|
|
|
|
|
controller := m.(*ControllerCfg)
|
|
|
|
|
vm_facts, err = controller.decortAPICall("POST", CloudspacesDeleteAPI, params)
|
|
|
|
|
vm_facts, err = controller.decortAPICall("POST", ResgroupDeleteAPI, params)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
@ -243,13 +265,13 @@ func resourceResgroup() *schema.Resource {
|
|
|
|
|
"name": &schema.Schema {
|
|
|
|
|
Type: schema.TypeString,
|
|
|
|
|
Required: true,
|
|
|
|
|
Description: "Name of this resource group. Names are case sensitive and unique within the context of a tenant.",
|
|
|
|
|
Description: "Name of this resource group. Names are case sensitive and unique within the context of a account.",
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
"tenant": &schema.Schema {
|
|
|
|
|
"account": &schema.Schema {
|
|
|
|
|
Type: schema.TypeString,
|
|
|
|
|
Required: true,
|
|
|
|
|
Description: "Name of the tenant, which this resource group belongs to.",
|
|
|
|
|
Description: "Name of the account, which this resource group belongs to.",
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
"extnet_id": &schema.Schema {
|
|
|
|
@ -258,31 +280,18 @@ func resourceResgroup() *schema.Resource {
|
|
|
|
|
Description: "ID of the external network, which this resource group will be connected to by default.",
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
"tenant_id": &schema.Schema {
|
|
|
|
|
"account_id": &schema.Schema {
|
|
|
|
|
Type: schema.TypeInt,
|
|
|
|
|
Computed: true,
|
|
|
|
|
Description: "Unique ID of the tenant, which this resource group belongs to.",
|
|
|
|
|
Description: "Unique ID of the account, which this resource group belongs to.",
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
"grid_id": &schema.Schema {
|
|
|
|
|
Type: schema.TypeInt,
|
|
|
|
|
Computed: true,
|
|
|
|
|
Required: true,
|
|
|
|
|
Description: "Unique ID of the grid, where this resource group is deployed.",
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
"location": &schema.Schema {
|
|
|
|
|
Type: schema.TypeString,
|
|
|
|
|
Optional: true, // note that it is a REQUIRED parameter when creating new resource group
|
|
|
|
|
ForceNew: true,
|
|
|
|
|
Description: "Name of the location where this resource group should exist.",
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
"public_ip": { // this may be obsoleted as new network segments and true resource groups are implemented
|
|
|
|
|
Type: schema.TypeString,
|
|
|
|
|
Computed: true,
|
|
|
|
|
Description: "Public IP address of this resource group (if any).",
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
"quotas": {
|
|
|
|
|
Type: schema.TypeList,
|
|
|
|
|
Optional: true,
|
|
|
|
|