package kvmvm import ( "encoding/json" "fmt" "sort" "strconv" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" log "github.com/sirupsen/logrus" "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/compute" "repository.basistech.ru/BASIS/terraform-provider-decort/internal/flattens" ) func flattenCompute(d *schema.ResourceData, computeRec *compute.RecordCompute) error { log.Debugf("flattenCompute: ID %d, RG ID %d", computeRec.ID, computeRec.RGID) customFields, _ := json.Marshal(computeRec.CustomFields) devices, _ := json.Marshal(computeRec.Devices) userData, _ := json.Marshal(computeRec.Userdata) bootDisk := findBootDisk(computeRec.Disks) if len(computeRec.Interfaces) > 0 { log.Debugf("flattenCompute: calling parseComputeInterfacesToNetworks for %d interfaces", len(computeRec.Interfaces)) if err := d.Set("network", parseComputeInterfacesToNetworks(computeRec.Interfaces)); err != nil { return err } } d.Set("account_id", computeRec.AccountID) d.Set("account_name", computeRec.AccountName) d.Set("acl", flattenListACLInterface(computeRec.ACL)) d.Set("affinity_label", computeRec.AffinityLabel) d.Set("affinity_weight", computeRec.AffinityWeight) d.Set("affinity_rules", flattenAffinityRules(computeRec.AffinityRules)) d.Set("anti_affinity_rules", flattenAffinityRules(computeRec.AntiAffinityRules)) d.Set("arch", computeRec.Arch) d.Set("boot_order", computeRec.BootOrder) d.Set("boot_disk_id", bootDisk.ID) // we intentionally use the SizeMax field, do not change it until the BootDiskSize field is fixed on the platform d.Set("boot_disk_size", bootDisk.SizeMax) d.Set("cd_image_id", computeRec.CdImageId) d.Set("clone_reference", computeRec.CloneReference) d.Set("clones", computeRec.Clones) d.Set("computeci_id", computeRec.ComputeCIID) d.Set("created_by", computeRec.CreatedBy) d.Set("created_time", computeRec.CreatedTime) d.Set("custom_fields", string(customFields)) d.Set("deleted_by", computeRec.DeletedBy) d.Set("deleted_time", computeRec.DeletedTime) d.Set("description", computeRec.Description) d.Set("devices", string(devices)) err := d.Set("disks", flattenComputeDisks(computeRec.Disks, d.Get("disks").([]interface{}), d.Get("extra_disks").(*schema.Set).List(), bootDisk.ID)) if err != nil { return err } d.Set("driver", computeRec.Driver) d.Set("gid", computeRec.GID) d.Set("guid", computeRec.GUID) d.Set("compute_id", computeRec.ID) d.Set("image_id", computeRec.ImageID) d.Set("image_name", computeRec.ImageName) d.Set("interfaces", flattenInterfaces(computeRec.Interfaces)) d.Set("lock_status", computeRec.LockStatus) d.Set("manager_id", computeRec.ManagerID) d.Set("manager_type", computeRec.ManagerType) d.Set("migrationjob", computeRec.MigrationJob) d.Set("milestones", computeRec.Milestones) d.Set("natable_vins_id", computeRec.NatableVINSID) d.Set("natable_vins_ip", computeRec.NatableVINSIP) d.Set("natable_vins_name", computeRec.NatableVINSName) d.Set("natable_vins_network", computeRec.NatableVINSNetwork) d.Set("natable_vins_network_name", computeRec.NatableVINSNetworkName) d.Set("need_reboot", computeRec.NeedReboot) d.Set("numa_node_id", computeRec.NumaNodeId) d.Set("os_users", flattenOSUsers(computeRec.OSUsers)) d.Set("pinned", computeRec.Pinned) d.Set("reference_id", computeRec.ReferenceID) d.Set("registered", computeRec.Registered) d.Set("res_name", computeRec.ResName) d.Set("reserved_node_cpus", computeRec.ReservedNodeCpus) d.Set("rg_name", computeRec.RGName) d.Set("snap_sets", flattenSnapSets(computeRec.SnapSets)) d.Set("stack_id", computeRec.StackID) d.Set("stack_name", computeRec.StackName) d.Set("stateless_sep_id", computeRec.StatelessSEPID) d.Set("stateless_sep_type", computeRec.StatelessSEPType) d.Set("status", computeRec.Status) d.Set("tags", flattenTags(computeRec.Tags)) d.Set("tech_status", computeRec.TechStatus) d.Set("updated_by", computeRec.UpdatedBy) d.Set("updated_time", computeRec.UpdatedTime) d.Set("user_data", string(userData)) d.Set("user_managed", computeRec.UserManaged) d.Set("vgpus", computeRec.VGPUs) d.Set("virtual_image_id", computeRec.VirtualImageID) d.Set("virtual_image_name", computeRec.VirtualImageName) return nil } func flattenTags(tags map[string]interface{}) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(tags)) for k, v := range tags { res = append(res, map[string]interface{}{ "key": k, "val": v, }) } return res } func flattenSnapSets(snaps compute.ListSnapshots) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(snaps)) for _, snap := range snaps { res = append(res, map[string]interface{}{ "disks": snap.Disks, "guid": snap.GUID, "label": snap.Label, "timestamp": snap.Timestamp, }) } return res } func flattenOSUsers(users compute.ListOSUsers) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(users)) for _, user := range users { res = append(res, map[string]interface{}{ "guid": user.GUID, "login": user.Login, "password": user.Password, "public_key": user.PubKey, }) } return res } func flattenInterfaces(ifaces compute.ListInterfaces) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(ifaces)) for _, iface := range ifaces { res = append(res, map[string]interface{}{ "conn_id": iface.ConnID, "conn_type": iface.ConnType, "def_gw": iface.DefGW, "enabled": iface.Enabled, "flip_group_id": iface.FLIPGroupID, "guid": iface.GUID, "ip_address": iface.IPAddress, "listen_ssh": iface.ListenSSH, "mac": iface.MAC, "name": iface.Name, "net_id": iface.NetID, "netmask": iface.NetMask, "net_type": iface.NetType, "node_id": iface.NodeID, "pci_slot": iface.PCISlot, "qos": flattenQOS(iface.QOS), "target": iface.Target, "type": iface.Type, "vnfs": iface.VNFs, }) } return res } func flattenQOS(qos compute.QOS) []map[string]interface{} { return []map[string]interface{}{ { "e_rate": qos.ERate, "guid": qos.GUID, "in_brust": qos.InBurst, "in_rate": qos.InRate, }, } } func flattenComputeDisks(disksList compute.ListDisks, disksBlocks, extraDisks []interface{}, bootDiskId uint64) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(disksList)) if len(disksBlocks) == 0 { return res } sort.Slice(disksList, func(i, j int) bool { return disksList[i].ID < disksList[j].ID }) indexDataDisks := 0 for _, disk := range disksList { if disk.ID == bootDiskId || findInExtraDisks(uint(disk.ID), extraDisks) { //skip main bootdisk and extraDisks continue } pernamentlyValue := disksBlocks[indexDataDisks].(map[string]interface{})["permanently"].(bool) nodeIds := disksBlocks[indexDataDisks].(map[string]interface{})["node_ids"].(*schema.Set) temp := map[string]interface{}{ "disk_name": disk.Name, "node_ids": nodeIds, "size": disk.SizeMax, "sep_id": disk.SEPID, "disk_type": disk.Type, "pool": disk.Pool, "desc": disk.Description, "image_id": disk.ImageID, "disk_id": disk.ID, "shareable": disk.Shareable, "size_used": disk.SizeUsed, "size_max": disk.SizeMax, "permanently": pernamentlyValue, } res = append(res, temp) indexDataDisks++ } return res } func findInExtraDisks(diskId uint, extraDisks []interface{}) bool { for _, ExtraDisk := range extraDisks { if diskId == uint(ExtraDisk.(int)) { return true } } return false } func flattenAffinityRules(rules compute.ListRules) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(rules)) for _, rule := range rules { res = append(res, map[string]interface{}{ "topology": rule.Topology, "policy": rule.Policy, "mode": rule.Mode, "key": rule.Key, "value": rule.Value, }) } return res } func flattenComputeList(computes *compute.ListComputes) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(computes.Data)) for _, computeItem := range computes.Data { customFields, _ := json.Marshal(computeItem.CustomFields) devices, _ := json.Marshal(computeItem.Devices) userData, _ := json.Marshal(computeItem.Userdata) temp := map[string]interface{}{ "acl": flattenListACLInterface(computeItem.ACL), "account_id": computeItem.AccountID, "account_name": computeItem.AccountName, "affinity_label": computeItem.AffinityLabel, "affinity_rules": flattenListRules(computeItem.AffinityRules), "affinity_weight": computeItem.AffinityWeight, "anti_affinity_rules": flattenListRules(computeItem.AntiAffinityRules), "arch": computeItem.Arch, "cd_image_id": computeItem.CdImageId, "boot_order": computeItem.BootOrder, "bootdisk_size": computeItem.BootDiskSize, "clone_reference": computeItem.CloneReference, "clones": computeItem.Clones, "computeci_id": computeItem.ComputeCIID, "cpus": computeItem.CPUs, "created_by": computeItem.CreatedBy, "created_time": computeItem.CreatedTime, "custom_fields": string(customFields), "deleted_by": computeItem.DeletedBy, "deleted_time": computeItem.DeletedTime, "desc": computeItem.Description, "devices": string(devices), "disks": flattenDisks(computeItem.Disks), "driver": computeItem.Driver, "gid": computeItem.GID, "guid": computeItem.GUID, "hp_backed": computeItem.HPBacked, "compute_id": computeItem.ID, "cpu_pin": computeItem.CPUPin, "image_id": computeItem.ImageID, "interfaces": flattenInterfaces(computeItem.Interfaces), "lock_status": computeItem.LockStatus, "manager_id": computeItem.ManagerID, "manager_type": computeItem.ManagerType, "migrationjob": computeItem.MigrationJob, "milestones": computeItem.Milestones, "name": computeItem.Name, "need_reboot": computeItem.NeedReboot, "numa_affinity": computeItem.NumaAffinity, "numa_node_id": computeItem.NumaNodeId, "os_users": flattenOSUsers(computeItem.OSUsers), "pinned": computeItem.Pinned, "ram": computeItem.RAM, "reference_id": computeItem.ReferenceID, "registered": computeItem.Registered, "res_name": computeItem.ResName, "reserved_node_cpus": computeItem.ReservedNodeCpus, "rg_id": computeItem.RGID, "rg_name": computeItem.RGName, "snap_sets": flattenSnapSets(computeItem.SnapSets), "stack_id": computeItem.StackID, "stateless_sep_id": computeItem.StatelessSEPID, "stateless_sep_type": computeItem.StatelessSEPType, "status": computeItem.Status, "tags": flattenTags(computeItem.Tags), "tech_status": computeItem.TechStatus, "total_disk_size": computeItem.TotalDiskSize, "updated_by": computeItem.UpdatedBy, "updated_time": computeItem.UpdatedTime, "user_data": string(userData), "user_managed": computeItem.UserManaged, "vgpus": computeItem.VGPUs, "vins_connected": computeItem.VINSConnected, "virtual_image_id": computeItem.VirtualImageID, } res = append(res, temp) } return res } func flattenListACLInterface(listAcl []interface{}) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(listAcl)) for _, aclInterface := range listAcl { acl := aclInterface.(map[string]interface{}) temp := map[string]interface{}{ "explicit": acl["explicit"], "guid": acl["guid"], "right": acl["right"], "status": acl["status"], "type": acl["type"], "user_group_id": acl["user_group_id"], } res = append(res, temp) } return res } func flattenListACL(listAcl compute.ListACL) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(listAcl)) for _, acl := range listAcl { temp := map[string]interface{}{ "explicit": acl.Explicit, "guid": acl.GUID, "right": acl.Right, "status": acl.Status, "type": acl.Type, "user_group_id": acl.UserGroupID, } res = append(res, temp) } return res } func flattenListComputeACL(listAcl []compute.ItemComputeACL) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(listAcl)) for _, acl := range listAcl { temp := map[string]interface{}{ "explicit": acl.Explicit, "guid": acl.GUID, "right": acl.Right, "status": acl.Status, "type": acl.Type, "user_group_id": acl.UserGroupID, } res = append(res, temp) } return res } func flattenListRules(listRules compute.ListRules) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(listRules)) for _, rule := range listRules { temp := map[string]interface{}{ "guid": rule.GUID, "key": rule.Key, "mode": rule.Mode, "policy": rule.Policy, "topology": rule.Topology, "value": rule.Value, } res = append(res, temp) } return res } func flattenDisks(disks []compute.InfoDisk) []map[string]interface{} { res := make([]map[string]interface{}, 0) for _, disk := range disks { temp := map[string]interface{}{ "disk_id": disk.ID, "pci_slot": disk.PCISlot, } res = append(res, temp) } return res } func flattenComputeAudits(computeAudits compute.ListDetailedAudits) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(computeAudits)) for _, computeAudit := range computeAudits { temp := map[string]interface{}{ "call": computeAudit.Call, "responsetime": computeAudit.ResponseTime, "statuscode": computeAudit.StatusCode, "timestamp": computeAudit.Timestamp, "user": computeAudit.User, } res = append(res, temp) } return res } func flattenComputeGetAudits(computeAudits compute.ListAudits) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(computeAudits)) for _, computeAudit := range computeAudits { temp := map[string]interface{}{ "epoch": computeAudit.Epoch, "message": computeAudit.Message, } res = append(res, temp) } return res } func flattenPfwList(computePfws *compute.ListPFW) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(computePfws.Data)) for _, computePfw := range computePfws.Data { temp := map[string]interface{}{ "pfw_id": computePfw.ID, "local_ip": computePfw.LocalIP, "local_port": computePfw.LocalPort, "protocol": computePfw.Protocol, "public_port_end": computePfw.PublicPortEnd, "public_port_start": computePfw.PublicPortStart, "vm_id": computePfw.VMID, } res = append(res, temp) } return res } func flattenUserList(d *schema.ResourceData, userList *compute.ListUsers) { d.Set("account_acl", flattenListACL(userList.Data.AccountACL)) d.Set("compute_acl", flattenListComputeACL(userList.Data.ComputeACL)) d.Set("rg_acl", flattenListACL(userList.Data.RGACL)) } func flattenSnapshotList(computeSnapshots *compute.ListSnapShot) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(computeSnapshots.Data)) for _, snp := range computeSnapshots.Data { temp := map[string]interface{}{ "disks": snp.Disks, "guid": snp.GUID, "label": snp.Label, "timestamp": snp.Timestamp, } res = append(res, temp) } return res } func flattenAffinityRelations(d *schema.ResourceData, ar *compute.RecordAffinityRelations) { d.Set("other_node", flattenNodes(ar.OtherNode)) d.Set("other_node_indirect", flattenNodes(ar.OtherNodeIndirect)) d.Set("other_node_indirect_soft", flattenNodes(ar.OtherNodeIndirectSoft)) d.Set("other_node_soft", flattenNodes(ar.OtherNodeSoft)) d.Set("same_node", flattenNodes(ar.SameNode)) d.Set("same_node_soft", flattenNodes(ar.SameNodeSoft)) } func flattenSnapshotUsage(computeSnapshotUsages compute.ListSnapshotUsage) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(computeSnapshotUsages)) for _, computeUsage := range computeSnapshotUsages { temp := map[string]interface{}{ "count": computeUsage.Count, "stored": computeUsage.Stored, "label": computeUsage.Label, "timestamp": computeUsage.Timestamp, } res = append(res, temp) } return res } func flattenPCIDevice(deviceList []compute.ItemPCIDevice) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(deviceList)) for _, dev := range deviceList { temp := map[string]interface{}{ "ckey": dev.CKey, "meta": flattens.FlattenMeta(dev.Meta), "compute_id": dev.ComputeID, "description": dev.Description, "guid": dev.GUID, "hwpath": dev.HwPath, "device_id": dev.ID, "name": dev.Name, "rg_id": dev.RGID, "stack_id": dev.StackID, "status": dev.Status, "system_name": dev.SystemName, } res = append(res, temp) } return res } func flattenVGPU(vgpuList []compute.ItemVGPU) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(vgpuList)) for _, dev := range vgpuList { temp := map[string]interface{}{ "account_id": dev.AccountID, "created_time": dev.CreatedTime, "deleted_time": dev.DeletedTime, "gid": dev.GID, "guid": dev.GUID, "vgpu_id": dev.ID, "last_claimed_by": dev.LastClaimedBy, "last_update_time": dev.LastUpdateTime, "mode": dev.Mode, "pci_slot": dev.PCISlot, "pgpuid": dev.PGPUID, "profile_id": dev.ProfileID, "ram": dev.RAM, "reference_id": dev.ReferenceID, "rg_id": dev.RGID, "status": dev.Status, "type": dev.Type, "vm_id": dev.VMID, } res = append(res, temp) } return res } func flattenNodes(m []interface{}) []string { var output []string for _, item := range m { switch d := item.(type) { case string: output = append(output, d) case int: output = append(output, strconv.Itoa(d)) case int64: output = append(output, strconv.FormatInt(d, 10)) case float64: output = append(output, strconv.FormatInt(int64(d), 10)) default: output = append(output, "") } } return output } func flattenDataCompute(d *schema.ResourceData, compFacts *compute.RecordCompute) error { // This function expects that compFacts string contains response from API compute/get, // i.e. detailed information about compute instance. // // NOTE: this function modifies ResourceData argument - as such it should never be called // from resourceComputeExists(...) method log.Debugf("flattenCompute: ID %d, RG ID %d", compFacts.ID, compFacts.RGID) customFields, _ := json.Marshal(compFacts.CustomFields) devices, _ := json.Marshal(compFacts.Devices) userData, _ := json.Marshal(compFacts.Userdata) // general fields setting d.SetId(fmt.Sprintf("%d", compFacts.ID)) d.Set("account_id", compFacts.AccountID) d.Set("account_name", compFacts.AccountName) d.Set("acl", flattenListACLInterface(compFacts.ACL)) d.Set("affinity_label", compFacts.AffinityLabel) d.Set("affinity_rules", flattenAffinityRules(compFacts.AffinityRules)) d.Set("affinity_weight", compFacts.AffinityWeight) d.Set("anti_affinity_rules", flattenAffinityRules(compFacts.AntiAffinityRules)) d.Set("arch", compFacts.Arch) d.Set("boot_order", compFacts.BootOrder) d.Set("cd_image_id", compFacts.CdImageId) d.Set("clone_reference", compFacts.CloneReference) d.Set("clones", compFacts.Clones) d.Set("computeci_id", compFacts.ComputeCIID) d.Set("cpu_pin", compFacts.CPUPin) d.Set("cpus", compFacts.CPUs) d.Set("created_by", compFacts.CreatedBy) d.Set("created_time", compFacts.CreatedTime) d.Set("custom_fields", string(customFields)) d.Set("deleted_by", compFacts.DeletedBy) d.Set("deleted_time", compFacts.DeletedTime) d.Set("desc", compFacts.Description) d.Set("devices", string(devices)) d.Set("disks", flattenDisk(compFacts.Disks)) d.Set("driver", compFacts.Driver) d.Set("gid", compFacts.GID) d.Set("guid", compFacts.GUID) d.Set("hp_backed", compFacts.HPBacked) d.Set("image_id", compFacts.ImageID) d.Set("image_name", compFacts.ImageName) d.Set("interfaces", flattenInterfaces(compFacts.Interfaces)) d.Set("lock_status", compFacts.LockStatus) d.Set("manager_id", compFacts.ManagerID) d.Set("manager_type", compFacts.ManagerType) d.Set("migrationjob", compFacts.MigrationJob) d.Set("milestones", compFacts.Milestones) d.Set("name", compFacts.Name) d.Set("natable_vins_id", compFacts.NatableVINSID) d.Set("natable_vins_ip", compFacts.NatableVINSIP) d.Set("natable_vins_name", compFacts.NatableVINSName) d.Set("natable_vins_network", compFacts.NatableVINSNetwork) d.Set("natable_vins_network_name", compFacts.NatableVINSNetworkName) d.Set("need_reboot", compFacts.NeedReboot) d.Set("numa_affinity", compFacts.NumaAffinity) d.Set("numa_node_id", compFacts.NumaNodeId) d.Set("os_users", flattenOSUsers(compFacts.OSUsers)) d.Set("pinned", compFacts.Pinned) d.Set("ram", compFacts.RAM) d.Set("reference_id", compFacts.ReferenceID) d.Set("registered", compFacts.Registered) d.Set("res_name", compFacts.ResName) d.Set("reserved_node_cpus", compFacts.ReservedNodeCpus) d.Set("rg_id", compFacts.RGID) d.Set("rg_name", compFacts.RGName) d.Set("snap_sets", flattenSnapSets(compFacts.SnapSets)) d.Set("stack_id", compFacts.StackID) d.Set("stack_name", compFacts.StackName) d.Set("stateless_sep_id", compFacts.StatelessSEPID) d.Set("stateless_sep_type", compFacts.StatelessSEPType) d.Set("status", compFacts.Status) d.Set("tags", flattenTags(compFacts.Tags)) d.Set("tech_status", compFacts.TechStatus) d.Set("updated_by", compFacts.UpdatedBy) d.Set("updated_time", compFacts.UpdatedTime) d.Set("user_data", string(userData)) d.Set("user_managed", compFacts.UserManaged) d.Set("vgpus", compFacts.VGPUs) d.Set("virtual_image_id", compFacts.VirtualImageID) d.Set("virtual_image_name", compFacts.VirtualImageName) //extra fields setting bootDisk := findBootDisk(compFacts.Disks) if bootDisk != nil { d.Set("boot_disk_size", bootDisk.SizeMax) d.Set("boot_disk_id", bootDisk.ID) // we may need boot disk ID in resize operations d.Set("sep_id", bootDisk.SEPID) d.Set("pool", bootDisk.Pool) } return nil } // Parse the list of interfaces from compute/get response into a list of networks // attached to this compute func parseComputeInterfacesToNetworks(ifaces compute.ListInterfaces) []interface{} { // return value will be used to d.Set("network") item of dataSourceCompute schema length := len(ifaces) log.Debugf("parseComputeInterfacesToNetworks: called for %d ifaces", length) result := []interface{}{} for _, value := range ifaces { elem := make(map[string]interface{}) // Keys in this map should correspond to the Schema definition for "network" elem["net_id"] = value.NetID elem["net_type"] = value.NetType elem["ip_address"] = value.IPAddress elem["mac"] = value.MAC result = append(result, elem) } return result } func flattenDisk(diskList compute.ListDisks) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(diskList)) for _, disk := range diskList { temp := map[string]interface{}{ "ckey": disk.CKey, "meta": flattens.FlattenMeta(disk.Meta), "account_id": disk.AccountID, "boot_partition": disk.BootPartition, "created_time": disk.CreatedTime, "deleted_time": disk.DeletedTime, "desc": disk.Description, "destruction_time": disk.DestructionTime, "disk_path": disk.DiskPath, "gid": disk.GID, "guid": disk.GUID, "disk_id": disk.ID, "image_id": disk.ImageID, "images": disk.Images, "iotune": flattenIOTune(disk.IOTune), "iqn": disk.IQN, "login": disk.Login, "milestones": disk.Milestones, "name": disk.Name, "order": disk.Order, "params": disk.Params, "parent_id": disk.ParentID, "passwd": disk.Password, "pci_slot": disk.PCISlot, "pool": disk.Pool, "purge_attempts": disk.PurgeAttempts, "present_to": disk.PresentTo, "purge_time": disk.PurgeTime, "replication": flattenDiskReplication(disk.Replication), "reality_device_number": disk.RealityDeviceNumber, "reference_id": disk.ReferenceID, "res_id": disk.ResID, "res_name": disk.ResName, "role": disk.Role, "sep_id": disk.SEPID, "shareable": disk.Shareable, "size_max": disk.SizeMax, "size_used": disk.SizeUsed, "snapshots": flattendDiskSnapshotList(disk.Snapshots), "status": disk.Status, "tech_status": disk.TechStatus, "type": disk.Type, "vmid": disk.VMID, } res = append(res, temp) } return res } func flattenDiskReplication(rep compute.ItemReplication) []map[string]interface{} { res := []map[string]interface{}{ { "disk_id": rep.DiskID, "pool_id": rep.PoolID, "role": rep.Role, "self_volume_id": rep.SelfVolumeID, "storage_id": rep.StorageID, "volume_id": rep.VolumeID, }, } return res } func flattenIOTune(iot compute.IOTune) []map[string]interface{} { res := make([]map[string]interface{}, 0) temp := map[string]interface{}{ "read_bytes_sec": iot.ReadBytesSec, "read_bytes_sec_max": iot.ReadBytesSecMax, "read_iops_sec": iot.ReadIOPSSec, "read_iops_sec_max": iot.ReadIOPSSecMax, "size_iops_sec": iot.SizeIOPSSec, "total_bytes_sec": iot.TotalBytesSec, "total_bytes_sec_max": iot.TotalBytesSecMax, "total_iops_sec": iot.TotalIOPSSec, "total_iops_sec_max": iot.TotalIOPSSecMax, "write_bytes_sec": iot.WriteBytesSec, "write_bytes_sec_max": iot.WriteBytesSecMax, "write_iops_sec": iot.WriteIOPSSec, "write_iops_sec_max": iot.WriteIOPSSecMax, } res = append(res, temp) return res } func flattendDiskSnapshotList(sl compute.ListDetailedSnapshots) []interface{} { res := make([]interface{}, 0) for _, snapshot := range sl { temp := map[string]interface{}{ "guid": snapshot.GUID, "label": snapshot.Label, "res_id": snapshot.ResID, "snap_set_guid": snapshot.SnapSetGUID, "snap_set_time": snapshot.SnapSetTime, "timestamp": snapshot.TimeStamp, } res = append(res, temp) } return res }