End of day commit, interim, no testing yet
This commit is contained in:
@@ -38,7 +38,7 @@ import (
|
|||||||
func flattenCompute(d *schema.ResourceData, comp_facts string) error {
|
func flattenCompute(d *schema.ResourceData, comp_facts string) error {
|
||||||
// NOTE: this function modifies ResourceData argument - as such it should never be called
|
// NOTE: this function modifies ResourceData argument - as such it should never be called
|
||||||
// from resourceComputeExists(...) method
|
// from resourceComputeExists(...) method
|
||||||
model := MachinesGetResp{}
|
model := ComputeGetResp{}
|
||||||
log.Printf("flattenCompute: ready to unmarshal string %q", comp_facts)
|
log.Printf("flattenCompute: ready to unmarshal string %q", comp_facts)
|
||||||
err := json.Unmarshal([]byte(comp_facts), &model)
|
err := json.Unmarshal([]byte(comp_facts), &model)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -50,11 +50,17 @@ func flattenCompute(d *schema.ResourceData, comp_facts string) error {
|
|||||||
d.SetId(fmt.Sprintf("%d", model.ID))
|
d.SetId(fmt.Sprintf("%d", model.ID))
|
||||||
d.Set("name", model.Name)
|
d.Set("name", model.Name)
|
||||||
d.Set("rgid", model.ResGroupID)
|
d.Set("rgid", model.ResGroupID)
|
||||||
|
d.Set("rg_name", model.ResGroupName)
|
||||||
|
d.Set("account_id", model.AccountID)
|
||||||
|
d.Set("account_name", model.AccountName)
|
||||||
|
d.Set("arch", model.Arch)
|
||||||
d.Set("cpu", model.Cpu)
|
d.Set("cpu", model.Cpu)
|
||||||
d.Set("ram", model.Ram)
|
d.Set("ram", model.Ram)
|
||||||
// d.Set("boot_disk", model.BootDisk)
|
d.Set("boot_disk_size", model.BootDiskSize)
|
||||||
d.Set("image_id", model.ImageID)
|
d.Set("image_id", model.ImageID)
|
||||||
d.Set("description", model.Description)
|
d.Set("description", model.Desc)
|
||||||
|
d.Set("status", model.Status)
|
||||||
|
d.Set("tech_status", model.TechStatus)
|
||||||
|
|
||||||
bootdisk_map := make(map[string]interface{})
|
bootdisk_map := make(map[string]interface{})
|
||||||
bootdisk_map["size"] = model.BootDisk
|
bootdisk_map["size"] = model.BootDisk
|
||||||
@@ -131,76 +137,86 @@ func dataSourceCompute() *schema.Resource {
|
|||||||
"name": {
|
"name": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
Description: "Name of this virtual machine. This parameter is case sensitive.",
|
Description: "Name of this compute instance. NOTE: this parameter is case sensitive.",
|
||||||
},
|
},
|
||||||
|
|
||||||
"rgid": {
|
"rgid": {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Required: true,
|
Required: true,
|
||||||
ValidateFunc: validation.IntAtLeast(1),
|
ValidateFunc: validation.IntAtLeast(1),
|
||||||
Description: "ID of the resource group where this virtual machine is located.",
|
Description: "ID of the resource group where this compute instance is located.",
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
"rg_name": {
|
||||||
"internal_ip": {
|
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
Description: "Internal IP address of this Compute.",
|
Description: "Name of the resource group where this compute instance is located.",
|
||||||
|
},
|
||||||
|
|
||||||
|
"account_id": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
Description: "ID of the account this compute instance belongs to.",
|
||||||
|
},
|
||||||
|
|
||||||
|
"account_name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Name of the account this compute instance belongs to.",
|
||||||
|
},
|
||||||
|
|
||||||
|
"arch": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Hardware architecture of this compute instance.",
|
||||||
},
|
},
|
||||||
*/
|
|
||||||
|
|
||||||
"cpu": {
|
"cpu": {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
Description: "Number of CPUs allocated for this virtual machine.",
|
Description: "Number of CPUs allocated for this compute instance.",
|
||||||
},
|
},
|
||||||
|
|
||||||
"ram": {
|
"ram": {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
Description: "Amount of RAM in MB allocated for this virtual machine.",
|
Description: "Amount of RAM in MB allocated for this compute instance.",
|
||||||
},
|
},
|
||||||
|
|
||||||
"image_id": {
|
"image_id": {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
Description: "ID of the OS image this virtual machine is based on.",
|
Description: "ID of the OS image this compute instance is based on.",
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
|
||||||
"image_name": {
|
"image_name": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
Description: "Name of the OS image this virtual machine is based on.",
|
Description: "Name of the OS image this compute instance is based on.",
|
||||||
},
|
},
|
||||||
*/
|
|
||||||
|
|
||||||
"boot_disk": {
|
"boot_disk_size": {
|
||||||
Type: schema.TypeList,
|
Type: schema.TypeInt,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
MinItems: 1,
|
Description: "This compute instance boot disk size in GB.",
|
||||||
Elem: &schema.Resource {
|
|
||||||
Schema: diskSubresourceSchema(),
|
|
||||||
},
|
|
||||||
Description: "Specification for a boot disk on this virtual machine.",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"data_disks": {
|
"disks": {
|
||||||
Type: schema.TypeList,
|
Type: schema.TypeList,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
Elem: &schema.Resource {
|
Elem: &schema.Resource {
|
||||||
Schema: diskSubresourceSchema(),
|
Schema: diskSubresourceSchema(), // ID, type, name, size, account ID, SEP ID, SEP type, pool, status, tech status, compute ID, image ID
|
||||||
},
|
},
|
||||||
Description: "Specification for data disks on this virtual machine.",
|
Description: "Detailed specification for all disks attached to this compute instance (including bood disk).",
|
||||||
},
|
},
|
||||||
|
|
||||||
"guest_logins": {
|
"guest_logins": {
|
||||||
Type: schema.TypeList,
|
Type: schema.TypeList,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
Elem: &schema.Resource {
|
Elem: &schema.Resource {
|
||||||
Schema: loginsSubresourceSchema(),
|
Schema: guestLoginsSubresourceSchema(),
|
||||||
},
|
},
|
||||||
Description: "Specification for guest logins on this virtual machine.",
|
Description: "Details about the guest OS users provisioned together with this compute instance.",
|
||||||
},
|
},
|
||||||
|
|
||||||
"networks": {
|
"networks": {
|
||||||
@@ -224,22 +240,28 @@ func dataSourceCompute() *schema.Resource {
|
|||||||
"description": {
|
"description": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
Description: "Description of this virtual machine.",
|
Description: "User-defined text description of this compute instance.",
|
||||||
},
|
},
|
||||||
|
|
||||||
"user": {
|
"status": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
Description: "Default login name for the guest OS on this virtual machine.",
|
Description: "Current model status of this compute instance.",
|
||||||
},
|
},
|
||||||
|
|
||||||
"password": {
|
"tech_status": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
Sensitive: true,
|
Description: "Current technical status of this compute instance.",
|
||||||
Description: "Default password for the guest OS login on this virtual machine.",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
"internal_ip": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Internal IP address of this Compute.",
|
||||||
|
},
|
||||||
|
*/
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,6 +54,12 @@ func flattenResgroup(d *schema.ResourceData, rg_facts string) error {
|
|||||||
d.Set("name", details.Name)
|
d.Set("name", details.Name)
|
||||||
d.Set("account_id", details.AccountID)
|
d.Set("account_id", details.AccountID)
|
||||||
d.Set("grid_id", details.GridID)
|
d.Set("grid_id", details.GridID)
|
||||||
|
d.Set("desc", details.Description)
|
||||||
|
d.Set("status", details.Status)
|
||||||
|
d.Set("def_net", details.DefaultNetType)
|
||||||
|
d.Set("def_net_id", details.DefaultNetID)
|
||||||
|
d.Set("vins", details.Vins)
|
||||||
|
d.Set("computes", details.Computes)
|
||||||
|
|
||||||
log.Debugf("flattenResgroup: calling flattenQuota()")
|
log.Debugf("flattenResgroup: calling flattenQuota()")
|
||||||
if err = d.Set("quotas", flattenQuota(details.Quotas)); err != nil {
|
if err = d.Set("quotas", flattenQuota(details.Quotas)); err != nil {
|
||||||
@@ -91,19 +97,25 @@ func dataSourceResgroup() *schema.Resource {
|
|||||||
"name": {
|
"name": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
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 an account.",
|
||||||
},
|
},
|
||||||
|
|
||||||
"account": &schema.Schema {
|
"account": &schema.Schema {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
Description: "Name of the tenant, which this resource group belongs to.",
|
Description: "Name of the account, which this resource group belongs to.",
|
||||||
},
|
},
|
||||||
|
|
||||||
"account_id": &schema.Schema {
|
"account_id": &schema.Schema {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Computed: true,
|
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.",
|
||||||
|
},
|
||||||
|
|
||||||
|
"desc": &schema.Schema {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "User-defined text description of this resource group.",
|
||||||
},
|
},
|
||||||
|
|
||||||
"grid_id": &schema.Schema {
|
"grid_id": &schema.Schema {
|
||||||
@@ -112,21 +124,52 @@ func dataSourceResgroup() *schema.Resource {
|
|||||||
Description: "Unique ID of the grid, where this resource group is deployed.",
|
Description: "Unique ID of the grid, where this resource group is deployed.",
|
||||||
},
|
},
|
||||||
|
|
||||||
"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": {
|
"quotas": {
|
||||||
Type: schema.TypeList,
|
Type: schema.TypeList,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
MaxItems: 1,
|
MaxItems: 1,
|
||||||
Elem: &schema.Resource {
|
Elem: &schema.Resource {
|
||||||
Schema: quotasSubresourceSchema(),
|
Schema: quotaRgSubresourceSchema(), // this is a dictionary
|
||||||
},
|
},
|
||||||
Description: "Quotas on the resources for this resource group.",
|
Description: "Quotas on the resources for this resource group.",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"status": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Current status of this resource group.",
|
||||||
|
},
|
||||||
|
|
||||||
|
"def_net": &schema.Schema {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Type of the default network for this resource group.",
|
||||||
|
},
|
||||||
|
|
||||||
|
"def_net_id": &schema.Schema {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
Description: "ID of the default network for this resource group (if any).",
|
||||||
|
},
|
||||||
|
|
||||||
|
"vins": {
|
||||||
|
Type: schema.TypeList, // this is a list of ints
|
||||||
|
Computed: true,
|
||||||
|
MaxItems: LimitMaxVinsPerResgroup,
|
||||||
|
Elem: &schema.Schema {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
},
|
||||||
|
Description: "List of VINs deployed in this resource group.",
|
||||||
|
},
|
||||||
|
|
||||||
|
"computes": {
|
||||||
|
Type: schema.TypeList, //t his is a list of ints
|
||||||
|
Computed: true,
|
||||||
|
Elem: &schema.Schema {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
},
|
||||||
|
Description: "List of computes deployed in this resource group."
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,12 +89,13 @@ func makeDataDisksArgString(disks []DiskConfig) string {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// ID, type, name, size, account ID, SEP ID, SEP type, pool, status, tech status, compute ID, image ID
|
||||||
func diskSubresourceSchema() map[string]*schema.Schema {
|
func diskSubresourceSchema() map[string]*schema.Schema {
|
||||||
rets := map[string]*schema.Schema {
|
rets := map[string]*schema.Schema {
|
||||||
"label": {
|
"name": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
Description: "Unique label to identify this disk among other disks connected to this VM.",
|
Description: "Name of this disk resource.",
|
||||||
},
|
},
|
||||||
|
|
||||||
"size": {
|
"size": {
|
||||||
@@ -104,6 +105,26 @@ func diskSubresourceSchema() map[string]*schema.Schema {
|
|||||||
Description: "Size of the disk in GB.",
|
Description: "Size of the disk in GB.",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"account_id": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
Description: "ID of the account this disk resource belongs to.",
|
||||||
|
},
|
||||||
|
|
||||||
|
"sep_id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Default: "default",
|
||||||
|
Description: "Storage provider (storage technology type) by which this disk should be served.",
|
||||||
|
},
|
||||||
|
|
||||||
|
"sep_type": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Default: "default",
|
||||||
|
Description: "Storage provider (storage technology type) by which this disk should be served.",
|
||||||
|
},
|
||||||
|
|
||||||
"pool": {
|
"pool": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
@@ -111,17 +132,10 @@ func diskSubresourceSchema() map[string]*schema.Schema {
|
|||||||
Description: "Pool from which this disk should be provisioned.",
|
Description: "Pool from which this disk should be provisioned.",
|
||||||
},
|
},
|
||||||
|
|
||||||
"provider": {
|
"image_id": {
|
||||||
Type: schema.TypeString,
|
|
||||||
Optional: true,
|
|
||||||
Default: "default",
|
|
||||||
Description: "Storage provider (storage technology type) by which this disk should be served.",
|
|
||||||
},
|
|
||||||
|
|
||||||
"disk_id": {
|
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
Description: "ID of this disk resource.",
|
Description: "ID of the binary Image this disk resource is cloned from (if any).",
|
||||||
},
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2019-2020 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||||
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
|
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@@ -104,7 +104,16 @@ type ResgroupUpdateParam struct {
|
|||||||
//
|
//
|
||||||
// structures related to /cloudapi/rg/get API call
|
// structures related to /cloudapi/rg/get API call
|
||||||
//
|
//
|
||||||
type ResourceRecord struct {
|
type QuotaRecord struct { // this is how quota is reported by /api/.../rg/get
|
||||||
|
Cpu int `json:"CU_C"` // CPU count in pcs
|
||||||
|
Ram int `json:"CU_M"` // RAM volume in MB
|
||||||
|
Disk int `json:"CU_D"` // Disk capacity in GB
|
||||||
|
ExtIPs int `json:"CU_I"` // Ext IPs count
|
||||||
|
ExtTraffic int `json:"CU_NP"` // Ext network traffic
|
||||||
|
GpuUnits int `json:"gpu_units"` // GPU count
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResourceRecord struct { // this is how actual usage is reported by /api/.../rg/get
|
||||||
Cpu int `json:"cpu"`
|
Cpu int `json:"cpu"`
|
||||||
Disk int `json:"disksize"`
|
Disk int `json:"disksize"`
|
||||||
ExtIPs int `json:"extips"`
|
ExtIPs int `json:"extips"`
|
||||||
@@ -135,7 +144,7 @@ type ResgroupGetResp struct {
|
|||||||
ID uint `json:"id"`
|
ID uint `json:"id"`
|
||||||
LockStatus string `json:"lockStatus"`
|
LockStatus string `json:"lockStatus"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Quotas QuotaRecord `json:"resourceLimits"`
|
Quota QuotaRecord `json:"resourceLimits"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
UpdatedBy string `json:"updatedBy"`
|
UpdatedBy string `json:"updatedBy"`
|
||||||
UpdatedTime uint64 `json:"updatedTime"`
|
UpdatedTime uint64 `json:"updatedTime"`
|
||||||
@@ -171,7 +180,7 @@ const ResgroupDeleteAPI = "/restmachine/cloudapi/rg/delete"
|
|||||||
//
|
//
|
||||||
const KvmX86CreateAPI = "/restmachine/cloudapi/kvmx86/create"
|
const KvmX86CreateAPI = "/restmachine/cloudapi/kvmx86/create"
|
||||||
const KvmPPCCreateAPI = "/restmachine/cloudapi/kvmppc/create"
|
const KvmPPCCreateAPI = "/restmachine/cloudapi/kvmppc/create"
|
||||||
type KvmXXXCreateParam struct { // this is unified structure for both x86 and PPC based VMs creation
|
type KvmVmCreateParam struct { // this is unified structure for both x86 and PPC based KVM VMs creation
|
||||||
RgID uint `json:"rgId"`
|
RgID uint `json:"rgId"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Cpu int `json:"cpu"`
|
Cpu int `json:"cpu"`
|
||||||
@@ -320,9 +329,6 @@ type OsUserRecord struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ComputeGetAPI = "/restmachine/cloudapi/compute/get"
|
const ComputeGetAPI = "/restmachine/cloudapi/compute/get"
|
||||||
type ComputeGetParam struct {
|
|
||||||
ComputeID int `json:"computeId"`
|
|
||||||
}
|
|
||||||
type ComputeGetResp struct {
|
type ComputeGetResp struct {
|
||||||
// ACLs `json:"ACL"` - it is a dictionary, special parsing required
|
// ACLs `json:"ACL"` - it is a dictionary, special parsing required
|
||||||
AccountID int `json:"accountId"`
|
AccountID int `json:"accountId"`
|
||||||
|
|||||||
@@ -29,13 +29,14 @@ import (
|
|||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeQuotaConfig(arg_list []interface{}) (ResgroupQuotaConfig, int) {
|
func makeQuotaRecord(arg_list []interface{}) (QuotaRecord, int) {
|
||||||
quota := ResgroupQuotaConfig{
|
quota := QuotaRecord{
|
||||||
Cpu: -1,
|
Cpu: -1,
|
||||||
Ram: -1,
|
Ram: -1,
|
||||||
Disk: -1,
|
Disk: -1,
|
||||||
NetTraffic: -1,
|
NetTraffic: -1,
|
||||||
ExtIPs: -1,
|
ExtIPs: -1,
|
||||||
|
GpuUnits: -1,
|
||||||
}
|
}
|
||||||
subres_data := arg_list[0].(map[string]interface{})
|
subres_data := arg_list[0].(map[string]interface{})
|
||||||
|
|
||||||
@@ -44,75 +45,86 @@ func makeQuotaConfig(arg_list []interface{}) (ResgroupQuotaConfig, int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if subres_data["disk"].(int) > 0 {
|
if subres_data["disk"].(int) > 0 {
|
||||||
quota.Disk = subres_data["disk"].(int)
|
quota.Disk = subres_data["disk"].(int) // Disk capacity ib GB
|
||||||
}
|
}
|
||||||
|
|
||||||
if subres_data["ram"].(int) > 0 {
|
if subres_data["ram"].(int) > 0 {
|
||||||
ram_limit := subres_data["ram"].(int)
|
quota.Ram= subres_data["ram"].(int) // RAM volume in MB
|
||||||
quota.Ram = float32(ram_limit) // /1024 // legacy fix - this can be obsoleted once redmine FR #1465 is implemented
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if subres_data["net_traffic"].(int) > 0 {
|
if subres_data["ext_traffic"].(int) > 0 {
|
||||||
quota.NetTraffic = subres_data["net_traffic"].(int)
|
quota.ExtTraffic = subres_data["ext_traffic"].(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
if subres_data["ext_ips"].(int) > 0 {
|
if subres_data["ext_ips"].(int) > 0 {
|
||||||
quota.ExtIPs = subres_data["ext_ips"].(int)
|
quota.ExtIPs = subres_data["ext_ips"].(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if subres_data["gpu_units"].(int) > 0 {
|
||||||
|
quota.GpuUnits = subres_data["gpu_units"].(int)
|
||||||
|
}
|
||||||
|
|
||||||
return quota, 1
|
return quota, 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func flattenQuota(quotas QuotaRecord) []interface{} {
|
func flattenQuota(quota QuotaRecord) []interface{} {
|
||||||
quotas_map := make(map[string]interface{})
|
quota_map := make(map[string]interface{})
|
||||||
|
|
||||||
quotas_map["cpu"] = quotas.Cpu
|
quota_map["cpu"] = quota.Cpu
|
||||||
quotas_map["ram"] = int(quotas.Ram)
|
quota_map["ram"] = quota.Ram
|
||||||
quotas_map["disk"] = quotas.Disk
|
quota_map["disk"] = quota.Disk
|
||||||
quotas_map["net_traffic"] = quotas.NetTraffic
|
quota_map["ext_traffic"] = quota.ExtTraffic
|
||||||
quotas_map["ext_ips"] = quotas.ExtIPs
|
quota_map["ext_ips"] = quota.ExtIPs
|
||||||
|
quota_map["gpu_units"] = quota.GpuUnits
|
||||||
|
|
||||||
result := make([]interface{}, 1)
|
result := make([]interface{}, 1)
|
||||||
result[0] = quotas_map
|
result[0] = quota_map
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func quotasSubresourceSchema() map[string]*schema.Schema {
|
func quotaRgSubresourceSchema() map[string]*schema.Schema {
|
||||||
rets := map[string]*schema.Schema {
|
rets := map[string]*schema.Schema {
|
||||||
"cpu": &schema.Schema {
|
"cpu": &schema.Schema {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: -1,
|
Default: -1,
|
||||||
Description: "The quota on the total number of CPUs in this resource group.",
|
Description: "Limit on the total number of CPUs in this resource group.",
|
||||||
},
|
},
|
||||||
|
|
||||||
"ram": &schema.Schema {
|
"ram": &schema.Schema {
|
||||||
Type: schema.TypeInt, // NB: API expects and returns this as float! This may be changed in the future.
|
Type: schema.TypeInt, // NB: old API expects and returns this as float! This may be changed in the future.
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: -1,
|
Default: -1,
|
||||||
Description: "The quota on the total amount of RAM in this resource group, specified in GB (Gigabytes!).",
|
Description: "Limit on the total amount of RAM in this resource group, specified in MB.",
|
||||||
},
|
},
|
||||||
|
|
||||||
"disk": &schema.Schema {
|
"disk": &schema.Schema {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: -1,
|
Default: -1,
|
||||||
Description: "The quota on the total volume of storage resources in this resource group, specified in GB.",
|
Description: "Limit on the total volume of storage resources in this resource group, specified in GB.",
|
||||||
},
|
},
|
||||||
|
|
||||||
"net_traffic": &schema.Schema {
|
"ext_traffic": &schema.Schema {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: -1,
|
Default: -1,
|
||||||
Description: "The quota on the total ingress network traffic for this resource group, specified in GB.",
|
Description: "Limit on the total ingress network traffic for this resource group, specified in GB.",
|
||||||
},
|
},
|
||||||
|
|
||||||
"ext_ips": &schema.Schema {
|
"ext_ips": &schema.Schema {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: -1,
|
Default: -1,
|
||||||
Description: "The quota on the total number of external IP addresses this resource group can use.",
|
Description: "Limit on the total number of external IP addresses this resource group can use.",
|
||||||
|
},
|
||||||
|
|
||||||
|
"gpu_units": &schema.Schema {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
Default: -1,
|
||||||
|
Description: "Limit on the total number of virtual GPUs this resource group can use.",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return rets
|
return rets
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2019-2020 Digital Energy Cloud Solutions. All Rights Reserved.
|
Copyright (c) 2019-2021 Digital Energy Cloud Solutions. All Rights Reserved.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -29,49 +29,54 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func resourceResgroupCreate(d *schema.ResourceData, m interface{}) error {
|
func resourceResgroupCreate(d *schema.ResourceData, m interface{}) error {
|
||||||
log.Debugf("resourceResgroupCreate: called for res group name %q, account name %q",
|
// First validate that we have all parameters required to create the new Resource Group
|
||||||
d.Get("name").(string), d.Get("account").(string))
|
arg_set := false
|
||||||
|
account_name, arg_set := d.GetOk("account")
|
||||||
rg := &ResgroupConfig{
|
if !arg_set {
|
||||||
Name: d.Get("name").(string),
|
return fmt.Errorf("Cannot create new RG: missing account.")
|
||||||
AccountName: d.Get("account").(string),
|
}
|
||||||
|
rg_name, arg_set := d.GetOk("name")
|
||||||
|
if !arg_set {
|
||||||
|
return fmt.Errorf("Cannot create new RG: missing name.")
|
||||||
|
}
|
||||||
|
grid_id, arg_set := d.GetOk("grid_id")
|
||||||
|
if !arg_set {
|
||||||
|
return fmt.Errorf("Cannot create new RG %q for account %q: missing Grid ID.",
|
||||||
|
rg_name.(string), account_name.(string))
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate that we have all parameters required to create the new Resource Group
|
// all required parameters are set in the schema - we can continue with RG creation
|
||||||
// location code is required to create new resource group
|
log.Debugf("resourceResgroupCreate: called for RG name %q, account name %q",
|
||||||
arg_value, arg_set := d.GetOk("location")
|
account_name.(string), rg_name.(string))
|
||||||
if arg_set {
|
|
||||||
rg.Location = arg_value.(string)
|
// Valid account ID is required to create new resource group
|
||||||
} else {
|
|
||||||
return fmt.Errorf("Cannot create new RG %q for account %q: missing location parameter.",
|
|
||||||
rg.Name, rg.AccountName)
|
|
||||||
}
|
|
||||||
// account ID is required to create new resource group
|
|
||||||
// obtain Account ID by account name - it should not be zero on success
|
// obtain Account ID by account name - it should not be zero on success
|
||||||
account_id, err := utilityGetAccountIdByName(rg.AccountName, m)
|
validated_account_id, err := utilityGetAccountIdByName(account_name.(string), m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rg.AccountID = account_id
|
|
||||||
|
|
||||||
set_quotas := false
|
// quota settings are optional
|
||||||
arg_value, arg_set = d.GetOk("quotas")
|
set_quota := false
|
||||||
|
var quota_record QuotaRecord
|
||||||
|
arg_value, arg_set = d.GetOk("quota")
|
||||||
if arg_set {
|
if arg_set {
|
||||||
log.Debugf("resourceResgroupCreate: calling makeQuotaConfig")
|
log.Debugf("resourceResgroupCreate: setting Quota on RG requested")
|
||||||
rg.Quota, _ = makeQuotaConfig(arg_value.([]interface{}))
|
quota_record, _ = makeQuotaRecord(arg_value.([]interface{}))
|
||||||
set_quotas = true
|
set_quota = true
|
||||||
}
|
}
|
||||||
|
|
||||||
controller := m.(*ControllerCfg)
|
controller := m.(*ControllerCfg)
|
||||||
log.Debugf("resourceResgroupCreate: called by user %q for RG name %q, for account %q / ID %d, location %q",
|
log.Debugf("resourceResgroupCreate: called by user %q for RG name %q, account %q / ID %d, Grid ID %d",
|
||||||
controller.getdecortUsername(),
|
controller.getdecortUsername(),
|
||||||
rg.Name, d.Get("account").(string), rg.AccountID, rg.Location)
|
rg_name.(string), account_name.(string), validated_account_id, gird_id.(int))
|
||||||
/*
|
/*
|
||||||
type ResgroupCreateParam struct {
|
type ResgroupCreateParam struct {
|
||||||
AccountID int `json:"accountId"`
|
AccountID int `json:"accountId"`
|
||||||
@@ -93,23 +98,40 @@ func resourceResgroupCreate(d *schema.ResourceData, m interface{}) error {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
url_values := &url.Values{}
|
url_values := &url.Values{}
|
||||||
url_values.Add("accountId", fmt.Sprintf("%d", rg.AccountID))
|
url_values.Add("accountId", fmt.Sprintf("%d", validated_account_id))
|
||||||
url_values.Add("name", rg.Name)
|
url_values.Add("name", rg_name.(string))
|
||||||
url_values.Add("gid", rg.Location)
|
url_values.Add("gid", fmt.Sprintf("%d", grid_id.(int)))
|
||||||
url_values.Add("owner", controller.getdecortUsername())
|
url_values.Add("owner", controller.getdecortUsername())
|
||||||
url_values.Add("def_net", "NONE")
|
|
||||||
// pass quota values as set
|
// pass quota values as set
|
||||||
if set_quotas {
|
if set_quota {
|
||||||
url_values.Add("maxCPUCapacity", fmt.Sprintf("%d", rg.Quota.Cpu))
|
url_values.Add("maxCPUCapacity", fmt.Sprintf("%d", quota_record.Cpu))
|
||||||
url_values.Add("maxVDiskCapacity", fmt.Sprintf("%d", rg.Quota.Disk))
|
url_values.Add("maxVDiskCapacity", fmt.Sprintf("%d", quota_record.Disk))
|
||||||
url_values.Add("maxMemoryCapacity", fmt.Sprintf("%f", rg.Quota.Ram))
|
url_values.Add("maxMemoryCapacity", fmt.Sprintf("%d", quota_record.Ram))
|
||||||
url_values.Add("maxNetworkPeerTransfer", fmt.Sprintf("%d", rg.Quota.NetTraffic))
|
url_values.Add("maxNetworkPeerTransfer", fmt.Sprintf("%d", quota_record.ExtTraffic))
|
||||||
url_values.Add("maxNumPublicIP", fmt.Sprintf("%d", rg.Quota.ExtIPs))
|
url_values.Add("maxNumPublicIP", fmt.Sprintf("%d", quota_record.ExtIPs))
|
||||||
|
// url_values.Add("???", fmt.Sprintf("%d", quota_record.GpuUnits))
|
||||||
}
|
}
|
||||||
// pass externalnetworkid if set
|
|
||||||
arg_value, arg_set = d.GetOk("extnet_id")
|
// parse and handle network settings
|
||||||
|
def_net_type, arg_set = d.GetOk("def_net_type")
|
||||||
if arg_set {
|
if arg_set {
|
||||||
url_values.Add("extNetId", fmt.Sprintf("%d", arg_value))
|
ulr_values.Add("def_net", def_net_type.(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
ipcidr, arg_set = d.GetOk("ipcidr")
|
||||||
|
if arg_set {
|
||||||
|
ulr_values.Add("ipcidr", ipcidr.(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
ext_net_id, arg_set = d.GetOk("ext_net_id")
|
||||||
|
if arg_set {
|
||||||
|
ulr_values.Add("extNetId", ext_net_id.(int))
|
||||||
|
}
|
||||||
|
|
||||||
|
ext_ip, arg_set = d.GetOk("ext_ip")
|
||||||
|
if arg_set {
|
||||||
|
ulr_values.Add("extIp", ext_ip.(string))
|
||||||
}
|
}
|
||||||
|
|
||||||
api_resp, err := controller.decortAPICall("POST", ResgroupCreateAPI, url_values)
|
api_resp, err := controller.decortAPICall("POST", ResgroupCreateAPI, url_values)
|
||||||
@@ -120,6 +142,7 @@ func resourceResgroupCreate(d *schema.ResourceData, m interface{}) error {
|
|||||||
d.SetId(api_resp) // rg/create API 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)
|
rg.ID, _ = strconv.Atoi(api_resp)
|
||||||
|
|
||||||
|
// re-read newly created RG to make sure schema contains complete and up to date set of specifications
|
||||||
return resourceResgroupRead(d, m)
|
return resourceResgroupRead(d, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,66 +161,81 @@ func resourceResgroupRead(d *schema.ResourceData, m interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func resourceResgroupUpdate(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.Debugf("resourceResgroupUpdate: called for RG name %q, account name %q",
|
log.Debugf("resourceResgroupUpdate: called for RG name %q, account name %q",
|
||||||
d.Get("name").(string), d.Get("account").(string))
|
d.Get("name").(string), d.Get("account").(string))
|
||||||
|
|
||||||
quota_value, arg_set := d.GetOk("quotas")
|
do_update := false
|
||||||
if !arg_set {
|
|
||||||
// if there are no quotas set explicitly in the resource configuration - no change 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{}))
|
|
||||||
|
|
||||||
quota_value, _ = d.GetChange("quotas") // returns old as 1st, new as 2nd argument
|
|
||||||
quotaconfig_old, _ := makeQuotaConfig(quota_value.([]interface{}))
|
|
||||||
|
|
||||||
controller := m.(*ControllerCfg)
|
controller := m.(*ControllerCfg)
|
||||||
url_values := &url.Values{}
|
url_values := &url.Values{}
|
||||||
url_values.Add("cloudspaceId", d.Id())
|
url_values.Add("rgId", d.Id())
|
||||||
url_values.Add("name", d.Get("name").(string))
|
|
||||||
|
name_new, name_set := d.GetOk("name")
|
||||||
|
if name_set {
|
||||||
|
log.Debugf("resourceResgroupUpdate: name specified - looking for deltas from the old settings.")
|
||||||
|
name_old, _ := d.GetChange("name")
|
||||||
|
if name_old.(string) != name_new.(string) {
|
||||||
|
do_update := true
|
||||||
|
url_values.Add("name", name_new.(string))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
do_update := false
|
quota_value, quota_set := d.GetOk("quota")
|
||||||
|
if quota_set {
|
||||||
|
log.Debugf("resourceResgroupUpdate: quota specified - looking for deltas from the old quota.")
|
||||||
|
quotarecord_new, _ := makeQuotaRecord(quota_value.([]interface{}))
|
||||||
|
quota_value_old, _ = d.GetChange("quota") // returns old as 1st, new as 2nd return value
|
||||||
|
quotarecord_old, _ := makeQuotaRecord(quota_value_old.([]interface{}))
|
||||||
|
|
||||||
if quotaconfig_new.Cpu != quotaconfig_old.Cpu {
|
if quotarecord_new.Cpu != quotarecord_old.Cpu {
|
||||||
do_update = true
|
do_update = true
|
||||||
log.Debugf("resourceResgroupUpdate: Cpu diff %d <- %d", quotaconfig_new.Cpu, quotaconfig_old.Cpu)
|
log.Debugf("resourceResgroupUpdate: Cpu diff %d <- %d", quotarecord_new.Cpu, quotarecord_old.Cpu)
|
||||||
url_values.Add("maxCPUCapacity", fmt.Sprintf("%d", quotaconfig_new.Cpu))
|
url_values.Add("maxCPUCapacity", fmt.Sprintf("%d", quotarecord_new.Cpu))
|
||||||
|
}
|
||||||
|
|
||||||
|
if quotarecord_new.Disk != quotarecord_old.Disk {
|
||||||
|
do_update = true
|
||||||
|
log.Debugf("resourceResgroupUpdate: Disk diff %d <- %d", quotarecord_new.Disk, quotarecord_old.Disk)
|
||||||
|
url_values.Add("maxVDiskCapacity", fmt.Sprintf("%d", quotarecord_new.Disk))
|
||||||
|
}
|
||||||
|
|
||||||
|
if quotarecord_new.Ram != quotarecord_old.Ram {
|
||||||
|
do_update = true
|
||||||
|
log.Debugf("resourceResgroupUpdate: Ram diff %f <- %f", quotarecord_new.Ram, quotarecord_old.Ram)
|
||||||
|
url_values.Add("maxMemoryCapacity", fmt.Sprintf("%f", quotarecord_new.Ram))
|
||||||
|
}
|
||||||
|
|
||||||
|
if quotarecord_new.ExtTraffic != quotarecord_old.ExtTraffic {
|
||||||
|
do_update = true
|
||||||
|
log.Debugf("resourceResgroupUpdate: NetTraffic diff %d <- %d", quotarecord_new.ExtTraffic, quotarecord_old.ExtTraffic)
|
||||||
|
url_values.Add("maxNetworkPeerTransfer", fmt.Sprintf("%d", quotarecord_new.NetTraffic))
|
||||||
|
}
|
||||||
|
|
||||||
|
if quotarecord_new.ExtIPs != quotarecord_old.ExtIPs {
|
||||||
|
do_update = true
|
||||||
|
log.Debugf("resourceResgroupUpdate: ExtIPs diff %d <- %d", quotarecord_new.ExtIPs, quotarecord_old.ExtIPs)
|
||||||
|
url_values.Add("maxNumPublicIP", fmt.Sprintf("%d", quotarecord_new.ExtIPs))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if quotaconfig_new.Disk != quotaconfig_old.Disk {
|
desc_new, desc_set := d.GetOk("desc")
|
||||||
do_update = true
|
if desc_set {
|
||||||
log.Debugf("resourceResgroupUpdate: Disk diff %d <- %d", quotaconfig_new.Disk, quotaconfig_old.Disk)
|
log.Debugf("resourceResgroupUpdate: description specified - looking for deltas from the old settings.")
|
||||||
url_values.Add("maxVDiskCapacity", fmt.Sprintf("%d", quotaconfig_new.Disk))
|
desc_old, _ := d.GetChange("desc")
|
||||||
}
|
if desc_old.(string) != desc_new.(string) {
|
||||||
|
do_update := true
|
||||||
if quotaconfig_new.Ram != quotaconfig_old.Ram {
|
url_values.Add("desc", desc_new.(string))
|
||||||
do_update = true
|
}
|
||||||
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.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.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 {
|
if do_update {
|
||||||
log.Debugf("resourceResgroupUpdate: some new quotas are set - updating the resource")
|
log.Debugf("resourceResgroupUpdate: detected delta between new and old RG specs - updating the RG")
|
||||||
_, err := controller.decortAPICall("POST", ResgroupUpdateAPI, url_values)
|
_, err := controller.decortAPICall("POST", ResgroupUpdateAPI, url_values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Debugf("resourceResgroupUpdate: no difference in quotas between old and new state - no update on this resource will be done")
|
log.Debugf("resourceResgroupUpdate: no difference between old and new state - no update on the RG will be done")
|
||||||
}
|
}
|
||||||
|
|
||||||
return resourceResgroupRead(d, m)
|
return resourceResgroupRead(d, m)
|
||||||
@@ -216,14 +254,14 @@ func resourceResgroupDelete(d *schema.ResourceData, m interface{}) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
params := &url.Values{}
|
url_values := &url.Values{}
|
||||||
params.Add("rgId", d.Id())
|
url_values.Add("rgId", d.Id())
|
||||||
params.Add("force", "true")
|
url_values.Add("force", "true")
|
||||||
params.Add("permanently", "true")
|
url_values.Add("permanently", "true")
|
||||||
params.Add("reason", "Destroyed by DECORT Terraform provider")
|
url_values.Add("reason", "Destroyed by DECORT Terraform provider")
|
||||||
|
|
||||||
controller := m.(*ControllerCfg)
|
controller := m.(*ControllerCfg)
|
||||||
vm_facts, err = controller.decortAPICall("POST", ResgroupDeleteAPI, params)
|
_, err = controller.decortAPICall("POST", ResgroupDeleteAPI, url_values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -232,7 +270,7 @@ func resourceResgroupDelete(d *schema.ResourceData, m interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func resourceResgroupExists(d *schema.ResourceData, m interface{}) (bool, error) {
|
func resourceResgroupExists(d *schema.ResourceData, m interface{}) (bool, error) {
|
||||||
// Reminder: according to Terraform rules, this function should not modify ResourceData argument
|
// Reminder: according to Terraform rules, this function should NOT modify ResourceData argument
|
||||||
rg_facts, err := utilityResgroupCheckPresence(d, m)
|
rg_facts, err := utilityResgroupCheckPresence(d, m)
|
||||||
if rg_facts == "" {
|
if rg_facts == "" {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -274,10 +312,30 @@ func resourceResgroup() *schema.Resource {
|
|||||||
Description: "Name of the account, which this resource group belongs to.",
|
Description: "Name of the account, which this resource group belongs to.",
|
||||||
},
|
},
|
||||||
|
|
||||||
"extnet_id": &schema.Schema {
|
"def_net": &schema.Schema {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Default: "PRIVATE"
|
||||||
|
Description: "Type of the network, which this resource group will use as default for its computes - PRIVATE or PUBLIC or NONE.",
|
||||||
|
},
|
||||||
|
|
||||||
|
"ipcidr": &schema.Schema {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Description: "Address of the netowrk inside the private network segment (aka ViNS) if def_net=PRIVATE",
|
||||||
|
},
|
||||||
|
|
||||||
|
"ext_net_id": &schema.Schema {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Description: "ID of the external network, which this resource group will be connected to by default.",
|
Default: 0,
|
||||||
|
Description: "ID of the external network, which this resource group will use as default for its computes if def_net=PUBLIC",
|
||||||
|
},
|
||||||
|
|
||||||
|
"ext_ip": &schema.Schema {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Description: "IP address on the external netowrk to request, if def_net=PUBLIC",
|
||||||
},
|
},
|
||||||
|
|
||||||
"account_id": &schema.Schema {
|
"account_id": &schema.Schema {
|
||||||
@@ -292,14 +350,51 @@ func resourceResgroup() *schema.Resource {
|
|||||||
Description: "Unique ID of the grid, where this resource group is deployed.",
|
Description: "Unique ID of the grid, where this resource group is deployed.",
|
||||||
},
|
},
|
||||||
|
|
||||||
"quotas": {
|
"quota": {
|
||||||
Type: schema.TypeList,
|
Type: schema.TypeList,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
MaxItems: 1,
|
MaxItems: 1,
|
||||||
Elem: &schema.Resource {
|
Elem: &schema.Resource {
|
||||||
Schema: quotasSubresourceSchema(),
|
Schema: quotasSubresourceSchema(),
|
||||||
},
|
},
|
||||||
Description: "Quotas on the resources for this resource group.",
|
Description: "Quota settings for this resource group.",
|
||||||
|
},
|
||||||
|
|
||||||
|
"desc": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Description: "User-defined text description of this resource group."
|
||||||
|
},
|
||||||
|
|
||||||
|
"status": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Current status of this resource group.",
|
||||||
|
},
|
||||||
|
|
||||||
|
"def_net_id": &schema.Schema {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
Description: "ID of the default network for this resource group (if any).",
|
||||||
|
},
|
||||||
|
|
||||||
|
"vins": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Computed: true,
|
||||||
|
MaxItems: LimitMaxVinsPerResgroup,
|
||||||
|
Elem: &schema.Resource {
|
||||||
|
Schema: vinsRgSubresourceSchema() // this is a list of ints
|
||||||
|
},
|
||||||
|
Description: "List of VINs deployed in this resource group.",
|
||||||
|
},
|
||||||
|
|
||||||
|
"computes": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Computed: true,
|
||||||
|
Elem: &schema.Resource {
|
||||||
|
Schema: computesRgSubresourceSchema() //this is a list of ints
|
||||||
|
},
|
||||||
|
Description: "List of computes deployed in this resource group."
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ func (ctrl *ControllerCfg) utilityResgroupConfigGet(rgid int) (*ResgroupGetResp,
|
|||||||
return model, nil
|
return model, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On success this function returns a string, as returned by API rg/get, which could be unmarshalled
|
||||||
|
// into ResgroupGetResp structure
|
||||||
func utilityResgroupCheckPresence(d *schema.ResourceData, m interface{}) (string, error) {
|
func utilityResgroupCheckPresence(d *schema.ResourceData, m interface{}) (string, error) {
|
||||||
// This function tries to locate resource group by its name and account name.
|
// This function tries to locate resource group by its name and account name.
|
||||||
// If succeeded, it returns non empty string that contains JSON formatted facts about the
|
// If succeeded, it returns non empty string that contains JSON formatted facts about the
|
||||||
@@ -79,7 +81,7 @@ func utilityResgroupCheckPresence(d *schema.ResourceData, m interface{}) (string
|
|||||||
// .../rg/list API with includedeleted=false
|
// .../rg/list API with includedeleted=false
|
||||||
//
|
//
|
||||||
// This function does not modify its ResourceData argument, so it is safe to use it as core
|
// This function does not modify its ResourceData argument, so it is safe to use it as core
|
||||||
// method for the resource's Exists method.
|
// method for the Terraform resource Exists method.
|
||||||
//
|
//
|
||||||
name := d.Get("name").(string)
|
name := d.Get("name").(string)
|
||||||
account_name := d.Get("account").(string)
|
account_name := d.Get("account").(string)
|
||||||
@@ -94,7 +96,7 @@ func utilityResgroupCheckPresence(d *schema.ResourceData, m interface{}) (string
|
|||||||
|
|
||||||
log.Debugf("%s", body_string)
|
log.Debugf("%s", body_string)
|
||||||
log.Debugf("utilityResgroupCheckPresence: ready to decode response body from %q", ResgroupListAPI)
|
log.Debugf("utilityResgroupCheckPresence: ready to decode response body from %q", ResgroupListAPI)
|
||||||
model := CloudspacesListResp{}
|
model := ResgroupListResp{}
|
||||||
err = json.Unmarshal([]byte(body_string), &model)
|
err = json.Unmarshal([]byte(body_string), &model)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -148,5 +150,5 @@ func utilityGetAccountIdByName(account_name string, m interface{}) (int, error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0, fmt.Errorf("Cannot find account %q for the current user. Check account value and your access rights", account_name)
|
return 0, fmt.Errorf("Cannot find account %q for the current user. Check account name and your access rights", account_name)
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user