Skip to content

Commit 9141d4c

Browse files
Merge pull request #15 from domendobnikar/main
ISO attach logic
2 parents b1300e4 + e58bb55 commit 9141d4c

File tree

5 files changed

+139
-6
lines changed

5 files changed

+139
-6
lines changed

docs/resources/disk.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ import {
5555

5656
### Optional
5757

58+
- `iso_uuid` (String) ISO UUID we want to attach to the disk, only available with disk type IDE_CDROM.
5859
- `size` (Number) Disk size in `GB`. Must be larger than the current size of the disk if specified.
5960
- `source_virtual_disk_id` (String) UUID of the virtual disk to use to clone and attach to the VM.
6061
- `type` (String) Disk type. Can be: `IDE_DISK`, `SCSI_DISK`, `VIRTIO_DISK`, `IDE_FLOPPY`, `NVRAM`, `VTPM`

docs/resources/iso.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "hypercore_iso Resource - hypercore"
4+
subcategory: ""
5+
description: |-
6+
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.
7+
---
8+
9+
# hypercore_iso (Resource)
10+
11+
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`.
12+
13+
## Example Usage
14+
15+
```terraform
16+
locals {
17+
vm_name = "myvm"
18+
}
19+
20+
data "hypercore_vm" "isovm" {
21+
name = local.vm_name
22+
}
23+
24+
// Upload ISO from local machine
25+
resource "hypercore_iso" "iso_upload_local" {
26+
name = "testiso-local.iso"
27+
source_url = "file:////home/bla/Downloads/mytestiso.iso"
28+
}
29+
30+
// Upload ISO from remote machine/storage
31+
resource "hypercore_iso" "iso_upload_from_url" {
32+
name = "testiso-remote.iso"
33+
source_url = "https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/aarch64/alpine-virt-3.21.3-aarch64.iso"
34+
}
35+
36+
37+
output "uploaded_iso_LOCAL" {
38+
value = hypercore_iso.iso_upload_local
39+
}
40+
41+
output "uploaded_iso_EXTERNAL" {
42+
value = hypercore_iso.iso_upload_from_url
43+
}
44+
45+
// We can then use this ISO for IDE_CDROM disk
46+
resource "hypercore_disk" "iso_attach" {
47+
vm_uuid = local.vm_name
48+
type = "IDE_CDROM"
49+
iso_uuid = hypercore_iso.iso_upload_local.id
50+
}
51+
52+
output "iso_attach" {
53+
value = hypercore_disk.iso_attach
54+
}
55+
```
56+
57+
<!-- schema generated by tfplugindocs -->
58+
## Schema
59+
60+
### Required
61+
62+
- `name` (String) Desired name of the ISO to upload. ISO name must end with '.iso'.
63+
64+
### Optional
65+
66+
- `source_url` (String) Source URL from where to fetch that disk from. URL can start with: `http://`, `https://`, `file:///`
67+
68+
### Read-Only
69+
70+
- `id` (String) ISO identifier

examples/resources/hypercore_iso/resource.tf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ data "hypercore_vm" "isovm" {
66
name = local.vm_name
77
}
88

9+
// Upload ISO from local machine
910
resource "hypercore_iso" "iso_upload_local" {
1011
name = "testiso-local.iso"
1112
source_url = "file:////home/bla/Downloads/mytestiso.iso"
1213
}
1314

15+
// Upload ISO from remote machine/storage
1416
resource "hypercore_iso" "iso_upload_from_url" {
1517
name = "testiso-remote.iso"
1618
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" {
2527
value = hypercore_iso.iso_upload_from_url
2628
}
2729

30+
// We can then use this ISO for IDE_CDROM disk
31+
resource "hypercore_disk" "iso_attach" {
32+
vm_uuid = local.vm_name
33+
type = "IDE_CDROM"
34+
iso_uuid = hypercore_iso.iso_upload_local.id
35+
}
36+
37+
output "iso_attach" {
38+
value = hypercore_disk.iso_attach
39+
}

internal/provider/hypercore_disk_resource.go

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type HypercoreDiskResourceModel struct {
3939
Type types.String `tfsdk:"type"`
4040
Size types.Float64 `tfsdk:"size"`
4141
SourceVirtualDiskID types.String `tfsdk:"source_virtual_disk_id"`
42+
IsoUUID types.String `tfsdk:"iso_uuid"`
4243
}
4344

4445
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
7980
MarkdownDescription: "UUID of the virtual disk to use to clone and attach to the VM.",
8081
Optional: true,
8182
},
83+
"iso_uuid": schema.StringAttribute{
84+
MarkdownDescription: "ISO UUID we want to attach to the disk, only available with disk type IDE_CDROM.",
85+
Optional: true,
86+
},
8287
},
8388
}
8489
}
@@ -128,20 +133,29 @@ func (r *HypercoreDiskResource) Create(ctx context.Context, req resource.CreateR
128133

129134
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()))
130135

