Skip to content

ISO attach logic #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/resources/disk.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import {

### Optional

- `iso_uuid` (String) ISO UUID we want to attach to the disk, only available with disk type IDE_CDROM.
- `size` (Number) Disk size in `GB`. Must be larger than the current size of the disk if specified.
- `source_virtual_disk_id` (String) UUID of the virtual disk to use to clone and attach to the VM.
- `type` (String) Disk type. Can be: `IDE_DISK`, `SCSI_DISK`, `VIRTIO_DISK`, `IDE_FLOPPY`, `NVRAM`, `VTPM`
Expand Down
70 changes: 70 additions & 0 deletions docs/resources/iso.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "hypercore_iso Resource - hypercore"
subcategory: ""
description: |-
Hypercore ISO resource to manage ISO images. To use this resource, it's recommended to set the environment variable TF_CLI_ARGS_apply="-parallelism=1" or pass the -parallelism parameter to the terraform apply.
---

# hypercore_iso (Resource)

Hypercore ISO resource to manage ISO images. <br><br>To use this resource, it's recommended to set the environment variable `TF_CLI_ARGS_apply="-parallelism=1"` or pass the `-parallelism` parameter to the `terraform apply`.

## Example Usage

```terraform
locals {
vm_name = "myvm"
}

data "hypercore_vm" "isovm" {
name = local.vm_name
}

// Upload ISO from local machine
resource "hypercore_iso" "iso_upload_local" {
name = "testiso-local.iso"
source_url = "file:////home/bla/Downloads/mytestiso.iso"
}

// Upload ISO from remote machine/storage
resource "hypercore_iso" "iso_upload_from_url" {
name = "testiso-remote.iso"
source_url = "https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/aarch64/alpine-virt-3.21.3-aarch64.iso"
}


output "uploaded_iso_LOCAL" {
value = hypercore_iso.iso_upload_local
}

output "uploaded_iso_EXTERNAL" {
value = hypercore_iso.iso_upload_from_url
}

// We can then use this ISO for IDE_CDROM disk
resource "hypercore_disk" "iso_attach" {
vm_uuid = local.vm_name
type = "IDE_CDROM"
iso_uuid = hypercore_iso.iso_upload_local.id
}

output "iso_attach" {
value = hypercore_disk.iso_attach
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `name` (String) Desired name of the ISO to upload. ISO name must end with '.iso'.

### Optional

- `source_url` (String) Source URL from where to fetch that disk from. URL can start with: `http://`, `https://`, `file:///`

### Read-Only

- `id` (String) ISO identifier
12 changes: 12 additions & 0 deletions examples/resources/hypercore_iso/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ data "hypercore_vm" "isovm" {
name = local.vm_name
}

// Upload ISO from local machine
resource "hypercore_iso" "iso_upload_local" {
name = "testiso-local.iso"
source_url = "file:////home/bla/Downloads/mytestiso.iso"
}

