Skip to content

Commit

Permalink
Added ovirt_disk_resize_all resource
Browse files Browse the repository at this point in the history
  • Loading branch information
Janos Bonic committed Jun 9, 2022
1 parent 29ed65e commit ce54a35
Show file tree
Hide file tree
Showing 4 changed files with 297 additions and 0 deletions.
30 changes: 30 additions & 0 deletions docs/resources/vm_disks_resize.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "ovirt_vm_disks_resize Resource - terraform-provider-ovirt"
subcategory: ""
description: |-
The ovirtvmdisks_resize resource resizes all disks in an oVirt VM to the specified size.
~> Only use this resource with disks created from templates. Otherwise, two terraform resources will handle the same disk resource.
---

# ovirt_vm_disks_resize (Resource)

The ovirt_vm_disks_resize resource resizes all disks in an oVirt VM to the specified size.

~> Only use this resource with disks created from templates. Otherwise, two terraform resources will handle the same disk resource.



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

### Required

- `size` (Number) Disk size in bytes to set all disks to.
- `vm_id` (String) Resize all disks in this VM to the specified size.

### Read-Only

- `id` (String) The ID of this resource.


1 change: 1 addition & 0 deletions internal/ovirt/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ func (p *provider) getProvider() *schema.Provider {
"ovirt_vm_optimize_cpu_settings": p.vmOptimizeCPUSettingsResource(),
"ovirt_disk": p.diskResource(),
"ovirt_disk_resize": p.diskResizeResource(),
"ovirt_vm_disks_resize": p.vmDisksResizeResource(),
"ovirt_disk_from_image": p.diskFromImageResource(),
"ovirt_disk_attachment": p.diskAttachmentResource(),
"ovirt_disk_attachments": p.diskAttachmentsResource(),
Expand Down
138 changes: 138 additions & 0 deletions internal/ovirt/resource_ovirt_vm_disks_resize.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package ovirt

import (
"context"
"fmt"

"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 vmDisksResizeSchema = map[string]*schema.Schema{
"vm_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "Resize all disks in this VM to the specified size.",
ValidateDiagFunc: validateUUID,
},
"size": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
Description: "Disk size in bytes to set all disks to.",
ValidateDiagFunc: validateDiskSize,
},
}

