1.1.0
This commit is contained in:
@@ -26,3 +26,21 @@ func ComputeCheckPresence(ctx context.Context, state *models.RecordComputeModel,
|
||||
tflog.Info(ctx, "Getting compute info, successfully")
|
||||
return computeRecord, nil
|
||||
}
|
||||
|
||||
func ComputePCIDevicesListCheckPresence(ctx context.Context, state *models.RecordComputeModel, c *decort.DecortClient) (*compute.ListPCIDevices, error) {
|
||||
tflog.Info(ctx, "Get PCI devices info")
|
||||
|
||||
req := compute.ListPCIDeviceRequest{
|
||||
ComputeID: uint64(state.ComputeId.ValueInt64()),
|
||||
}
|
||||
|
||||
tflog.Info(ctx, "Check req", map[string]any{"req": req})
|
||||
|
||||
pciDevicesList, err := c.CloudAPI().Compute().ListPCIDevice(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tflog.Info(ctx, "Getting PCI devices info, successfully")
|
||||
return pciDevicesList, nil
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package utilities
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -11,7 +12,6 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
|
||||
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/compute"
|
||||
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/kvmppc"
|
||||
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/kvmx86"
|
||||
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/kvmvm/models"
|
||||
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/status"
|
||||
@@ -81,42 +81,50 @@ func CreateResourceCompute(ctx context.Context, plan *models.ResourceComputeMode
|
||||
diags := diag.Diagnostics{}
|
||||
|
||||
createReqX86 := kvmx86.CreateRequest{Start: false}
|
||||
createReqPPC := kvmppc.CreateRequest{Start: false}
|
||||
|
||||
if !plan.Description.IsUnknown() {
|
||||
createReqPPC.Description = plan.Description.ValueString()
|
||||
createReqX86.Description = plan.Description.ValueString()
|
||||
}
|
||||
|
||||
if !plan.SepId.IsUnknown() {
|
||||
createReqPPC.SEPID = uint64(plan.SepId.ValueInt64())
|
||||
createReqX86.SepID = uint64(plan.SepId.ValueInt64())
|
||||
}
|
||||
|
||||
if !plan.Pool.IsUnknown() {
|
||||
createReqPPC.Pool = plan.Pool.ValueString()
|
||||
createReqX86.Pool = plan.Pool.ValueString()
|
||||
}
|
||||
|
||||
if !plan.IpaType.IsNull() {
|
||||
createReqPPC.IPAType = plan.IpaType.ValueString()
|
||||
createReqX86.IPAType = plan.IpaType.ValueString()
|
||||
}
|
||||
|
||||
if !plan.BootDiskSize.IsNull() {
|
||||
createReqPPC.BootDisk = uint64(plan.BootDiskSize.ValueInt64())
|
||||
createReqX86.BootDisk = uint64(plan.BootDiskSize.ValueInt64())
|
||||
}
|
||||
|
||||
if !plan.IS.IsNull() {
|
||||
createReqPPC.IS = plan.IS.ValueString()
|
||||
createReqX86.IS = plan.IS.ValueString()
|
||||
}
|
||||
|
||||
if !plan.Chipset.IsUnknown() {
|
||||
createReqX86.Chipset = plan.Chipset.ValueString()
|
||||
}
|
||||
|
||||
createReqX86.Interfaces = make([]kvmx86.Interface, 0)
|
||||
|
||||
if !plan.Network.IsNull() {
|
||||
networkList := plan.Network.Elements()
|
||||
sort.Slice(networkList, func(i, j int) bool {
|
||||
weightI := networkList[i].(types.Object).Attributes()["weight"].(types.Int64).ValueInt64()
|
||||
weightJ := networkList[j].(types.Object).Attributes()["weight"].(types.Int64).ValueInt64()
|
||||
if weightI == 0 {
|
||||
return false
|
||||
}
|
||||
if weightJ == 0 {
|
||||
return true
|
||||
}
|
||||
return weightI < weightJ
|
||||
})
|
||||
interfaces := make([]kvmx86.Interface, 0)
|
||||
for _, elem := range networkList {
|
||||
objVal := elem.(types.Object)
|
||||
@@ -125,108 +133,72 @@ func CreateResourceCompute(ctx context.Context, plan *models.ResourceComputeMode
|
||||
NetType: strings.ToUpper(elemMap["net_type"].(types.String).ValueString()),
|
||||
NetID: uint64(elemMap["net_id"].(types.Int64).ValueInt64()),
|
||||
}
|
||||
if reqInterface.NetType == "DPDK" {
|
||||
reqInterface.MTU = uint64(elemMap["mtu"].(types.Int64).ValueInt64())
|
||||
}
|
||||
ipaddr, ipSet := elemMap["ip_address"]
|
||||
if ipSet {
|
||||
reqInterface.IPAddr = ipaddr.(types.String).ValueString()
|
||||
}
|
||||
|
||||
interfaces = append(interfaces, reqInterface)
|
||||
}
|
||||
|
||||
createReqX86.Interfaces = interfaces
|
||||
}
|
||||
|
||||
createReqPPC.Interfaces = make([]kvmppc.Interface, 0)
|
||||
|
||||
if !plan.Network.IsNull() {
|
||||
networkList := plan.Network.Elements()
|
||||
interfaces := make([]kvmppc.Interface, 0)
|
||||
for _, elem := range networkList {
|
||||
objVal := elem.(types.Object)
|
||||
elemMap := objVal.Attributes()
|
||||
reqInterface := kvmppc.Interface{
|
||||
NetType: strings.ToUpper(elemMap["net_type"].(types.String).ValueString()),
|
||||
NetID: uint64(elemMap["net_id"].(types.Int64).ValueInt64()),
|
||||
}
|
||||
ipaddr, ipSet := elemMap["ip_address"]
|
||||
if ipSet {
|
||||
reqInterface.IPAddr = ipaddr.(types.String).ValueString()
|
||||
}
|
||||
|
||||
interfaces = append(interfaces, reqInterface)
|
||||
}
|
||||
|
||||
createReqPPC.Interfaces = interfaces
|
||||
}
|
||||
|
||||
if !plan.CloudInit.IsNull() {
|
||||
userData := plan.CloudInit.ValueString()
|
||||
if userData != "" && userData != "applied" {
|
||||
createReqPPC.Userdata = strings.TrimSpace(userData)
|
||||
createReqX86.Userdata = strings.TrimSpace(userData)
|
||||
}
|
||||
}
|
||||
|
||||
driver := strings.ToUpper(plan.Driver.ValueString())
|
||||
if driver == "KVM_PPC" {
|
||||
createReqPPC.RGID = uint64(plan.RGID.ValueInt64())
|
||||
createReqPPC.Name = plan.Name.ValueString()
|
||||
createReqPPC.CPU = uint64(plan.CPU.ValueInt64())
|
||||
createReqPPC.RAM = uint64(plan.RAM.ValueInt64())
|
||||
createReqPPC.ImageID = uint64(plan.ImageID.ValueInt64())
|
||||
|
||||
tflog.Info(ctx, fmt.Sprintf("CreateResourceCompute: creating Compute of type KVM VM PowerPC"))
|
||||
id, err := c.CloudAPI().KVMPPC().Create(ctx, createReqPPC)
|
||||
if err != nil {
|
||||
diags.AddError("CreateResourceCompute: unable to create KVM VP PowerPC", err.Error())
|
||||
return 0, diags
|
||||
}
|
||||
return id, diags
|
||||
} else {
|
||||
createReqX86.RGID = uint64(plan.RGID.ValueInt64())
|
||||
createReqX86.Name = plan.Name.ValueString()
|
||||
createReqX86.CPU = uint64(plan.CPU.ValueInt64())
|
||||
createReqX86.RAM = uint64(plan.RAM.ValueInt64())
|
||||
createReqX86.Driver = driver
|
||||
createReqX86.RGID = uint64(plan.RGID.ValueInt64())
|
||||
createReqX86.Name = plan.Name.ValueString()
|
||||
createReqX86.CPU = uint64(plan.CPU.ValueInt64())
|
||||
createReqX86.RAM = uint64(plan.RAM.ValueInt64())
|
||||
createReqX86.Driver = driver
|
||||
|
||||
if !plan.ImageID.IsNull() {
|
||||
createReqX86.ImageID = uint64(plan.ImageID.ValueInt64())
|
||||
}
|
||||
|
||||
if !plan.WithoutBootDisk.IsNull() {
|
||||
createReqX86.WithoutBootDisk = plan.WithoutBootDisk.ValueBool()
|
||||
}
|
||||
|
||||
if !plan.CustomFields.IsUnknown() { //CustomFields optional && computed
|
||||
val := plan.CustomFields.ValueString()
|
||||
val = strings.ReplaceAll(val, "\\", "")
|
||||
val = strings.ReplaceAll(val, "\n", "")
|
||||
val = strings.ReplaceAll(val, "\t", "")
|
||||
val = strings.TrimSpace(val)
|
||||
|
||||
createReqX86.CustomFields = val
|
||||
}
|
||||
|
||||
if !plan.NumaAffinity.IsNull() {
|
||||
createReqX86.NumaAffinity = strings.ToLower(plan.NumaAffinity.ValueString())
|
||||
}
|
||||
|
||||
if !plan.CPUPin.IsNull() && plan.CPUPin.ValueBool() {
|
||||
createReqX86.CPUPin = true
|
||||
}
|
||||
|
||||
if !plan.HPBacked.IsNull() && plan.HPBacked.ValueBool() {
|
||||
createReqX86.HPBacked = true
|
||||
}
|
||||
|
||||
tflog.Info(ctx, fmt.Sprintf("CreateResourceCompute: creating Compute of type KVM VM x86"))
|
||||
id, err := c.CloudAPI().KVMX86().Create(ctx, createReqX86)
|
||||
if err != nil {
|
||||
diags.AddError("CreateResourceCompute: unable to create KVM VP x86", err.Error())
|
||||
return 0, diags
|
||||
}
|
||||
return id, diags
|
||||
if !plan.ImageID.IsNull() {
|
||||
createReqX86.ImageID = uint64(plan.ImageID.ValueInt64())
|
||||
}
|
||||
|
||||
if !plan.WithoutBootDisk.IsNull() {
|
||||
createReqX86.WithoutBootDisk = plan.WithoutBootDisk.ValueBool()
|
||||
}
|
||||
|
||||
if !plan.CustomFields.IsUnknown() { //CustomFields optional && computed
|
||||
val := plan.CustomFields.ValueString()
|
||||
val = strings.ReplaceAll(val, "\\", "")
|
||||
val = strings.ReplaceAll(val, "\n", "")
|
||||
val = strings.ReplaceAll(val, "\t", "")
|
||||
val = strings.TrimSpace(val)
|
||||
|
||||
createReqX86.CustomFields = val
|
||||
}
|
||||
|
||||
if !plan.NumaAffinity.IsNull() {
|
||||
createReqX86.NumaAffinity = strings.ToLower(plan.NumaAffinity.ValueString())
|
||||
}
|
||||
|
||||
if !plan.CPUPin.IsNull() && plan.CPUPin.ValueBool() {
|
||||
createReqX86.CPUPin = true
|
||||
}
|
||||
|
||||
if !plan.HPBacked.IsNull() && plan.HPBacked.ValueBool() {
|
||||
createReqX86.HPBacked = true
|
||||
}
|
||||
|
||||
tflog.Info(ctx, fmt.Sprintf("CreateResourceCompute: creating Compute of type KVM VM x86"))
|
||||
id, err := c.CloudAPI().KVMX86().Create(ctx, createReqX86)
|
||||
if err != nil {
|
||||
diags.AddError("CreateResourceCompute: unable to create KVM VP x86", err.Error())
|
||||
return 0, diags
|
||||
}
|
||||
return id, diags
|
||||
|
||||
}
|
||||
|
||||
func CleanupResourceCompute(ctx context.Context, computeId uint64, c *decort.DecortClient) {
|
||||
@@ -281,16 +253,11 @@ func ComputeResourceEnableDisable(ctx context.Context, plan *models.ResourceComp
|
||||
return diags
|
||||
}
|
||||
|
||||
var enable bool
|
||||
if plan.Enabled.IsNull() {
|
||||
enable = true // default value
|
||||
} else {
|
||||
enable = plan.Enabled.ValueBool()
|
||||
}
|
||||
enable := plan.Enabled.ValueBool()
|
||||
|
||||
tflog.Info(ctx, "ComputeEnableDisable: compute to be enabled/disabled", map[string]any{
|
||||
"compute_id": computeId,
|
||||
"enable": enable})
|
||||
"enable": plan.Enabled.ValueBool()})
|
||||
|
||||
if enable {
|
||||
_, err = c.CloudAPI().Compute().Enable(ctx, compute.EnableRequest{ComputeID: computeId})
|
||||
@@ -326,12 +293,7 @@ func ComputeResourceStartStop(ctx context.Context, plan *models.ResourceComputeM
|
||||
return diags
|
||||
}
|
||||
|
||||
var started bool
|
||||
if plan.Started.IsNull() {
|
||||
started = true // default value
|
||||
} else {
|
||||
started = plan.Started.ValueBool()
|
||||
}
|
||||
started := plan.Started.ValueBool()
|
||||
|
||||
tflog.Info(ctx, "ComputeStartStop: compute to be started/stopped", map[string]any{
|
||||
"compute_id": computeId,
|
||||
@@ -642,6 +604,41 @@ func ComputeResourceSnapshot(ctx context.Context, plan *models.ResourceComputeMo
|
||||
return nil
|
||||
}
|
||||
|
||||
func ComputeResourcePCIDevice(ctx context.Context, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
|
||||
tflog.Info(ctx, "ComputeResourcePCIDevice: Start added PCI devices(s) to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
|
||||
diags := diag.Diagnostics{}
|
||||
|
||||
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
|
||||
if err != nil {
|
||||
diags.AddError("ComputeResourcePCIDevice: cannot parsed ID compute from plan", err.Error())
|
||||
return diags
|
||||
}
|
||||
|
||||
pciDeviceList := plan.PCIDevices.Elements()
|
||||
for _, pciDevice := range pciDeviceList {
|
||||
pciDeviceId := pciDevice.(types.Int64).ValueInt64()
|
||||
req := compute.AttachPCIDeviceRequest{
|
||||
ComputeID: computeId,
|
||||
DeviceID: uint64(pciDeviceId),
|
||||
}
|
||||
tflog.Info(ctx, "ComputeResourcePCIDevice: Start attach PCI device to compute with ID", map[string]any{"compute_id": plan.ID.ValueString(), "pci_device_id": pciDeviceId})
|
||||
res, err := c.CloudAPI().Compute().AttachPCIDevice(ctx, req)
|
||||
tflog.Info(ctx, "ComputeResourceSnapshot: response from CloudAPI().Compute().AttachPCIDevice", map[string]any{"compute_id": computeId, "response": res})
|
||||
if err != nil {
|
||||
diags.AddWarning(
|
||||
"ComputeResourceSnapshot: Unable to add PCI device for Compute",
|
||||
err.Error(),
|
||||
)
|
||||
}
|
||||
}
|
||||
if diags.WarningsCount() != 0 {
|
||||
return diags
|
||||
}
|
||||
|
||||
tflog.Info(ctx, "ComputeResourcePCIDevice: PCI devices(s) is successfully added", map[string]any{"compute_id": computeId})
|
||||
return nil
|
||||
}
|
||||
|
||||
func ComputeResourceCDInsert(ctx context.Context, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
|
||||
tflog.Info(ctx, "ComputeResourceCDInsert: Start added cd to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
|
||||
diags := diag.Diagnostics{}
|
||||
@@ -745,7 +742,7 @@ func ComputeReadStatus(ctx context.Context, state *models.ResourceComputeModel,
|
||||
"compute_id": computeId,
|
||||
"status": recordCompute.Status})
|
||||
// restore and enable compute in case it is required
|
||||
if state.Restore.IsNull() || state.Restore.ValueBool() { // default true or user set-up true
|
||||
if state.Restore.ValueBool() { // default true or user set-up true
|
||||
diags.Append(RestoreCompute(ctx, computeId, c)...)
|
||||
if diags.HasError() {
|
||||
tflog.Error(ctx, "ComputeReadStatus: cannot restore compute")
|
||||
@@ -759,14 +756,14 @@ func ComputeReadStatus(ctx context.Context, state *models.ResourceComputeModel,
|
||||
return diags
|
||||
}
|
||||
}
|
||||
if state.Enabled.IsNull() || state.Enabled.ValueBool() { // default true or user set-up true
|
||||
if state.Enabled.ValueBool() { // default true or user set-up true
|
||||
diags.Append(ComputeResourceEnableDisable(ctx, state, c)...)
|
||||
if diags.HasError() {
|
||||
tflog.Error(ctx, "ComputeReadStatus: Unable to enable compute")
|
||||
return diags
|
||||
}
|
||||
tflog.Info(ctx, "ComputeReadStatus: compute enabled successfully", map[string]any{"compute_id": computeId})
|
||||
if state.Started.IsNull() || state.Started.ValueBool() {
|
||||
if state.Started.ValueBool() {
|
||||
diags.Append(ComputeResourceStartStop(ctx, state, c)...)
|
||||
if diags.HasError() {
|
||||
tflog.Error(ctx, "ComputeReadStatus: Unable to start compute")
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package utilities
|
||||
|
||||
import "github.com/hashicorp/terraform-plugin-framework/types"
|
||||
import (
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
)
|
||||
|
||||
// differenceSimpleType returns lists added and removed values
|
||||
func differenceSimpleType(oldSet, newSet types.Set) (added, removed []any) {
|
||||
@@ -30,36 +33,52 @@ func differenceSimpleType(oldSet, newSet types.Set) (added, removed []any) {
|
||||
return
|
||||
}
|
||||
|
||||
func differenceNetwork(oldSet, newSet types.Set) (added, removed []any) {
|
||||
func differenceNetwork(oldSet, newSet types.Set) (added, changeIp, removed []map[string]attr.Value) {
|
||||
oldSlice := oldSet.Elements()
|
||||
newSlice := newSet.Elements()
|
||||
foundIdx := make([]bool, len(oldSlice))
|
||||
|
||||
for _, newElem := range newSlice {
|
||||
newObj := newElem.(types.Object)
|
||||
newElemMap := newObj.Attributes()
|
||||
added = make([]map[string]attr.Value, 0)
|
||||
changeIp = make([]map[string]attr.Value, 0)
|
||||
removed = make([]map[string]attr.Value, 0)
|
||||
|
||||
for _, oldNetwork := range oldSlice {
|
||||
oldMap := oldNetwork.(types.Object).Attributes()
|
||||
found := false
|
||||
for i, oldElem := range oldSlice {
|
||||
oldObj := oldElem.(types.Object)
|
||||
oldElemMap := oldObj.Attributes()
|
||||
if oldElemMap["net_type"] == newElemMap["net_type"] && oldElemMap["net_id"] == newElemMap["net_id"] {
|
||||
ipaddr, ipSet := newElemMap["ip_address"]
|
||||
if !ipSet || ipaddr.(types.String).ValueString() == "" || ipaddr == oldElemMap["ip_address"] {
|
||||
for _, newNetwork := range newSlice {
|
||||
newMap := newNetwork.(types.Object).Attributes()
|
||||
if newMap["net_type"] == oldMap["net_type"] && newMap["net_id"] == oldMap["net_id"] && newMap["weight"] == oldMap["weight"] && (newMap["mtu"] == oldMap["mtu"] || newMap["mtu"].(types.Int64).ValueInt64() == 0) {
|
||||
if (newMap["net_type"].(types.String).ValueString() == "EXTNET" || newMap["net_type"].(types.String).ValueString() == "VINS") && (newMap["ip_address"] != oldMap["ip_address"] && newMap["ip_address"].(types.String).ValueString() != "") {
|
||||
changeIp = append(changeIp, newMap)
|
||||
found = true
|
||||
break
|
||||
} else if newMap["ip_address"] == oldMap["ip_address"] || newMap["ip_address"].(types.String).ValueString() != "" {
|
||||
found = true
|
||||
foundIdx[i] = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
added = append(added, newElem)
|
||||
if found {
|
||||
continue
|
||||
}
|
||||
removed = append(removed, oldMap)
|
||||
}
|
||||
|
||||
for i, found := range foundIdx {
|
||||
if !found {
|
||||
removed = append(removed, oldSlice[i])
|
||||
for _, newNetwork := range newSlice {
|
||||
newMap := newNetwork.(types.Object).Attributes()
|
||||
found := false
|
||||
for _, oldNetwork := range oldSlice {
|
||||
oldMap := oldNetwork.(types.Object).Attributes()
|
||||
if newMap["net_type"] == oldMap["net_type"] && newMap["net_id"] == oldMap["net_id"] && newMap["weight"] == oldMap["weight"] && (newMap["mtu"] == oldMap["mtu"] || newMap["mtu"].(types.Int64).ValueInt64() == 0) {
|
||||
if newMap["ip_address"] == oldMap["ip_address"] || newMap["ip_address"].(types.String).ValueString() != "" || ((newMap["net_type"].(types.String).ValueString() == "EXTNET" || newMap["net_type"].(types.String).ValueString() == "VINS") && newMap["ip_address"] != oldMap["ip_address"]) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if found {
|
||||
continue
|
||||
}
|
||||
added = append(added, newMap)
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
@@ -3,6 +3,7 @@ package utilities
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -169,7 +170,7 @@ func ComputeResourceExtraDiskUpdate(ctx context.Context, state *models.ResourceC
|
||||
}
|
||||
}
|
||||
|
||||
if len(detachSet) > 0 && (plan.Started.ValueBool() || plan.Started.IsNull()) {
|
||||
if len(detachSet) > 0 && plan.Started.ValueBool() {
|
||||
diags = ComputeResourceStartStop(ctx, plan, c)
|
||||
}
|
||||
|
||||
@@ -182,6 +183,55 @@ func ComputeResourceExtraDiskUpdate(ctx context.Context, state *models.ResourceC
|
||||
return nil
|
||||
}
|
||||
|
||||
func ComputeResourcePCIDeviceUpdate(ctx context.Context, state *models.ResourceComputeModel, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
|
||||
tflog.Info(ctx, "ComputeResourcePCIDeviceUpdate: start update PCI device(s) list to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
|
||||
diags := diag.Diagnostics{}
|
||||
|
||||
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
|
||||
if err != nil {
|
||||
diags.AddError("ComputeResourcePCIDeviceUpdate: cannot parsed ID compute from state", err.Error())
|
||||
return diags
|
||||
}
|
||||
|
||||
attachSet, detachSet := differenceSimpleType(state.ExtraDisks, plan.ExtraDisks)
|
||||
|
||||
for _, pciDevice := range detachSet {
|
||||
pciDeviceId := pciDevice.(types.Int64).ValueInt64()
|
||||
tflog.Info(ctx, fmt.Sprintf("ComputeResourcePCIDeviceUpdate: Start detach PCI device with ID - %d from compute with ID - %d", pciDeviceId, computeId))
|
||||
req := compute.DetachPCIDeviceRequest{
|
||||
ComputeID: computeId,
|
||||
DeviceID: uint64(pciDeviceId),
|
||||
}
|
||||
res, err := c.CloudAPI().Compute().DetachPCIDevice(ctx, req)
|
||||
tflog.Info(ctx, "ComputeResourcePCIDeviceUpdate: response from CloudAPI().Compute().DetachPCIDevice", map[string]any{"compute_id": plan.ID.ValueString(), "response": res})
|
||||
if err != nil {
|
||||
diags.AddError(fmt.Sprintf("ComputeResourcePCIDeviceUpdate: Cannot detach PCI device with ID - %d", pciDeviceId), err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
for _, pciDevice := range attachSet {
|
||||
pciDeviceId := pciDevice.(types.Int64).ValueInt64()
|
||||
tflog.Info(ctx, fmt.Sprintf("ComputeResourcePCIDeviceUpdate: Start attach PCI device with ID - %d to compute with ID - %d", pciDeviceId, computeId))
|
||||
req := compute.AttachPCIDeviceRequest{
|
||||
ComputeID: computeId,
|
||||
DeviceID: uint64(pciDeviceId),
|
||||
}
|
||||
res, err := c.CloudAPI().Compute().AttachPCIDevice(ctx, req)
|
||||
tflog.Info(ctx, "ComputeResourcePCIDeviceUpdate: response from CloudAPI().Compute().AttachPCIDevice", map[string]any{"compute_id": plan.ID.ValueString(), "response": res})
|
||||
if err != nil {
|
||||
diags.AddError(fmt.Sprintf("ComputeResourcePCIDeviceUpdate: Cannot attach PCI device with ID - %d", pciDeviceId), err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if diags.HasError() {
|
||||
tflog.Error(ctx, "ComputeResourcePCIDeviceUpdate: Errors occurred while managing PCI device(s)")
|
||||
return diags
|
||||
}
|
||||
|
||||
tflog.Info(ctx, "ComputeResourcePCIDeviceUpdate: PCI device(s) is successfully update", map[string]any{"compute_id": computeId})
|
||||
return nil
|
||||
}
|
||||
|
||||
func ComputeResourceNetworkUpdate(ctx context.Context, state *models.ResourceComputeModel, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
|
||||
tflog.Info(ctx, "ComputeResourceNetworkUpdate: start update network rules to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
|
||||
diags := diag.Diagnostics{}
|
||||
@@ -192,22 +242,43 @@ func ComputeResourceNetworkUpdate(ctx context.Context, state *models.ResourceCom
|
||||
return diags
|
||||
}
|
||||
|
||||
attachSet, detachSet := differenceNetwork(state.Network, plan.Network)
|
||||
attachMap, changeIpMap, detachMap := differenceNetwork(state.Network, plan.Network)
|
||||
|
||||
for _, network := range detachSet {
|
||||
objVal := network.(types.Object)
|
||||
elemMap := objVal.Attributes()
|
||||
tflog.Info(ctx, "ComputeResourceNetworkUpdate: start detach network(s) rules to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
|
||||
for _, network := range detachMap {
|
||||
req := compute.NetDetachRequest{
|
||||
ComputeID: computeId,
|
||||
IPAddr: elemMap["ip_address"].(types.String).ValueString(),
|
||||
MAC: elemMap["mac"].(types.String).ValueString(),
|
||||
IPAddr: network["ip_address"].(types.String).ValueString(),
|
||||
MAC: network["mac"].(types.String).ValueString(),
|
||||
}
|
||||
tflog.Info(ctx, "ComputeResourceNetworkUpdate: before calling CloudAPI().Compute().NetDetach", map[string]any{"compute_id": computeId, "req": req})
|
||||
res, err := c.CloudAPI().Compute().NetDetach(ctx, req)
|
||||
tflog.Info(ctx, "ComputeResourceNetworkUpdate: response from CloudAPI().Compute().NetDetach", map[string]any{"compute_id": plan.ID.ValueString(), "response": res})
|
||||
if err != nil {
|
||||
diags.AddError(fmt.Sprintf("ComputeResourceNetworkUpdate: failed to detach net ID %d from Compute ID %d",
|
||||
elemMap["net_id"].(types.Int64).ValueInt64(), computeId), err.Error())
|
||||
network["net_id"].(types.Int64).ValueInt64(), computeId), err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
|
||||
tflog.Info(ctx, "ComputeResourceNetworkUpdate: start change IP network(s) rules to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
|
||||
|
||||
for _, network := range changeIpMap {
|
||||
req := compute.ChangeIPRequest{
|
||||
ComputeID: computeId,
|
||||
NetType: network["net_type"].(types.String).ValueString(),
|
||||
NetID: uint64(network["net_id"].(types.Int64).ValueInt64()),
|
||||
IPAddr: network["ip_address"].(types.String).ValueString(),
|
||||
}
|
||||
tflog.Info(ctx, "ComputeResourceNetworkUpdate: before calling CloudAPI().Compute().ChangeIP", map[string]any{"compute_id": computeId, "req": req})
|
||||
res, err := c.CloudAPI().Compute().ChangeIP(ctx, req)
|
||||
tflog.Info(ctx, "ComputeResourceNetworkUpdate: response from CloudAPI().Compute().ChangeIP", map[string]any{"compute_id": plan.ID.ValueString(), "response": res})
|
||||
if err != nil {
|
||||
diags.AddError(fmt.Sprintf("ComputeResourceNetworkUpdate: failed to change IP net ID %d from Compute ID %d",
|
||||
network["net_id"].(types.Int64).ValueInt64(), computeId), err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +288,7 @@ func ComputeResourceNetworkUpdate(ctx context.Context, state *models.ResourceCom
|
||||
|
||||
needStart := false
|
||||
// need stop to attach first network
|
||||
if (len(detachSet) == len(state.Network.Elements()) || len(state.Network.Elements()) < 1) && len(attachSet) > 0 {
|
||||
if len(detachMap) == len(state.Network.Elements()) || (len(state.Network.Elements()) < 1) && len(attachMap) > 0 || hasDPDKnetwork(attachMap) {
|
||||
tflog.Info(ctx, "ComputeResourceNetworkUpdate: stop compute", map[string]any{"compute_id": computeId})
|
||||
_, err = c.CloudAPI().Compute().Stop(ctx, compute.StopRequest{ComputeID: computeId})
|
||||
if err != nil {
|
||||
@@ -226,18 +297,33 @@ func ComputeResourceNetworkUpdate(ctx context.Context, state *models.ResourceCom
|
||||
)
|
||||
return diags
|
||||
}
|
||||
needStart = true
|
||||
if plan.Started.ValueBool() {
|
||||
needStart = true
|
||||
}
|
||||
}
|
||||
|
||||
for _, network := range attachSet {
|
||||
objVal := network.(types.Object)
|
||||
elemMap := objVal.Attributes()
|
||||
sort.Slice(attachMap, func(i, j int) bool {
|
||||
weightI := attachMap[i]["weight"].(types.Int64).ValueInt64()
|
||||
weightJ := attachMap[j]["weight"].(types.Int64).ValueInt64()
|
||||
if weightI == 0 {
|
||||
return false
|
||||
}
|
||||
if weightJ == 0 {
|
||||
return true
|
||||
}
|
||||
return weightI < weightJ
|
||||
})
|
||||
|
||||
for _, network := range attachMap {
|
||||
req := compute.NetAttachRequest{
|
||||
ComputeID: computeId,
|
||||
NetType: strings.ToUpper(elemMap["net_type"].(types.String).ValueString()),
|
||||
NetID: uint64(elemMap["net_id"].(types.Int64).ValueInt64()),
|
||||
NetType: strings.ToUpper(network["net_type"].(types.String).ValueString()),
|
||||
NetID: uint64(network["net_id"].(types.Int64).ValueInt64()),
|
||||
}
|
||||
ipaddr, ipSet := elemMap["ip_address"]
|
||||
if req.NetType == "DPDK" {
|
||||
req.MTU = uint64(network["mtu"].(types.Int64).ValueInt64())
|
||||
}
|
||||
ipaddr, ipSet := network["ip_address"]
|
||||
if ipSet {
|
||||
req.IPAddr = ipaddr.(types.String).ValueString()
|
||||
}
|
||||
@@ -246,11 +332,11 @@ func ComputeResourceNetworkUpdate(ctx context.Context, state *models.ResourceCom
|
||||
tflog.Info(ctx, "ComputeResourceNetworkUpdate: response from CloudAPI().Compute().NetAttach", map[string]any{"compute_id": plan.ID.ValueString(), "response": res})
|
||||
if err != nil {
|
||||
diags.AddError(fmt.Sprintf("ComputeResourceNetworkUpdate: failed to attach net ID %d from Compute ID %d",
|
||||
elemMap["net_id"].(types.Int64).ValueInt64(), computeId), err.Error())
|
||||
network["net_id"].(types.Int64).ValueInt64(), computeId), err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if needStart && (plan.Started.ValueBool() || plan.Started.IsNull()) {
|
||||
if needStart {
|
||||
diags = ComputeResourceStartStop(ctx, plan, c)
|
||||
}
|
||||
|
||||
@@ -263,6 +349,15 @@ func ComputeResourceNetworkUpdate(ctx context.Context, state *models.ResourceCom
|
||||
return nil
|
||||
}
|
||||
|
||||
func hasDPDKnetwork(networkAttachMap []map[string]attr.Value) bool {
|
||||
for _, elem := range networkAttachMap {
|
||||
if elem["net_type"].(types.String).ValueString() == "DPDK" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func ComputeResourceComputeUpdate(ctx context.Context, state *models.ResourceComputeModel, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
|
||||
tflog.Info(ctx, "ComputeResourceComputeUpdate: start update compute parameters", map[string]any{"compute_id": plan.ID.ValueString()})
|
||||
diags := diag.Diagnostics{}
|
||||
@@ -301,6 +396,10 @@ func ComputeResourceComputeUpdate(ctx context.Context, state *models.ResourceCom
|
||||
req.HPBacked = state.HPBacked.ValueBool()
|
||||
}
|
||||
|
||||
if !plan.Chipset.IsUnknown() && !plan.Chipset.Equal(state.Chipset) {
|
||||
req.Chipset = plan.Chipset.ValueString()
|
||||
}
|
||||
|
||||
// Note bene: numa_affinity, cpu_pin and hp_backed are not allowed to be changed for compute in STARTED tech status.
|
||||
// If STARTED, we need to stop it before update
|
||||
|
||||
@@ -328,7 +427,7 @@ func ComputeResourceComputeUpdate(ctx context.Context, state *models.ResourceCom
|
||||
return diags
|
||||
}
|
||||
|
||||
if isStopRequred && (plan.Started.ValueBool() || plan.Started.IsNull()) {
|
||||
if isStopRequred && plan.Started.ValueBool() {
|
||||
diags = ComputeResourceStartStop(ctx, plan, c)
|
||||
}
|
||||
|
||||
@@ -889,7 +988,7 @@ func ComputeResourceRollback(ctx context.Context, plan *models.ResourceComputeMo
|
||||
return diags
|
||||
}
|
||||
|
||||
if plan.Started.ValueBool() || plan.Started.IsNull() {
|
||||
if plan.Started.ValueBool() {
|
||||
diags = ComputeResourceStartStop(ctx, plan, c)
|
||||
if diags.HasError() {
|
||||
tflog.Error(ctx, "ComputeResourceRollback: cannot start compute")
|
||||
@@ -1092,7 +1191,7 @@ func ComputeResourceRedeploy(ctx context.Context, plan *models.ResourceComputeMo
|
||||
return diags
|
||||
}
|
||||
|
||||
if plan.Started.ValueBool() || plan.Started.IsNull() {
|
||||
if plan.Started.ValueBool() {
|
||||
diags = ComputeResourceStartStop(ctx, plan, c)
|
||||
if diags.HasError() {
|
||||
tflog.Error(ctx, "ComputeResourceRedeploy: cannot start compute")
|
||||
|
||||
Reference in New Issue
Block a user