/* Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved. Authors: Petr Krutov, Stanislav Solovev, Kasim Baybikov, Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud Orchestration Technology) with Terraform by Hashicorp. Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort Please see README.md to learn where to place source code so that it builds seamlessly. Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki */ package kvmvm import ( "encoding/json" "sort" "strconv" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" log "github.com/sirupsen/logrus" "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/compute" "repository.basistech.ru/BASIS/terraform-provider-decort/internal/status" ) 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 flattenQOS(qos compute.QOS) []map[string]interface{} { res := make([]map[string]interface{}, 0) temp := map[string]interface{}{ "e_rate": qos.ERate, "guid": qos.GUID, "in_brust": qos.InBurst, "in_rate": qos.InRate, } res = append(res, temp) return res } func flattenInterfaces(interfaces compute.ListInterfaces) []map[string]interface{} { res := make([]map[string]interface{}, 0) for _, interfaceItem := range interfaces { temp := map[string]interface{}{ "conn_id": interfaceItem.ConnID, "conn_type": interfaceItem.ConnType, "def_gw": interfaceItem.DefGW, "flip_group_id": interfaceItem.FLIPGroupID, "guid": interfaceItem.GUID, "ip_address": interfaceItem.IPAddress, "listen_ssh": interfaceItem.ListenSSH, "mac": interfaceItem.MAC, "name": interfaceItem.Name, "net_id": interfaceItem.NetID, "netmask": interfaceItem.NetMask, "net_type": interfaceItem.NetType, "pci_slot": interfaceItem.PCISlot, "qos": flattenQOS(interfaceItem.QOS), "target": interfaceItem.Target, "type": interfaceItem.Type, "vnfs": interfaceItem.VNFs, } res = append(res, temp) } return res } func flattenSnapSets(snapSets compute.ListSnapSets) []map[string]interface{} { res := make([]map[string]interface{}, 0) for _, snapSet := range snapSets { temp := map[string]interface{}{ "disks": snapSet.Disks, "guid": snapSet.GUID, "label": snapSet.Label, "timestamp": snapSet.Timestamp, } res = append(res, temp) } return res } func flattenTags(tags map[string]string) []map[string]interface{} { res := make([]map[string]interface{}, 0) for key, val := range tags { temp := map[string]interface{}{ "key": key, "val": val, } res = append(res, temp) } return res } func flattenListRules(listRules compute.ListRules) []map[string]interface{} { res := make([]map[string]interface{}, 0) 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 flattenListACL(listAcl compute.ListACL) []map[string]interface{} { res := make([]map[string]interface{}, 0) 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 flattenComputeList(computes *compute.ListComputes) []map[string]interface{} { res := make([]map[string]interface{}, 0) for _, compute := range computes.Data { customFields, _ := json.Marshal(compute.CustomFields) devices, _ := json.Marshal(compute.Devices) temp := map[string]interface{}{ "acl": flattenListACL(compute.ACL), "account_id": compute.AccountID, "account_name": compute.AccountName, "affinity_label": compute.AffinityLabel, "affinity_rules": flattenListRules(compute.AffinityRules), "affinity_weight": compute.AffinityWeight, "anti_affinity_rules": flattenListRules(compute.AntiAffinityRules), "arch": compute.Architecture, "boot_order": compute.BootOrder, "bootdisk_size": compute.BootDiskSize, "clone_reference": compute.CloneReference, "clones": compute.Clones, "computeci_id": compute.ComputeCIID, "cpus": compute.CPU, "created_by": compute.CreatedBy, "created_time": compute.CreatedTime, "custom_fields": string(customFields), "deleted_by": compute.DeletedBy, "deleted_time": compute.DeletedTime, "desc": compute.Description, "devices": string(devices), "disks": flattenDisks(compute.Disks), "driver": compute.Driver, "gid": compute.GID, "guid": compute.GUID, "compute_id": compute.ID, "image_id": compute.ImageID, "interfaces": flattenInterfaces(compute.Interfaces), "lock_status": compute.LockStatus, "manager_id": compute.ManagerID, "manager_type": compute.ManagerType, "migrationjob": compute.MigrationJob, "milestones": compute.Milestones, "name": compute.Name, "pinned": compute.Pinned, "ram": compute.RAM, "reference_id": compute.ReferenceID, "registered": compute.Registered, "res_name": compute.ResName, "rg_id": compute.RGID, "rg_name": compute.RGName, "snap_sets": flattenSnapSets(compute.SnapSets), "stateless_sep_id": compute.StatelessSepID, "stateless_sep_type": compute.StatelessSepType, "status": compute.Status, "tags": flattenTags(compute.Tags), "tech_status": compute.TechStatus, "total_disk_size": compute.TotalDiskSize, "updated_by": compute.UpdatedBy, "updated_time": compute.UpdatedTime, "user_managed": compute.UserManaged, "vgpus": compute.VGPUs, "vins_connected": compute.VINSConnected, "virtual_image_id": compute.VirtualImageID, } res = append(res, temp) } return res } func flattenBootDisk(bootDisk *compute.ItemComputeDisk) []map[string]interface{} { res := make([]map[string]interface{}, 0) temp := map[string]interface{}{ "disk_name": bootDisk.Name, "disk_id": bootDisk.ID, "disk_type": bootDisk.Type, "sep_id": bootDisk.SepID, "shareable": bootDisk.Shareable, "size_max": bootDisk.SizeMax, "size_used": bootDisk.SizeUsed, "pool": bootDisk.Pool, "desc": bootDisk.Description, "image_id": bootDisk.ImageID, "size": bootDisk.SizeMax, } res = append(res, temp) return res } func flattenComputeDisksDemo(disksList compute.ListComputeDisks, extraDisks []interface{}, bootDiskId uint64) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(disksList)) for _, disk := range disksList { if disk.ID == bootDiskId || findInExtraDisks(uint(disk.ID), extraDisks) { //skip main bootdisk and extraDisks continue } temp := map[string]interface{}{ "disk_name": disk.Name, "disk_id": disk.ID, "disk_type": disk.Type, "sep_id": disk.SepID, "shareable": disk.Shareable, "size_max": disk.SizeMax, "size_used": disk.SizeUsed, "pool": disk.Pool, "desc": disk.Description, "image_id": disk.ImageID, "size": disk.SizeMax, } res = append(res, temp) } sort.Slice(res, func(i, j int) bool { return res[i]["disk_id"].(uint64) < res[j]["disk_id"].(uint64) }) return res } func flattenNetwork(interfaces compute.ListInterfaces) []map[string]interface{} { res := make([]map[string]interface{}, 0, len(interfaces)) for _, network := range interfaces { temp := map[string]interface{}{ "net_id": network.NetID, "net_type": network.NetType, "ip_address": network.IPAddress, "mac": network.MAC, } res = append(res, temp) } return res } func findBootDisk(disks compute.ListComputeDisks) *compute.ItemComputeDisk { for _, disk := range disks { if disk.Type == "B" { return &disk } } return nil } func flattenCompute(d *schema.ResourceData, computeRec 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", computeRec.ID, computeRec.RGID) devices, _ := json.Marshal(computeRec.Devices) bootDisk := findBootDisk(computeRec.Disks) //check extraDisks, ipa_type, is, d.SetId(strconv.FormatUint(computeRec.ID, 10)) // d.Set("acl", flattenACL(computeRec.ACL)) d.Set("account_id", computeRec.AccountID) d.Set("account_name", computeRec.AccountName) d.Set("affinity_weight", computeRec.AffinityWeight) d.Set("arch", computeRec.Architecture) d.Set("boot_order", computeRec.BootOrder) d.Set("boot_disk_size", bootDisk.SizeMax) d.Set("boot_disk", flattenBootDisk(bootDisk)) d.Set("boot_disk_id", bootDisk.ID) d.Set("sep_id", bootDisk.SepID) d.Set("pool", bootDisk.Pool) 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", flattenCustomFields(computeRec.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", flattenComputeDisksDemo(computeRec.Disks, d.Get("extra_disks").(*schema.Set).List(), bootDisk.ID)) if err != nil { return err } d.Set("driver", computeRec.Driver) d.Set("cpu", computeRec.CPU) d.Set("gid", computeRec.GID) d.Set("guid", computeRec.GUID) d.Set("compute_id", computeRec.ID) if computeRec.VirtualImageID != 0 { d.Set("image_id", computeRec.VirtualImageID) } else { d.Set("image_id", computeRec.ImageID) } 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("name", computeRec.Name) 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) if err := d.Set("os_users", parseOsUsers(computeRec.OSUsers)); err != nil { return err } d.Set("pinned", computeRec.Pinned) d.Set("ram", computeRec.RAM) d.Set("reference_id", computeRec.ReferenceID) d.Set("registered", computeRec.Registered) d.Set("res_name", computeRec.ResName) d.Set("rg_id", computeRec.RGID) d.Set("rg_name", computeRec.RGName) d.Set("snap_sets", flattenSnapSets(computeRec.SnapSets)) 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_managed", computeRec.UserManaged) d.Set("vgpus", computeRec.VGPUs) d.Set("virtual_image_id", computeRec.VirtualImageID) d.Set("virtual_image_name", computeRec.VirtualImageName) d.Set("enabled", false) if computeRec.Status == status.Enabled { d.Set("enabled", true) } d.Set("started", false) if computeRec.TechStatus == "STARTED" { d.Set("started", true) } d.Set("network", flattenNetwork(computeRec.Interfaces)) return nil } func flattenACL(acl compute.RecordACL) []map[string]interface{} { res := make([]map[string]interface{}, 0) temp := map[string]interface{}{ "account_acl": flattenListACL(acl.AccountACL), "compute_acl": flattenListACL(acl.ComputeACL), "rg_acl": flattenListACL(acl.RGACL), } res = append(res, temp) return res } func flattenAffinityRules(affinityRules compute.ListRules) []map[string]interface{} { res := make([]map[string]interface{}, 0) for _, affinityRule := range affinityRules { temp := map[string]interface{}{ "guid": affinityRule.GUID, "key": affinityRule.Key, "mode": affinityRule.Mode, "policy": affinityRule.Policy, "topology": affinityRule.Topology, "value": affinityRule.Value, } res = append(res, temp) } return res } func flattenIotune(iotune compute.IOTune) []map[string]interface{} { res := make([]map[string]interface{}, 0) temp := map[string]interface{}{ "read_bytes_sec": iotune.ReadBytesSec, "read_bytes_sec_max": iotune.ReadBytesSecMax, "read_iops_sec": iotune.ReadIOPSSec, "read_iops_sec_max": iotune.ReadIOPSSecMax, "size_iops_sec": iotune.SizeIOPSSec, "total_bytes_sec": iotune.TotalBytesSec, "total_bytes_sec_max": iotune.TotalBytesSecMax, "total_iops_sec": iotune.TotalIOPSSec, "total_iops_sec_max": iotune.TotalIOPSSecMax, "write_bytes_sec": iotune.WriteBytesSec, "write_bytes_sec_max": iotune.WriteBytesSecMax, "write_iops_sec": iotune.WriteIOPSSec, "write_iops_sec_max": iotune.WriteIOPSSecMax, } res = append(res, temp) return res } func flattenSnapshots(snapshots compute.SnapshotExtendList) []map[string]interface{} { res := make([]map[string]interface{}, 0) for _, snapshot := range snapshots { temp := map[string]interface{}{ "guid": snapshot.GUID, "label": snapshot.Label, "res_id": snapshot.ResID, "reference_id": snapshot.ReferenceID, "snap_set_guid": snapshot.SnapSetGUID, "snap_set_time": snapshot.SnapSetTime, "timestamp": snapshot.TimeStamp, } res = append(res, temp) } return res } func flattenListComputeDisks(disks compute.ListComputeDisks) []map[string]interface{} { res := make([]map[string]interface{}, 0) for _, disk := range disks { acl, _ := json.Marshal(disk.ACL) temp := map[string]interface{}{ "_ckey": disk.CKey, "acl": string(acl), "account_id": disk.AccountID, "boot_partition": disk.BootPartition, "created_time": disk.CreatedTime, "deleted_time": disk.DeletedTime, "description": 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.Passwd, "pci_slot": disk.PCISlot, "pool": disk.Pool, "present_to": disk.PresentTo, "purge_time": disk.PurgeTime, "reality_device_number": disk.RealityDeviceNumber, "res_id": disk.ResID, "role": disk.Role, "sep_id": disk.SepID, "shareable": disk.Shareable, "size_max": disk.SizeMax, "size_used": disk.SizeUsed, "snapshots": flattenSnapshots(disk.Snapshots), "status": disk.Status, "tech_status": disk.TechStatus, "type": disk.Type, "vmid": disk.VMID, } res = append(res, temp) } return res } func flattenCustomFields(customFields map[string]interface{}) string { encoded, _ := json.Marshal(customFields) return string(encoded) } func flattenOsUsers(osUsers compute.ListOSUser) []map[string]interface{} { res := make([]map[string]interface{}, 0) for _, user := range osUsers { temp := map[string]interface{}{ "guid": user.GUID, "login": user.Login, "password": user.Password, "public_key": user.PubKey, } res = append(res, temp) } return res } func flattenDataCompute(d *schema.ResourceData, computeRec compute.RecordCompute) { devices, _ := json.Marshal(computeRec.Devices) userdata, _ := json.Marshal(computeRec.Userdata) d.Set("acl", flattenACL(computeRec.ACL)) d.Set("account_id", computeRec.AccountID) d.Set("account_name", computeRec.AccountName) d.Set("affinity_label", computeRec.AffinityLabel) d.Set("affinity_rules", flattenAffinityRules(computeRec.AffinityRules)) d.Set("affinity_weight", computeRec.AffinityWeight) d.Set("anti_affinity_rules", flattenListRules(computeRec.AntiAffinityRules)) d.Set("arch", computeRec.Architecture) d.Set("boot_order", computeRec.BootOrder) d.Set("bootdisk_size", computeRec.BootDiskSize) d.Set("clone_reference", computeRec.CloneReference) d.Set("clones", computeRec.Clones) d.Set("computeci_id", computeRec.ComputeCIID) d.Set("cpus", computeRec.CPU) d.Set("created_by", computeRec.CreatedBy) d.Set("created_time", computeRec.CreatedTime) d.Set("custom_fields", flattenCustomFields(computeRec.CustomFields)) d.Set("deleted_by", computeRec.DeletedBy) d.Set("deleted_time", computeRec.DeletedTime) d.Set("desc", computeRec.Description) d.Set("devices", string(devices)) d.Set("disks", flattenListComputeDisks(computeRec.Disks)) 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("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("name", computeRec.Name) 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("os_users", flattenOsUsers(computeRec.OSUsers)) d.Set("pinned", computeRec.Pinned) d.Set("ram", computeRec.RAM) d.Set("reference_id", computeRec.ReferenceID) d.Set("registered", computeRec.Registered) d.Set("res_name", computeRec.ResName) d.Set("rg_id", computeRec.RGID) d.Set("rg_name", computeRec.RGName) d.Set("snap_sets", flattenSnapSets(computeRec.SnapSets)) d.Set("stateless_sep_id", computeRec.StatelessSepID) d.Set("stateless_sep_type", computeRec.StatelessSepType) d.Set("status", computeRec.Status) d.Set("tags", computeRec.Tags) d.Set("tech_status", computeRec.TechStatus) d.Set("updated_by", computeRec.UpdatedBy) d.Set("updated_time", computeRec.UpdatedTime) d.Set("user_managed", computeRec.UserManaged) d.Set("userdata", string(userdata)) d.Set("vgpus", computeRec.VGPUs) d.Set("virtual_image_id", computeRec.VirtualImageID) d.Set("virtual_image_name", computeRec.VirtualImageName) } func flattenComputeAudits(computeAudits compute.ListAudits) []map[string]interface{} { res := make([]map[string]interface{}, 0) 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 flattenPfwList(computePfws *compute.ListPFWs) []map[string]interface{} { res := make([]map[string]interface{}, 0) 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", flattenListACL(userList.Data.ComputeACL)) d.Set("rg_acl", flattenListACL(userList.Data.RGACL)) } func flattenComputeGetAudits(computeAudits compute.ListShortAudits) []map[string]interface{} { res := make([]map[string]interface{}, 0) for _, computeAudit := range computeAudits { temp := map[string]interface{}{ "epoch": computeAudit.Epoch, "message": computeAudit.Message, } res = append(res, temp) } return res } func flattenSnapshotUsage(computeSnapshotUsages compute.ListUsageSnapshots) []map[string]interface{} { res := make([]map[string]interface{}, 0) 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 }