diff --git a/docs/resources/disk.md b/docs/resources/disk.md
index fbd406a..41529e2 100644
--- a/docs/resources/disk.md
+++ b/docs/resources/disk.md
@@ -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`
diff --git a/docs/resources/iso.md b/docs/resources/iso.md
new file mode 100644
index 0000000..7746c41
--- /dev/null
+++ b/docs/resources/iso.md
@@ -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.
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
+
+### 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
diff --git a/examples/resources/hypercore_iso/resource.tf b/examples/resources/hypercore_iso/resource.tf
index 76635bf..0bfa74c 100644
--- a/examples/resources/hypercore_iso/resource.tf
+++ b/examples/resources/hypercore_iso/resource.tf
@@ -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"
@@ -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
+}
diff --git a/internal/provider/hypercore_disk_resource.go b/internal/provider/hypercore_disk_resource.go
index a0ebc14..59a5462 100644
--- a/internal/provider/hypercore_disk_resource.go
+++ b/internal/provider/hypercore_disk_resource.go
@@ -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) {
@@ -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,
+ },
},
}
}
@@ -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 != "" {
@@ -164,6 +178,7 @@ func (r *HypercoreDiskResource) Create(ctx context.Context, req resource.CreateR
"capacity": originalVDSizeBytes,
},
}
+
diskUUID, disk = utils.AttachVirtualDisk(
*r.client,
attachPayload,
@@ -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",
@@ -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())
diff --git a/internal/utils/vm_disk.go b/internal/utils/vm_disk.go
index 1b0f695..f37d320 100644
--- a/internal/utils/vm_disk.go
+++ b/internal/utils/vm_disk.go
@@ -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(