131-
diagDiskType := utils.ValidateDiskType(data.Type.ValueString())
136+
var diskUUID string
137+
var disk map[string]any
138+
isAttachingISO := data.IsoUUID.ValueString() != ""
139+
140+
diagDiskType := utils.ValidateDiskType(data.Type.ValueString(), data.IsoUUID.ValueString())
132141
if diagDiskType != nil {
133142
resp.Diagnostics.AddError(diagDiskType.Summary(), diagDiskType.Detail())
134143
return
135144
}
145+
diagISOAttach, iso := utils.ValidateISOAttach(*r.client, data.IsoUUID.ValueString(), isAttachingISO)
146+
if diagISOAttach != nil {
147+
resp.Diagnostics.AddError(diagISOAttach.Summary(), diagISOAttach.Detail())
148+
return
149+
}
136150

137151
createPayload := map[string]any{
138152
"virDomainUUID": data.VmUUID.ValueString(),
139153
"type": data.Type.ValueString(),
140154
"capacity": data.Size.ValueFloat64() * 1000 * 1000 * 1000, // GB to B
141155
}
142-
143-
var diskUUID string
144-
var disk map[string]any
156+
if isAttachingISO {
157+
createPayload["path"] = (*iso)["path"]
158+
}
145159

146160
sourceVirtualDiskID := data.SourceVirtualDiskID.ValueString()
147161
if sourceVirtualDiskID != "" {
@@ -164,6 +178,7 @@ func (r *HypercoreDiskResource) Create(ctx context.Context, req resource.CreateR
164178
"capacity": originalVDSizeBytes,
165179
},
166180
}
181+
167182
diskUUID, disk = utils.AttachVirtualDisk(
168183
*r.client,
169184
attachPayload,
@@ -257,6 +272,8 @@ func (r *HypercoreDiskResource) Update(ctx context.Context, req resource.UpdateR
257272
restClient := *r.client
258273
diskUUID := data.Id.ValueString()
259274
vmUUID := data.VmUUID.ValueString()
275+
isAttachingISO := data.IsoUUID.ValueString() != ""
276+
260277
tflog.Debug(
261278
ctx, fmt.Sprintf(
262279
"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
287304
}
288305

289306
// Validate the type
290-
diagDiskType := utils.ValidateDiskType(data.Type.ValueString())
307+
diagDiskType := utils.ValidateDiskType(data.Type.ValueString(), data.IsoUUID.String())
291308
if diagDiskType != nil {
292309
resp.Diagnostics.AddError(diagDiskType.Summary(), diagDiskType.Detail())
293310
return
294311
}
312+
diagISOAttach, iso := utils.ValidateISOAttach(*r.client, data.IsoUUID.ValueString(), isAttachingISO)
313+
if diagISOAttach != nil {
314+
resp.Diagnostics.AddError(diagISOAttach.Summary(), diagISOAttach.Detail())
315+
return
316+
}
317+
318+
isDetachingISO := oldHc3Disk["path"] != "" && data.IsoUUID.ValueString() == "" && data.Type.ValueString() == "IDE_CDROM"
295319

296320
updatePayload := map[string]any{
297321
"virDomainUUID": vmUUID,
298322
"type": data.Type.ValueString(),
299323
"capacity": data.Size.ValueFloat64() * 1000 * 1000 * 1000, // GB to B
300324
}
325+
if isAttachingISO {
326+
updatePayload["path"] = (*iso)["path"]
327+
} else if isDetachingISO {
328+
updatePayload["path"] = ""
329+
}
301330
diag := utils.UpdateDisk(restClient, diskUUID, updatePayload, ctx)
302331
if diag != nil {
303332
resp.Diagnostics.AddWarning(diag.Summary(), diag.Detail())

internal/utils/vm_disk.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,16 +311,37 @@ func CreateDisk(
311311
return diskUUID, *disk
312312
}
313313

314-
func ValidateDiskType(diskType string) diag.Diagnostic {
314+
func ValidateDiskType(diskType string, isoUUID string) diag.Diagnostic {
315315
if !ALLOWED_DISK_TYPES[diskType] {
316316
return diag.NewErrorDiagnostic(
317317
"Invalid disk type",
318318
fmt.Sprintf("Disk type '%s' not allowed. Allowed types are: IDE_DISK, SCSI_DISK, VIRTIO_DISK, IDE_FLOPPY, NVRAM, VTPM", diskType),
319319
)
320320
}
321+
if isoUUID != "" && diskType != "IDE_CDROM" {
322+
return diag.NewErrorDiagnostic(
323+
"Invalid disk type",
324+
fmt.Sprintf("Disk type '%s' is not compatible with ISO, for ISO attach action type of IDE_CDROM is needed.", diskType),
325+
)
326+
}
321327
return nil
322328
}
323329

330+
func ValidateISOAttach(restClient RestClient, isoUUID string, isAttachingISO bool) (diag.Diagnostic, *map[string]any) {
331+
if isAttachingISO {
332+
iso := GetISOByUUID(restClient, isoUUID)
333+
if iso == nil {
334+
return diag.NewErrorDiagnostic(
335+
"Invalid ISO UUID",
336+
fmt.Sprintf("ISO with UUID '%s' not found.", isoUUID),
337+
),
338+
nil
339+
}
340+
return nil, iso
341+
}
342+
return nil, nil
343+
}
344+
324345
func ValidateDiskSize(diskUUID string, oldSize float64, newSize float64) diag.Diagnostic {
325346
if newSize < oldSize {
326347
return diag.NewErrorDiagnostic(

0 commit comments

Comments
 (0)