diff --git a/docs/resources/disk_resize.md b/docs/resources/disk_resize.md new file mode 100644 index 00000000..37c6bca4 --- /dev/null +++ b/docs/resources/disk_resize.md @@ -0,0 +1,46 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "ovirt_disk_resize Resource - terraform-provider-ovirt" +subcategory: "" +description: |- + The ovirtdiskresize resource resizes disks in oVirt to the specified size. + ~> Only use this resource with disks created from templates. Otherwise, two terraform resources will handle the same disk resource. +--- + +# ovirt_disk_resize (Resource) + +The ovirt_disk_resize resource resizes disks in oVirt to the specified size. + +~> Only use this resource with disks created from templates. Otherwise, two terraform resources will handle the same disk resource. + +## Example Usage + +```terraform +# this data-source requires a VM created in another configuration and referenced here +data "ovirt_disk_attachments" "templated" { + vm_id = var.vm_id +} + +resource "ovirt_disk_resize" "resized" { + # looping through all the disk attachments + # using the attachment id (a.id) as key and the disk id (a.disk_id) as value + for_each = {for a in data.ovirt_disk_attachments.templated.attachments: a.id => a.disk_id} + + disk_id = "${each.value}" + size = 2*1048576 +} +``` + + +## Schema + +### Required + +- `disk_id` (String) ID of the disk to resize. +- `size` (Number) Disk size in bytes. + +### Read-Only + +- `id` (String) The ID of this resource. + + diff --git a/examples/resources/ovirt_disk_resize/provider.tf b/examples/resources/ovirt_disk_resize/provider.tf new file mode 100644 index 00000000..8fc30a35 --- /dev/null +++ b/examples/resources/ovirt_disk_resize/provider.tf @@ -0,0 +1,20 @@ +terraform { + required_providers { + ovirt = { + source = "ovirt/ovirt" + } + } + + required_version = ">= 0.15" +} + +provider "ovirt" { + url = var.url + username = var.username + password = var.password + tls_ca_bundle = var.tls_ca_bundle + tls_system = var.tls_system + tls_ca_dirs = var.tls_ca_dirs + tls_ca_files = var.tls_ca_files + tls_insecure = var.tls_insecure +} \ No newline at end of file diff --git a/examples/resources/ovirt_disk_resize/resource.tf b/examples/resources/ovirt_disk_resize/resource.tf new file mode 100644 index 00000000..2acde704 --- /dev/null +++ b/examples/resources/ovirt_disk_resize/resource.tf @@ -0,0 +1,13 @@ +# this data-source requires a VM created in another configuration and referenced here +data "ovirt_disk_attachments" "templated" { + vm_id = var.vm_id +} + +resource "ovirt_disk_resize" "resized" { + # looping through all the disk attachments + # using the attachment id (a.id) as key and the disk id (a.disk_id) as value + for_each = {for a in data.ovirt_disk_attachments.templated.attachments: a.id => a.disk_id} + + disk_id = "${each.value}" + size = 2*1048576 +} \ No newline at end of file diff --git a/examples/resources/ovirt_disk_resize/variables.tf b/examples/resources/ovirt_disk_resize/variables.tf new file mode 100644 index 00000000..1e77cb25 --- /dev/null +++ b/examples/resources/ovirt_disk_resize/variables.tf @@ -0,0 +1,39 @@ +variable "vm_id" { + type = string + description = "ID of the oVirt VM for which the disks are resized." +} + +variable "username" { + type = string +} +variable "password" { + type = string +} +variable "url" { + type = string +} +variable "tls_ca_files" { + type = list(string) + default = [] +} +variable "tls_ca_dirs" { + type = list(string) + default = [] +} +variable "tls_insecure" { + type = bool + default = false +} +variable "tls_ca_bundle" { + type = string + default = "" +} +variable "tls_system" { + type = bool + default = true + description = "Take TLS CA certificates from system root. Does not work on Windows." +} +variable "mock" { + type = bool + default = true +} \ No newline at end of file diff --git a/internal/ovirt/provider.go b/internal/ovirt/provider.go index b981b6da..b0988bac 100644 --- a/internal/ovirt/provider.go +++ b/internal/ovirt/provider.go @@ -123,6 +123,7 @@ func (p *provider) getProvider() *schema.Provider { "ovirt_vm_tag": p.vmTagResource(), "ovirt_vm_optimize_cpu_settings": p.vmOptimizeCPUSettingsResource(), "ovirt_disk": p.diskResource(), + "ovirt_disk_resize": p.diskResizeResource(), "ovirt_disk_from_image": p.diskFromImageResource(), "ovirt_disk_attachment": p.diskAttachmentResource(), "ovirt_disk_attachments": p.diskAttachmentsResource(), diff --git a/internal/ovirt/resource_ovirt_disk_resize.go b/internal/ovirt/resource_ovirt_disk_resize.go new file mode 100644 index 00000000..5c4537fc --- /dev/null +++ b/internal/ovirt/resource_ovirt_disk_resize.go @@ -0,0 +1,119 @@ +package ovirt + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + ovirtclient "github.com/ovirt/go-ovirt-client" +) + +var diskResizeSchema = map[string]*schema.Schema{ + "disk_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "ID of the disk to resize.", + ValidateDiagFunc: validateUUID, + }, + "size": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + Description: "Disk size in bytes.", + ValidateDiagFunc: validateDiskSize, + }, +} + +func (p *provider) diskResizeResource() *schema.Resource { + return &schema.Resource{ + CreateContext: p.diskResizeCreate, + ReadContext: p.diskResizeRead, + DeleteContext: p.diskResizeDelete, + Schema: diskResizeSchema, + Description: `The ovirt_disk_resize resource resizes disks in oVirt to the specified size. + +~> Only use this resource with disks created from templates. Otherwise, two terraform resources will handle the same disk resource. + `, + } +} + +func (p *provider) diskResizeCreate( + ctx context.Context, + data *schema.ResourceData, + _ interface{}, +) diag.Diagnostics { + client := p.client.WithContext(ctx) + return resizeDisk(client, data) +} + +func (p *provider) diskResizeRead(ctx context.Context, data *schema.ResourceData, _ interface{}) diag.Diagnostics { + client := p.client.WithContext(ctx) + + diskID := data.Get("disk_id").(string) + disk, err := client.GetDisk(ovirtclient.DiskID(diskID)) + if err != nil { + return diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Error, + Summary: "Failed to retrieve disk.", + Detail: err.Error(), + }, + } + } + + data.SetId(diskID) + diags := diag.Diagnostics{} + diags = setResourceField(data, "size", disk.ProvisionedSize(), diags) + + return diags +} + +func (p *provider) diskResizeDelete(_ context.Context, data *schema.ResourceData, _ interface{}) diag.Diagnostics { + data.SetId("") + return nil +} + +func resizeDisk(client ovirtclient.Client, data *schema.ResourceData) diag.Diagnostics { + diskID := data.Get("disk_id").(string) + newSize := data.Get("size").(int) + + params := ovirtclient.UpdateDiskParams() + _, err := params.WithProvisionedSize(uint64(newSize)) + if err != nil { + return diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Error, + Summary: "Failed to set parameters for updating disk size.", + Detail: err.Error(), + }, + } + } + + updateFailedDiag := diag.Diagnostic{ + Severity: diag.Error, + Summary: "Failed to update disk size.", + } + diskUpdate, err := client.StartUpdateDisk(ovirtclient.DiskID(diskID), params) + if err != nil { + if isNotFound(err) { + data.SetId("") + } + updateFailedDiag.Detail = err.Error() + return diag.Diagnostics{updateFailedDiag} + } + _, err = diskUpdate.Wait() + if err != nil { + if isNotFound(err) { + data.SetId("") + } + updateFailedDiag.Detail = err.Error() + return diag.Diagnostics{updateFailedDiag} + } + + data.SetId(diskID) + diags := diag.Diagnostics{} + diags = setResourceField(data, "size", newSize, diags) + + return diags +} diff --git a/internal/ovirt/resource_ovirt_disk_resize_test.go b/internal/ovirt/resource_ovirt_disk_resize_test.go new file mode 100644 index 00000000..bbd241e2 --- /dev/null +++ b/internal/ovirt/resource_ovirt_disk_resize_test.go @@ -0,0 +1,55 @@ +package ovirt + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + ovirtclient "github.com/ovirt/go-ovirt-client" +) + +func TestDiskResizeResource(t *testing.T) { + t.Parallel() + + p := newProvider(newTestLogger(t)) + + helper := p.getTestHelper() + disk, err := helper.GetClient().CreateDisk( + helper.GetStorageDomainID(), ovirtclient.ImageFormatRaw, 1048576, + ovirtclient.CreateDiskParams().MustWithAlias("TestDisk").MustWithSparse(true)) + if err != nil { + t.Fatal(err) + } + + resource.UnitTest(t, resource.TestCase{ + ProviderFactories: p.getProviderFactories(), + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(` + provider "ovirt" { + mock = true + } + resource "ovirt_disk_resize" "resized" { + disk_id = "%s" + size = 2*1048576 + }`, + disk.ID(), + ), + Check: resource.ComposeTestCheckFunc( + func(state *terraform.State) error { + diskID := state.RootModule().Resources["ovirt_disk_resize.resized"].Primary.ID + disk, err := p.getTestHelper().GetClient().GetDisk(ovirtclient.DiskID(diskID)) + if err != nil { + return err + } + if disk.ProvisionedSize() != 2097152 { + return fmt.Errorf("Expected disk size to be 2097152, but got %d", disk.ProvisionedSize()) + } + return nil + }, + ), + }, + }, + }) +}