This commit is contained in:
asteam
2025-07-01 13:44:09 +03:00
parent 5382579a5f
commit ddbb12996d
1041 changed files with 2842 additions and 96448 deletions

View File

@@ -37,6 +37,60 @@ func ComputeResourceCheckPresence(ctx context.Context, plan *models.ResourceComp
return computeItem, nil
}
func ResourceComputePCIDevicesListCheckPresence(ctx context.Context, id uint64, c *client.Client) (*compute.ListPCIDevices, error) {
tflog.Info(ctx, "Get PCI devices info")
req := compute.ListPCIDeviceRequest{
ComputeID: id,
}
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
}
func ComputeResourceUserAccessGet(ctx context.Context, computeID uint64, c *client.Client) (*compute.ListUsers, error) {
tflog.Info(ctx, "Get compute user access info")
req := compute.UserListRequest{
ComputeID: computeID,
}
tflog.Info(ctx, "Check req", map[string]any{"req": req})
userList, err := c.CloudAPI().Compute().UserList(ctx, req)
if err != nil {
return nil, err
}
tflog.Info(ctx, "Getting compute user access info, successfully")
return userList, nil
}
func ComputeResourcePFWListGet(ctx context.Context, computeID uint64, c *client.Client) (*compute.ListPFWs, error) {
tflog.Info(ctx, "Get compute pfw list info")
req := compute.PFWListRequest{
ComputeID: computeID,
}
tflog.Info(ctx, "Check req", map[string]any{"req": req})
pfwList, err := c.CloudAPI().Compute().PFWList(ctx, req)
if err != nil {
return nil, err
}
tflog.Info(ctx, "Getting compute pfw list info, successfully")
return pfwList, nil
}
func ComputeResourceCheckDetachDisks(state *models.ResourceComputeModel, recordCompute *compute.RecordCompute) bool {
bootDiskId := uint64(state.BootDiskId.ValueInt64())
extraDiskList := state.ExtraDisks.Elements()
@@ -140,6 +194,10 @@ func CreateResourceCompute(ctx context.Context, plan *models.ResourceComputeMode
if ipSet {
reqInterface.IPAddr = ipaddr.(types.String).ValueString()
}
macaddr, macSet := elemMap["mac"]
if macSet {
reqInterface.MAC = macaddr.(types.String).ValueString()
}
interfaces = append(interfaces, reqInterface)
}
@@ -206,6 +264,37 @@ func CreateResourceCompute(ctx context.Context, plan *models.ResourceComputeMode
diags.AddError("CreateResourceCompute: unable to create KVM VP x86", err.Error())
return 0, diags
}
updateReq := compute.UpdateRequest{}
if !plan.LoaderType.IsNull() {
updateReq.LoaderType = plan.LoaderType.ValueString()
}
if !plan.BootType.IsNull() {
updateReq.BootType = plan.BootType.ValueString()
}
if !plan.HotResize.IsNull() {
updateReq.HotResize = plan.HotResize.ValueBool()
}
if !plan.NetworkInterfaceNaming.IsNull() {
updateReq.NetworkInterfaceNaming = plan.NetworkInterfaceNaming.ValueString()
}
if !plan.LoaderType.IsNull() ||
!plan.BootType.IsNull() ||
!plan.HotResize.IsNull() ||
!plan.NetworkInterfaceNaming.IsNull() {
updateReq.ComputeID = id
tflog.Info(ctx, "CreateResourceCompute: creating Compute with LoaderType or BootType or HotResize or NetworkInterfaceNaming")
_, err = c.CloudAPI().Compute().Update(ctx, updateReq)
if err != nil {
diags.AddWarning("CreateResourceCompute: unable to update LoaderType or BootType or HotResize or NetworkInterfaceNaming", err.Error())
}
}
return id, diags
}
@@ -520,8 +609,8 @@ func ComputeResourcePortForwarding(ctx context.Context, plan *models.ResourceCom
PublicPortStart: uint64(itemPortForwarding.PublicPortStart.ValueInt64()),
Proto: strings.ToLower(itemPortForwarding.Proto.ValueString()),
}
if itemPortForwarding.PublicPortStart.ValueInt64() != 0 {
req.PublicPortStart = uint64(itemPortForwarding.PublicPortStart.ValueInt64())
if itemPortForwarding.PublicPortEnd.ValueInt64() != 0 {
req.PublicPortEnd = itemPortForwarding.PublicPortEnd.ValueInt64()
}
if itemPortForwarding.LocalPort.ValueInt64() != 0 {
req.LocalBasePort = uint64(itemPortForwarding.LocalPort.ValueInt64())
@@ -659,7 +748,7 @@ func ComputeResourceCDInsert(ctx context.Context, plan *models.ResourceComputeMo
}
req := compute.CDInsertRequest{ComputeID: computeId}
req.CDROMID = uint64(plan.CD.Attributes()["cdrom_id"].(types.Int64).ValueInt64())
req.CDROMID = uint64(plan.CDImageID.ValueInt64())
tflog.Info(ctx, "ComputeResourceCDInsert: before calling CloudAPI().Compute().CDInsert", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().CDInsert(ctx, req)
tflog.Info(ctx, "ComputeResourceCDInsert: response from CloudAPI().Compute().CDInsert", map[string]any{"compute_id": computeId, "response": res})

View File

@@ -33,12 +33,13 @@ func differenceSimpleType(oldSet, newSet types.Set) (added, removed []any) {
return
}
func differenceNetwork(oldSet, newSet types.Set) (added, changeIp, removed []map[string]attr.Value) {
func differenceNetwork(oldSet, newSet types.Set) (added, changeIp, changeMac, removed []map[string]attr.Value) {
oldSlice := oldSet.Elements()
newSlice := newSet.Elements()
added = make([]map[string]attr.Value, 0)
changeIp = make([]map[string]attr.Value, 0)
changeMac = make([]map[string]attr.Value, 0)
removed = make([]map[string]attr.Value, 0)
for _, oldNetwork := range oldSlice {
@@ -47,15 +48,19 @@ func differenceNetwork(oldSet, newSet types.Set) (added, changeIp, removed []map
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() != "") {
found = true
switch {
case (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
break
fallthrough
case newMap["mac"] != oldMap["mac"] && newMap["mac"].(types.String).ValueString() != "":
newMap["old_mac"] = oldMap["mac"]
changeMac = append(changeMac, newMap)
}
}
if found {
break
}
}
if found {
continue
@@ -69,10 +74,8 @@ func differenceNetwork(oldSet, newSet types.Set) (added, changeIp, removed []map
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
}
found = true
break
}
}
if found {

View File

@@ -93,7 +93,7 @@ func ComputeResourceBootDiskResize(ctx context.Context, state *models.ResourceCo
}
if state.BootDiskSize.ValueInt64() > plan.BootDiskSize.ValueInt64() {
diags.AddError(fmt.Sprintf("ComputeResourceBootDiskResize: compute ID %d - shrinking boot disk is not allowed", computeId), "")
diags.AddError(fmt.Sprintf("ComputeResourceBootDiskResize: compute ID %d - shrinking boot disk is not allowed, state: %d, plan: %d", computeId, state.BootDiskSize.ValueInt64(), plan.BootDiskSize.ValueInt64()), "")
return diags
}
@@ -159,17 +159,6 @@ func ComputeResourceExtraDiskUpdate(ctx context.Context, state *models.ResourceC
return diags
}
if len(detachSet) > 0 {
tflog.Info(ctx, "ComputeResourceExtraDiskUpdate: stop compute", map[string]any{"compute_id": computeId})
_, err = c.CloudAPI().Compute().Stop(ctx, compute.StopRequest{ComputeID: computeId})
if err != nil {
diags.AddError(
"ComputeResourceExtraDiskUpdate: cannot stop compute", err.Error(),
)
return diags
}
}
for _, disk := range detachSet {
diskId := uint64(disk.(types.Int64).ValueInt64())
tflog.Info(ctx, fmt.Sprintf("ComputeResourceExtraDiskUpdate: Start detach extra disk with ID - %d from compute with ID - %d", diskId, computeId))
@@ -184,10 +173,6 @@ func ComputeResourceExtraDiskUpdate(ctx context.Context, state *models.ResourceC
}
}
if len(detachSet) > 0 && plan.Started.ValueBool() {
diags = ComputeResourceStartStop(ctx, plan, c)
}
if diags.HasError() {
tflog.Error(ctx, "ComputeResourceExtraDiskUpdate: Errors occurred while managing disks")
return diags
@@ -207,7 +192,7 @@ func ComputeResourcePCIDeviceUpdate(ctx context.Context, state *models.ResourceC
return diags
}
attachSet, detachSet := differenceSimpleType(state.ExtraDisks, plan.ExtraDisks)
attachSet, detachSet := differenceSimpleType(state.PCIDevices, plan.PCIDevices)
for _, pciDevice := range detachSet {
pciDeviceId := pciDevice.(types.Int64).ValueInt64()
@@ -256,7 +241,7 @@ func ComputeResourceNetworkUpdate(ctx context.Context, state *models.ResourceCom
return diags
}
attachMap, changeIpMap, detachMap := differenceNetwork(state.Network, plan.Network)
attachMap, changeIpMap, changeMacMap, detachMap := differenceNetwork(state.Network, plan.Network)
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 {
@@ -302,7 +287,7 @@ func ComputeResourceNetworkUpdate(ctx context.Context, state *models.ResourceCom
needStart := false
// need stop to attach first network
if len(detachMap) == len(state.Network.Elements()) || (len(state.Network.Elements()) < 1) && len(attachMap) > 0 {
if len(detachMap) == len(state.Network.Elements()) || (len(state.Network.Elements()) < 1) && len(attachMap) > 0 || hasDPDKnetwork(attachMap) || len(changeMacMap) > 0 {
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 {
@@ -316,6 +301,27 @@ func ComputeResourceNetworkUpdate(ctx context.Context, state *models.ResourceCom
}
}
tflog.Info(ctx, "ComputeResourceNetworkUpdate: start change MAC address network(s) to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
for _, network := range changeMacMap {
req := compute.ChangeMACRequest{
ComputeID: computeId,
NewMAC: network["mac"].(types.String).ValueString(),
СurrentMAC: network["old_mac"].(types.String).ValueString(),
}
tflog.Info(ctx, "ComputeResourceNetworkUpdate: before calling CloudAPI().Compute().ChangeMAC", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().ChangeMAC(ctx, req)
tflog.Info(ctx, "ComputeResourceNetworkUpdate: response from CloudAPI().Compute().ChangeMAC", map[string]any{"compute_id": plan.ID.ValueString(), "response": res})
if err != nil {
diags.AddError(fmt.Sprintf("ComputeResourceNetworkUpdate: failed to change Mac to net ID %d from Compute ID %d",
network["net_id"].(types.Int64).ValueInt64(), computeId), err.Error())
}
}
if diags.HasError() {
return diags
}
sort.Slice(attachMap, func(i, j int) bool {
weightI := attachMap[i]["weight"].(types.Int64).ValueInt64()
weightJ := attachMap[j]["weight"].(types.Int64).ValueInt64()
@@ -341,6 +347,10 @@ func ComputeResourceNetworkUpdate(ctx context.Context, state *models.ResourceCom
if ipSet {
req.IPAddr = ipaddr.(types.String).ValueString()
}
macaddr, macSet := network["mac"]
if macSet {
req.MACAddr = macaddr.(types.String).ValueString()
}
tflog.Info(ctx, "ComputeResourceNetworkUpdate: before calling CloudAPI().Compute().NetAttach", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().NetAttach(ctx, req)
tflog.Info(ctx, "ComputeResourceNetworkUpdate: response from CloudAPI().Compute().NetAttach", map[string]any{"compute_id": plan.ID.ValueString(), "response": res})
@@ -367,6 +377,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 *client.Client) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourceComputeUpdate: start update compute parameters", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
@@ -389,13 +408,29 @@ func ComputeResourceComputeUpdate(ctx context.Context, state *models.ResourceCom
req.Description = plan.Description.ValueString()
}
if !plan.NumaAffinity.Equal(state.NumaAffinity) {
if !plan.NumaAffinity.Equal(state.NumaAffinity) && !plan.NumaAffinity.IsUnknown() {
req.NumaAffinity = plan.NumaAffinity.ValueString()
}
req.CPUPin = plan.CPUPin.ValueBool()
req.HPBacked = plan.HPBacked.ValueBool()
req.AutoStart = plan.AutoStartWithNode.ValueBool()
if !plan.CPUPin.Equal(state.CPUPin) && !plan.CPUPin.IsUnknown() {
req.CPUPin = plan.CPUPin.ValueBool()
}
if !plan.HPBacked.Equal(state.HPBacked) && !plan.HPBacked.IsUnknown() {
req.HPBacked = plan.HPBacked.ValueBool()
}
if !plan.LoaderType.Equal(state.LoaderType) && !plan.LoaderType.IsUnknown() {
req.LoaderType = plan.LoaderType.ValueString()
}
if !plan.BootType.Equal(state.BootType) && !plan.BootType.IsUnknown() {
req.BootType = plan.BootType.ValueString()
}
if !plan.HotResize.Equal(state.HotResize) && !plan.HotResize.IsUnknown() {
req.HotResize = plan.HotResize.ValueBool()
}
if !plan.NetworkInterfaceNaming.Equal(state.NetworkInterfaceNaming) && !plan.NetworkInterfaceNaming.IsUnknown() {
req.NetworkInterfaceNaming = plan.NetworkInterfaceNaming.ValueString()
}
if !plan.Chipset.IsUnknown() && !plan.Chipset.Equal(state.Chipset) {
req.Chipset = plan.Chipset.ValueString()
@@ -413,6 +448,10 @@ func ComputeResourceComputeUpdate(ctx context.Context, state *models.ResourceCom
req.PreferredCPU = []int64{-1}
}
if !plan.LoaderType.IsUnknown() && !plan.LoaderType.Equal(state.Description) {
req.Description = plan.Description.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
@@ -917,19 +956,35 @@ func ComputeResourceSnapshotUpdate(ctx context.Context, state *models.ResourceCo
addedLabel, deleteLabel := differenceSnapshot(state.Snapshot, plan.Snapshot)
for _, label := range deleteLabel {
req := compute.SnapshotDeleteRequest{ComputeID: computeId}
objTag := label.(types.Object)
tagMap := objTag.Attributes()
req.Label = tagMap["label"].(types.String).ValueString()
tflog.Info(ctx, "ComputeResourceSnapshotUpdate: before calling CloudAPI().Compute().SnapshotDelete", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().SnapshotDelete(ctx, req)
tflog.Info(ctx, "ComputeResourceSnapshotUpdate: response from CloudAPI().Compute().SnapshotDelete", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourceSnapshotUpdate: Unable to delete snapshot for Compute",
err.Error(),
)
reqLabel := tagMap["label"].(types.String).ValueString()
req := compute.SnapshotDeleteRequest{ComputeID: computeId, Label: reqLabel}
if (state.SnapshotDeleteAsync).ValueBool() {
tflog.Info(ctx, "ComputeResourceSnapshotUpdate: before calling CloudAPI().Compute().SnapshotDeleteAsync", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().SnapshotDeleteAsync(ctx, req)
req.Label = reqLabel
tflog.Info(ctx, "ComputeResourceSnapshotUpdate: response from CloudAPI().Compute().SnapshotDeleteAsync", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourceSnapshotUpdate: Unable to async delete snapshot for Compute",
err.Error(),
)
}
} else {
tflog.Info(ctx, "ComputeResourceSnapshotUpdate: before calling CloudAPI().Compute().SnapshotDelete", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().SnapshotDelete(ctx, req)
req.Label = reqLabel
tflog.Info(ctx, "ComputeResourceSnapshotUpdate: response from CloudAPI().Compute().SnapshotDelete", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourceSnapshotUpdate: Unable to delete snapshot for Compute",
err.Error(),
)
}
}
}
if diags.HasError() {
@@ -1023,7 +1078,7 @@ func ComputeResourceCDUpdate(ctx context.Context, plan *models.ResourceComputeMo
return diags
}
if plan.CD.IsNull() {
if plan.CDImageID.IsNull() {
tflog.Info(ctx, "ComputeResourceCDUpdate: before calling CloudAPI().Compute().CDEject", map[string]any{"compute_id": computeId})
res, err := c.CloudAPI().Compute().CDEject(ctx, compute.CDEjectRequest{ComputeID: computeId})
tflog.Info(ctx, "ComputeResourceCDUpdate: response from CloudAPI().Compute().CDEject", map[string]any{"compute_id": computeId, "response": res})
@@ -1036,7 +1091,7 @@ func ComputeResourceCDUpdate(ctx context.Context, plan *models.ResourceComputeMo
}
} else {
req := compute.CDInsertRequest{ComputeID: computeId}
req.CDROMID = uint64(plan.CD.Attributes()["cdrom_id"].(types.Int64).ValueInt64())
req.CDROMID = uint64(plan.CDImageID.ValueInt64())
tflog.Info(ctx, "ComputeResourceCDUpdate: before calling CloudAPI().Compute().CDInsert", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().CDInsert(ctx, req)
tflog.Info(ctx, "ComputeResourceCDUpdate: response from CloudAPI().Compute().CDInsert", map[string]any{"compute_id": computeId, "response": res})
@@ -1188,17 +1243,14 @@ func ComputeResourceRedeploy(ctx context.Context, plan *models.ResourceComputeMo
req := compute.RedeployRequest{
ComputeID: computeId,
ImageID: uint64(plan.ImageID.ValueInt64()),
DataDisks: "detach",
DataDisks: "KEEP",
}
if !plan.BootDiskSize.IsNull() {
req.DiskSize = uint64(plan.BootDiskSize.ValueInt64())
}
if !plan.DataDisks.IsNull() {
req.DataDisks = plan.DataDisks.ValueString()
}
if !plan.AutoStart.IsNull() {
req.AutoStart = plan.AutoStart.ValueBool()
if !plan.Started.IsNull() {
req.AutoStart = plan.Started.ValueBool()
}
if !plan.ForceStop.IsNull() {
req.ForceStop = plan.ForceStop.ValueBool()