// Upload ISO from remote machine/storage
resource "hypercore_iso" "iso_upload_from_url" {
name = "testiso-remote.iso"
source_url = "https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/aarch64/alpine-virt-3.21.3-aarch64.iso"
Expand All @@ -25,3 +27,13 @@ output "uploaded_iso_EXTERNAL" {
value = hypercore_iso.iso_upload_from_url
}

// We can then use this ISO for IDE_CDROM disk
resource "hypercore_disk" "iso_attach" {
vm_uuid = local.vm_name
type = "IDE_CDROM"
iso_uuid = hypercore_iso.iso_upload_local.id
}

output "iso_attach" {
value = hypercore_disk.iso_attach
}
39 changes: 34 additions & 5 deletions internal/provider/hypercore_disk_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type HypercoreDiskResourceModel struct {
Type types.String `tfsdk:"type"`
Size types.Float64 `tfsdk:"size"`
SourceVirtualDiskID types.String `tfsdk:"source_virtual_disk_id"`
IsoUUID types.String `tfsdk:"iso_uuid"`
}

func (r *HypercoreDiskResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
Expand Down Expand Up @@ -79,6 +80,10 @@ func (r *HypercoreDiskResource) Schema(ctx context.Context, req resource.SchemaR
MarkdownDescription: "UUID of the virtual disk to use to clone and attach to the VM.",
Optional: true,
},
"iso_uuid": schema.StringAttribute{
MarkdownDescription: "ISO UUID we want to attach to the disk, only available with disk type IDE_CDROM.",
Optional: true,
},
},
}
}
Expand Down Expand Up @@ -128,20 +133,29 @@ func (r *HypercoreDiskResource) Create(ctx context.Context, req resource.CreateR

tflog.Info(ctx, fmt.Sprintf("TTRT Create: vm_uuid=%s, type=%s, slot=%d, size=%d", data.VmUUID.ValueString(), data.Type.ValueString(), data.Slot.ValueInt64(), data.Slot.ValueInt64()))

diagDiskType := utils.ValidateDiskType(data.Type.ValueString())
var diskUUID string
var disk map[string]any
isAttachingISO := data.IsoUUID.ValueString() != ""

diagDiskType := utils.ValidateDiskType(data.Type.ValueString(), data.IsoUUID.ValueString())
if diagDiskType != nil {
resp.Diagnostics.AddError(diagDiskType.Summary(), diagDiskType.Detail())
return
}
diagISOAttach, iso := utils.ValidateISOAttach(*r.client, data.IsoUUID.ValueString(), isAttachingISO)
if diagISOAttach != nil {
resp.Diagnostics.AddError(diagISOAttach.Summary(), diagISOAttach.Detail())
return
}

createPayload := map[string]any{
"virDomainUUID": data.VmUUID.ValueString(),
"type": data.Type.ValueString(),
"capacity": data.Size.ValueFloat64() * 1000 * 1000 * 1000, // GB to B
}

var diskUUID string
var disk map[string]any
if isAttachingISO {
createPayload["path"] = (*iso)["path"]
}

sourceVirtualDiskID := data.SourceVirtualDiskID.ValueString()
if sourceVirtualDiskID != "" {
Expand All @@ -164,6 +178,7 @@ func (r *HypercoreDiskResource) Create(ctx context.Context, req resource.CreateR
"capacity": originalVDSizeBytes,
},
}

diskUUID, disk = utils.AttachVirtualDisk(
*r.client,
attachPayload,
Expand Down Expand Up @@ -257,6 +272,8 @@ func (r *HypercoreDiskResource) Update(ctx context.Context, req resource.UpdateR
restClient := *r.client
diskUUID := data.Id.ValueString()
vmUUID := data.VmUUID.ValueString()
isAttachingISO := data.IsoUUID.ValueString() != ""

tflog.Debug(
ctx, fmt.Sprintf(
"TTRT HypercoreDiskResource Update vm_uuid=%s disk_uuid=%s REQUESTED slot=%d type=%s size=%v\n",
Expand Down Expand Up @@ -287,17 +304,29 @@ func (r *HypercoreDiskResource) Update(ctx context.Context, req resource.UpdateR
}

// Validate the type
diagDiskType := utils.ValidateDiskType(data.Type.ValueString())
diagDiskType := utils.ValidateDiskType(data.Type.ValueString(), data.IsoUUID.String())
if diagDiskType != nil {
resp.Diagnostics.AddError(diagDiskType.Summary(), diagDiskType.Detail())
return
}
diagISOAttach, iso := utils.ValidateISOAttach(*r.client, data.IsoUUID.ValueString(), isAttachingISO)
if diagISOAttach != nil {
resp.Diagnostics.AddError(diagISOAttach.Summary(), diagISOAttach.Detail())
return
}

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
}
if isAttachingISO {
updatePayload["path"] = (*iso)["path"]
} else if isDetachingISO {
updatePayload["path"] = ""
}
diag := utils.UpdateDisk(restClient, diskUUID, updatePayload, ctx)
if diag != nil {
resp.Diagnostics.AddWarning(diag.Summary(), diag.Detail())
Expand Down
23 changes: 22 additions & 1 deletion internal/utils/vm_disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,16 +311,37 @@ func CreateDisk(
return diskUUID, *disk
}

func ValidateDiskType(diskType string) diag.Diagnostic {
func ValidateDiskType(diskType string, isoUUID string) diag.Diagnostic {
if !ALLOWED_DISK_TYPES[diskType] {
return diag.NewErrorDiagnostic(
"Invalid disk type",
fmt.Sprintf("Disk type '%s' not allowed. Allowed types are: IDE_DISK, SCSI_DISK, VIRTIO_DISK, IDE_FLOPPY, NVRAM, VTPM", diskType),
)
}
if isoUUID != "" && diskType != "IDE_CDROM" {
return diag.NewErrorDiagnostic(
"Invalid disk type",
fmt.Sprintf("Disk type '%s' is not compatible with ISO, for ISO attach action type of IDE_CDROM is needed.", diskType),
)
}
return nil
}

func ValidateISOAttach(restClient RestClient, isoUUID string, isAttachingISO bool) (diag.Diagnostic, *map[string]any) {
if isAttachingISO {
iso := GetISOByUUID(restClient, isoUUID)
if iso == nil {
return diag.NewErrorDiagnostic(
"Invalid ISO UUID",
fmt.Sprintf("ISO with UUID '%s' not found.", isoUUID),
),
nil
}
return nil, iso
}
return nil, nil
}

func ValidateDiskSize(diskUUID string, oldSize float64, newSize float64) diag.Diagnostic {
if newSize < oldSize {
return diag.NewErrorDiagnostic(
Expand Down
Loading