func (p *provider) vmDisksResizeResource() *schema.Resource {
return &schema.Resource{
CreateContext: p.vmDisksResizeCreate,
ReadContext: p.vmDisksResizeRead,
DeleteContext: p.vmDisksResizeDelete,
Schema: vmDisksResizeSchema,
Description: `The ovirt_vm_disks_resize resource resizes all disks in an oVirt VM 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) vmDisksResizeCreate(
ctx context.Context,
data *schema.ResourceData,
_ interface{},
) diag.Diagnostics {
client := p.client.WithContext(ctx)
return resizeAllDisks(client, data)
}

func (p *provider) vmDisksResizeRead(ctx context.Context, data *schema.ResourceData, _ interface{}) diag.Diagnostics {
client := p.client.WithContext(ctx)

desiredSize := uint64(data.Get("size").(int))
size := desiredSize

vmID := ovirtclient.VMID(data.Get("vm_id").(string))

diskAttachments, err := client.ListDiskAttachments(vmID)
if err != nil {
return errorToDiags(fmt.Sprintf("list disk attachments of VM %s", vmID), err)
}
for _, diskAttachment := range diskAttachments {
disk, err := diskAttachment.Disk()
if err != nil {
return errorToDiags(fmt.Sprintf("get disk %s", diskAttachment.DiskID()), err)
}
if disk.ProvisionedSize() != desiredSize {
// Set the reported size to the size differing so the resource can be refreshed and the disks resized.
size = disk.ProvisionedSize()
}
}

data.SetId(string(vmID))
diags := diag.Diagnostics{}
diags = setResourceField(data, "size", size, diags)

return diags
}

func (p *provider) vmDisksResizeDelete(_ context.Context, data *schema.ResourceData, _ interface{}) diag.Diagnostics {
data.SetId("")
return nil
}

func resizeAllDisks(client ovirtclient.Client, data *schema.ResourceData) diag.Diagnostics {
vmID := ovirtclient.VMID(data.Get("vm_id").(string))
desiredSize := uint64(data.Get("size").(int))

diskAttachments, err := client.ListDiskAttachments(vmID)
if err != nil {
return errorToDiags(fmt.Sprintf("list disk attachments of VM %s", vmID), err)
}
var diags diag.Diagnostics
for _, diskAttachment := range diskAttachments {
disk, err := diskAttachment.Disk()
if err != nil {
return errorToDiags(fmt.Sprintf("get disk %s", diskAttachment.DiskID()), err)
}
if disk.ProvisionedSize() == desiredSize {
continue
}
params := ovirtclient.UpdateDiskParams()
if _, err := params.WithProvisionedSize(desiredSize); err != nil {
diags = append(
diags,
diag.Diagnostic{
Severity: diag.Error,
Summary: fmt.Sprintf("Failed to set parameters for updating disk %s size.", disk.ID()),
Detail: err.Error(),
},
)
continue
}
updateFailedDiag := diag.Diagnostic{
Severity: diag.Error,
Summary: fmt.Sprintf("Failed to update disk %s size.", disk.ID()),
}
diskUpdate, err := client.StartUpdateDisk(disk.ID(), params)
if err != nil {
updateFailedDiag.Detail = err.Error()
diags = append(diags, updateFailedDiag)
continue
}
_, err = diskUpdate.Wait()
if err != nil {
updateFailedDiag.Detail = err.Error()
diags = append(diags, updateFailedDiag)
continue
}
}

data.SetId(string(vmID))
if !diags.HasError() {
diags = setResourceField(data, "size", desiredSize, diags)
}
return diags
}
128 changes: 128 additions & 0 deletions internal/ovirt/resource_ovirt_vm_disks_resize_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package ovirt

import (
"context"
"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 TestVMDisksResize(t *testing.T) {
t.Parallel()

testData := []struct {
name string
diskCount int
startingDiskSize uint64
desiredDiskSize uint64
}{
{
"empty",
0,
uint64(1024 * 1024),
2 * uint64(1024*1024),
},
{
"single",
1,
uint64(1024 * 1024),
2 * uint64(1024*1024),
},
{
"double",
2,
uint64(1024 * 1024),
2 * uint64(1024*1024),
},
}

for _, testCase := range testData {
t.Run(
testCase.name, func(t *testing.T) {
p := newProvider(newTestLogger(t))

helper := p.getTestHelper()
client := helper.GetClient().WithContext(context.Background())
vm, err := client.CreateVM(
helper.GetClusterID(),
helper.GetBlankTemplateID(),
helper.GenerateTestResourceName(t),
nil,
)
if err != nil {
t.Fatal(err)
}

startingDiskSize := testCase.startingDiskSize
desiredDiskSize := testCase.desiredDiskSize

disks := make([]ovirtclient.Disk, testCase.diskCount)

for i := 0; i < testCase.diskCount; i++ {
disk, err := client.CreateDisk(
helper.GetStorageDomainID(),
ovirtclient.ImageFormatRaw,
startingDiskSize,
nil,
)
if err != nil {
t.Fatal(err)
}

_, err = client.CreateDiskAttachment(vm.ID(), disk.ID(), ovirtclient.DiskInterfaceVirtIO, nil)
if err != nil {
t.Fatal(err)
}

disks[i] = disk
}

config := fmt.Sprintf(
`
provider "ovirt" {
mock = true
}
resource "ovirt_vm_disks_resize" "resized" {
vm_id = "%s"
size = %d
}`,
vm.ID(),
desiredDiskSize,
)

resource.UnitTest(
t, resource.TestCase{
ProviderFactories: p.getProviderFactories(),
Steps: []resource.TestStep{
{
Config: config,
Check: func(state *terraform.State) error {
for _, disk := range disks {
disk, err := client.GetDisk(disk.ID())
if err != nil {
return err
}
if disk.ProvisionedSize() != desiredDiskSize {
return fmt.Errorf(
"incorrect disk size after apply: %d",
disk.ProvisionedSize(),
)
}
}
return nil
},
},
{
Config: config,
Destroy: true,
},
},
},
)
},
)
}
}

0 comments on commit ce54a35

Please sign in to comment.