Skip to content
10 changes: 9 additions & 1 deletion internal/provider/hypercore_disk_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,15 @@ func (r *HypercoreDiskResource) Update(ctx context.Context, req resource.UpdateR
}
oldHc3Disk := *pDisk

// Validate that source VM UUID hasn't changed (task 103 - disk source UUID cannot be changed after creation)
oldVMUUID := utils.AnyToString(oldHc3Disk["virDomainUUID"])
newVMUUID := data.VmUUID.ValueString()
diagDiskSourceVMUUID := utils.ValidateDiskSourceVMUUIDUnchanged(diskUUID, oldVMUUID, newVMUUID)
if diagDiskSourceVMUUID != nil {
resp.Diagnostics.AddError(diagDiskSourceVMUUID.Summary(), diagDiskSourceVMUUID.Detail())
return
}

// Validate the size
oldDiskSize := utils.AnyToFloat64(oldHc3Disk["capacity"]) / 1000 / 1000 / 1000 // B to GB
wantedDiskSize := data.Size.ValueFloat64()
Expand Down Expand Up @@ -360,7 +369,6 @@ func (r *HypercoreDiskResource) Update(ctx context.Context, req resource.UpdateR
isDetachingISO := oldHc3Disk["path"] != "" && data.IsoUUID.ValueString() == "" && data.Type.ValueString() == "IDE_CDROM"

updatePayload := map[string]any{
"virDomainUUID": vmUUID,
"type": data.Type.ValueString(),
"capacity": data.Size.ValueFloat64() * 1000 * 1000 * 1000, // GB to B
"tieringPriorityFactor": utils.FROM_HUMAN_PRIORITY_FACTOR[data.FlashPriority.ValueInt64()],
Comment thread
domendobnikar marked this conversation as resolved.
Expand Down
32 changes: 25 additions & 7 deletions internal/provider/hypercore_nic_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,11 +207,28 @@ func (r *HypercoreNicResource) Update(ctx context.Context, req resource.UpdateRe
tflog.Debug(ctx, fmt.Sprintf("TTRT HypercoreNicResource Update vm_uuid=%s nic_uuid=%s REQUESTED vlan=%d type=%s", vmUUID, nicUUID, data.Vlan.ValueInt64(), data.Type.String()))
tflog.Debug(ctx, fmt.Sprintf("TTRT HypercoreNicResource Update vm_uuid=%s nic_uuid=%s STATE vlan=%d type=%s", vmUUID, nicUUID, data_state.Vlan.ValueInt64(), data_state.Type.String()))

// Get NIC before update
pNic := utils.GetNic(restClient, nicUUID)
if pNic == nil {
msg := fmt.Sprintf("NIC not found - nicUUID=%s, vmUUID=%s.", nicUUID, vmUUID)
resp.Diagnostics.AddError("NIC not found", msg)
return
}
oldHc3Nic := *pNic

// Validate that source VM UUID hasn't changed (task 103 - NIC source UUID cannot be changed after creation)
oldVMUUID := utils.AnyToString(oldHc3Nic["virDomainUUID"])
newVMUUID := data.VmUUID.ValueString()
diagNICSourceVMUUID := utils.ValidateNICSourceVMUUIDUnchanged(nicUUID, oldVMUUID, newVMUUID)
if diagNICSourceVMUUID != nil {
resp.Diagnostics.AddError(diagNICSourceVMUUID.Summary(), diagNICSourceVMUUID.Detail())
return
}

updatePayload := map[string]any{
"virDomainUUID": vmUUID,
"type": data.Type.ValueString(),
"vlan": data.Vlan.ValueInt64(),
"macAddress": data.MacAddress.ValueString(),
"type": data.Type.ValueString(),
"vlan": data.Vlan.ValueInt64(),
"macAddress": data.MacAddress.ValueString(),
}
Comment thread
domendobnikar marked this conversation as resolved.
diag := utils.UpdateNic(restClient, nicUUID, updatePayload, ctx)
if diag != nil {
Expand All @@ -220,15 +237,16 @@ func (r *HypercoreNicResource) Update(ctx context.Context, req resource.UpdateRe

// TODO: Check if HC3 matches TF
// Do not trust UpdateNic made what we asked for. Read new NIC state from HC3.
pNic := utils.GetNic(restClient, nicUUID)
pNic = utils.GetNic(restClient, nicUUID)
if pNic == nil {
msg := fmt.Sprintf("NIC not found - nicUUID=%s, vmUUID=%s.", nicUUID, vmUUID)
resp.Diagnostics.AddError("NIC not found", msg)
return
}
nic := *pNic
newHc3Nic := *pNic

//
tflog.Info(ctx, fmt.Sprintf("TTRT HypercoreNicResource: vm_uuid=%s, nic_uuid=%s, nic=%v", vmUUID, nicUUID, nic))
tflog.Info(ctx, fmt.Sprintf("TTRT HypercoreNicResource: vm_uuid=%s, nic_uuid=%s, nic=%v", vmUUID, nicUUID, newHc3Nic))

// TODO MAC, IP address etc

Expand Down
29 changes: 24 additions & 5 deletions internal/provider/hypercore_vm_replication_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,6 @@ func (r *HypercoreVMReplicationResource) Update(ctx context.Context, req resourc

restClient := *r.client
replicationUUID := data.Id.ValueString()
vmUUID := data.VmUUID.ValueString()
connectionUUID := data.ConnectionUUID.ValueString()
label := data.Label.ValueString()

Expand All @@ -261,22 +260,42 @@ func (r *HypercoreVMReplicationResource) Update(ctx context.Context, req resourc
"Missing connection_uuid",
"Parameter 'connection_uuid' is required for updating a VM replication",
)
return
}

// Get replication before update
pReplication := utils.GetVMReplicationByUUID(restClient, replicationUUID)
if pReplication == nil {
msg := fmt.Sprintf("VM replication not found - replicationUUID=%s.", replicationUUID)
resp.Diagnostics.AddError("VM replication not found", msg)
return
}
oldHc3Replication := *pReplication

// Validate that source VM UUID hasn't changed (task 103 - replication source UUID cannot be changed after creation)
oldVMUUID := utils.AnyToString(oldHc3Replication["sourceDomainUUID"])
newVMUUID := data.VmUUID.ValueString()
diagReplicationSourceVMUUID := utils.ValidateReplicationSourceVMUUIDUnchanged(replicationUUID, oldVMUUID, newVMUUID)
if diagReplicationSourceVMUUID != nil {
resp.Diagnostics.AddError(diagReplicationSourceVMUUID.Summary(), diagReplicationSourceVMUUID.Detail())
return
}

diag := utils.UpdateVMReplication(restClient, replicationUUID, vmUUID, connectionUUID, label, enable, ctx)

diag := utils.UpdateVMReplication(restClient, replicationUUID, connectionUUID, label, enable, ctx)
Comment thread
domendobnikar marked this conversation as resolved.
if diag != nil {
resp.Diagnostics.AddWarning(diag.Summary(), diag.Detail())
}

// TODO: Check if HC3 matches TF
// Do not trust UpdateVMReplication made what we asked for. Read new power state from HC3.
pHc3Replication := utils.GetVMReplicationByUUID(restClient, replicationUUID)
if pHc3Replication == nil {
pReplication = utils.GetVMReplicationByUUID(restClient, replicationUUID)
if pReplication == nil {
msg := fmt.Sprintf("VM replication not found - replicationUUID=%s.", replicationUUID)
resp.Diagnostics.AddError("VM replication not found", msg)
return
}
newHc3Replication := *pHc3Replication
newHc3Replication := *pReplication

tflog.Info(ctx, fmt.Sprintf("TTRT HypercoreVMReplicationResource: replication_uuid=%s, replication=%v", replicationUUID, newHc3Replication))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func TestAccHypercoreVMsDatasource_stopped(t *testing.T) {
resource.TestCheckResourceAttr("data.hypercore_vms.test", "vms.0.memory", "4096"),
// resource.TestCheckResourceAttr("data.hypercore_vms.test", "vms.0.vcpu", "1"),
resource.TestCheckResourceAttr("data.hypercore_vms.test", "vms.0.power_state", "SHUTOFF"),
resource.TestCheckResourceAttr("data.hypercore_vms.test", "vms.0.disks.#", "2"),
resource.TestCheckResourceAttr("data.hypercore_vms.test", "vms.0.disks.#", "4"),
resource.TestCheckResourceAttr("data.hypercore_vms.test", "vms.0.disks.0.type", "VIRTIO_DISK"),
resource.TestCheckResourceAttr("data.hypercore_vms.test", "vms.0.disks.0.slot", "0"),
resource.TestCheckResourceAttr("data.hypercore_vms.test", "vms.0.disks.0.size", "1.2"),
Expand Down
155 changes: 9 additions & 146 deletions internal/utils/nic.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,153 +78,16 @@ func UpdateNic(
return nil
}

/*
func (vd *VMDisk) CreateOrUpdate(
vc *VMClone,
restClient RestClient,
ctx context.Context,
) (bool, bool, string, error) {
changed := false
vm := GetByName(vc.VMName, restClient, true)
vmUUID := AnyToString((*vm)["uuid"])
vmDisks := AnyToListOfMap((*vm)["blockDevs"])

if vd.Size != nil {
existingDisk := vd.GetSpecificDisk(vmDisks, ctx) // from HC3
desiredDisk := vd.BuildDiskPayload(vmUUID)

tflog.Debug(ctx, fmt.Sprintf("Desired disk: %v\n", desiredDisk))
tflog.Debug(ctx, fmt.Sprintf("Existing disk: %v\n", existingDisk))

if existingDisk != nil {
existingDiskSize := AnyToFloat64((*existingDisk)["capacity"]) / 1000 / 1000 / 1000
existingDiskSlot := AnyToInteger64((*existingDisk)["slot"])
existingDiskType := AnyToString((*existingDisk)["type"])
desiredDiskSize := AnyToFloat64(desiredDisk["capacity"]) / 1000 / 1000 / 1000
if existingDiskSize > desiredDiskSize {
return false, false, "", fmt.Errorf(
"Disk of type '%s' on slot %d can only be expanded. Use a different slot or use a larger size. %v GB > %v GB\n",
existingDiskType, existingDiskSlot, existingDiskSize, desiredDiskSize,
)
}
}

if existingDisk != nil {
if isSuperset(*existingDisk, desiredDisk) {
return false, vc.WasRebooted(), "", nil
}

tflog.Debug(ctx, "Updating existing disk\n")
vd.UUID = vd.UpdateBlockDevice(vc, vmUUID, restClient, desiredDisk, *existingDisk, ctx)
changed = true
} else {
tflog.Debug(ctx, "Creating new disk\n")
vd.UUID = vd.CreateBlockDevice(restClient, desiredDisk, ctx)
changed = true
}
}

return changed, vc.WasRebooted(), vd.UUID, nil
}

func (vd *VMDisk) UpdateBlockDevice(
vc *VMClone,
vmUUID string,
restClient RestClient,
desiredDisk map[string]any,
existingDisk map[string]any,
ctx context.Context,
) string {
vc.DoShutdownSteps(vmUUID, SHUTDOWN_TIMEOUT_SECONDS, restClient, ctx)

existingDiskUUID := AnyToString(existingDisk["uuid"])
taskTag := restClient.UpdateRecord(
fmt.Sprintf("/rest/v1/VirDomainBlockDevice/%s", existingDiskUUID),
desiredDisk,
-1,
ctx,
)
taskTag.WaitTask(restClient, ctx)

return existingDiskUUID
}

func (vd *VMDisk) CreateBlockDevice(
restClient RestClient,
desiredDisk map[string]any,
ctx context.Context,
) string {
taskTag, _, _ := restClient.CreateRecord(
"/rest/v1/VirDomainBlockDevice",
desiredDisk,
-1,
)
taskTag.WaitTask(restClient, ctx)

return taskTag.CreatedUUID
}

// This function will be useful when dealing with IDE_CDROM type disks: so for the future
// nolint:unused
func (vd *VMDisk) EnsureAbsend(
vc *VMClone,
changedParams map[string]bool,
restClient RestClient,
ctx context.Context,
) (bool, bool, map[string]any) {
vm := GetByName(vc.VMName, restClient, true)
vmDisks := AnyToListOfMap((*vm)["blockDevs"])

if vd.Size != nil {
existingDisk := vd.GetSpecificDisk(vmDisks, ctx)
if existingDisk == nil {
return true, false, map[string]any{} // no disk - absent is already ensured
}

diskUUID := AnyToString((*existingDisk)["uuid"])

// Remove the disk to ensure it's absence
vmUUID := AnyToString((*vm)["uuid"])
vc.DoShutdownSteps(vmUUID, SHUTDOWN_TIMEOUT_SECONDS, restClient, ctx)

taskTag := restClient.DeleteRecord(
fmt.Sprintf("/rest/v1/VirDomainBlockDevice/%s", diskUUID),
-1,
ctx,
// Checks that source VM UUID wasn't altered during update.
func ValidateNICSourceVMUUIDUnchanged(nicUUID string, oldVMUUID string, newVMUUID string) diag.Diagnostic {
if oldVMUUID != newVMUUID {
return diag.NewErrorDiagnostic(
"Invalid NIC source virtual machine UUID",
fmt.Sprintf(
" virtual machine and NIC relationship is established at creation and cannot be changed, source UUID: %s, new VM UUID: %s, NIC UUID: %s",
oldVMUUID, newVMUUID, nicUUID,
),
Comment thread
domendobnikar marked this conversation as resolved.
)
Comment thread
domendobnikar marked this conversation as resolved.
taskTag.WaitTask(restClient, ctx)

vc.PowerUp(*vm, restClient, ctx)
return true, true, map[string]any{}
}

return false, false, map[string]any{}
}

func (vd *VMDisk) BuildDiskPayload(vmUUID string) map[string]any {
return map[string]any{
"virDomainUUID": vmUUID,
"type": vd.Type,
"slot": vd.Slot,
"capacity": *vd.Size,
}
}

func (vd *VMDisk) GetSpecificDisk(vmDisks []map[string]any, ctx context.Context) *map[string]any {
for _, vmDisk := range vmDisks {
vmDiskUUID := AnyToString(vmDisk["uuid"])
vmDiskSlot := AnyToInteger64(vmDisk["slot"])
vmDiskType := AnyToString(vmDisk["type"])
if vmDiskUUID == vd.UUID {
tflog.Debug(ctx, fmt.Sprintf("Got disk by UUID: %v", vmDisk))
return &vmDisk
}

if vmDiskSlot == vd.Slot && vmDiskType == vd.Type {
tflog.Debug(ctx, fmt.Sprintf("Got disk by slot and type: %v", vmDisk))
return &vmDisk
}
}
return nil
}
*/
Loading
Loading