Skip to content

Fix node affinity #64

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 2 commits into from
May 22, 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
2 changes: 1 addition & 1 deletion demo/sc_demo_vm.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# After we have virtual disk, we use it to create new VM from it
# First create VM without any disk.
resource "hypercore_vm" "demo_vm" {
group = "testtf"
tags = ["testtf"]
name = local.vm_name
description = "Demo Ana's cloned VM"
vcpu = 4
Expand Down
13 changes: 8 additions & 5 deletions docs/resources/vm.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ resource "hypercore_vm" "empty-vm" {
name = "empty-vm"
description = "some description"

vcpu = 4
memory = 4096 # MiB
vcpu = 4
memory = 4096 # MiB
affinity_strategy = {}
}

data "hypercore_vms" "clone_source_vm" {
Expand All @@ -55,6 +56,7 @@ resource "hypercore_vm" "myvm" {

vcpu = 4
memory = 4096 # MiB
affinity_strategy = {}
snapshot_schedule_uuid = data.hypercore_vms.clone_source_vm.vms.0.snapshot_schedule_uuid

clone = {
Expand All @@ -76,8 +78,9 @@ resource "hypercore_vm" "import-from-smb" {
name = "imported-vm"
description = "some description"

vcpu = 4
memory = 4096 # MiB
vcpu = 4
memory = 4096 # MiB
affinity_strategy = {}

import = {
server = "10.5.11.39"
Expand All @@ -102,7 +105,7 @@ output "vm_uuid" {

### Optional

- `affinity_strategy` (Object) VM node affinity. (see [below for nested schema](#nestedatt--affinity_strategy))
- `affinity_strategy` (Attributes) (see [below for nested schema](#nestedatt--affinity_strategy))
- `clone` (Attributes) Clone options if the VM is being created as a clone. The `source_vm_uuid` is the UUID of the VM used for cloning, <br>`user_data` and `meta_data` are used for the cloud init data. (see [below for nested schema](#nestedatt--clone))
- `description` (String) Description of this VM
- `import` (Attributes) Options for importing a VM through a SMB server or some other HTTP location. <br>Use server, username, password for SMB or http_uri for some other HTTP location. Parameters path and file_name are always **required** (see [below for nested schema](#nestedatt--import))
Expand Down
11 changes: 7 additions & 4 deletions examples/resources/hypercore_vm/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ resource "hypercore_vm" "empty-vm" {
name = "empty-vm"
description = "some description"

vcpu = 4
memory = 4096 # MiB
vcpu = 4
memory = 4096 # MiB
affinity_strategy = {}
}

data "hypercore_vms" "clone_source_vm" {
Expand All @@ -24,6 +25,7 @@ resource "hypercore_vm" "myvm" {

vcpu = 4
memory = 4096 # MiB
affinity_strategy = {}
snapshot_schedule_uuid = data.hypercore_vms.clone_source_vm.vms.0.snapshot_schedule_uuid

clone = {
Expand All @@ -45,8 +47,9 @@ resource "hypercore_vm" "import-from-smb" {
name = "imported-vm"
description = "some description"

vcpu = 4
memory = 4096 # MiB
vcpu = 4
memory = 4096 # MiB
affinity_strategy = {}

import = {
server = "10.5.11.39"
Expand Down
89 changes: 56 additions & 33 deletions internal/provider/hypercore_vm_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/objectdefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
Expand All @@ -41,16 +41,16 @@ type HypercoreVMResource struct {

// HypercoreVMResourceModel describes the resource data model.
type HypercoreVMResourceModel struct {
Tags types.List `tfsdk:"tags"`
Name types.String `tfsdk:"name"`
Description types.String `tfsdk:"description"`
VCPU types.Int32 `tfsdk:"vcpu"`
Memory types.Int64 `tfsdk:"memory"`
Import *ImportModel `tfsdk:"import"`
SnapshotScheduleUUID types.String `tfsdk:"snapshot_schedule_uuid"`
Clone *CloneModel `tfsdk:"clone"`
AffinityStrategy AffinityStrategyModel `tfsdk:"affinity_strategy"`
Id types.String `tfsdk:"id"`
Tags types.List `tfsdk:"tags"`
Name types.String `tfsdk:"name"`
Description types.String `tfsdk:"description"`
VCPU types.Int32 `tfsdk:"vcpu"`
Memory types.Int64 `tfsdk:"memory"`
Import *ImportModel `tfsdk:"import"`
SnapshotScheduleUUID types.String `tfsdk:"snapshot_schedule_uuid"`
Clone *CloneModel `tfsdk:"clone"`
AffinityStrategy *AffinityStrategyModel `tfsdk:"affinity_strategy"`
Id types.String `tfsdk:"id"`
}

type ImportModel struct {
Expand Down Expand Up @@ -173,29 +173,35 @@ The provider will currently try to shutdown VM only before VM delete.`,
},
},
},
"affinity_strategy": schema.ObjectAttribute{
MarkdownDescription: "VM node affinity.",
Optional: true,
AttributeTypes: map[string]attr.Type{
"strict_affinity": types.BoolType,
"preferred_node_uuid": types.StringType,
"backup_node_uuid": types.StringType,
},
"affinity_strategy": schema.SingleNestedAttribute{
Optional: true,
Computed: true,
Default: objectdefault.StaticValue(
types.ObjectValueMust(
map[string]attr.Type{
"strict_affinity": types.BoolType,
"preferred_node_uuid": types.StringType,
"backup_node_uuid": types.StringType,
Attributes: map[string]schema.Attribute{
"strict_affinity": schema.BoolAttribute{
Optional: true,
Computed: true,
//Default: booldefault.StaticBool(false),
PlanModifiers: []planmodifier.Bool{
boolplanmodifier.UseStateForUnknown(),
},
map[string]attr.Value{
"strict_affinity": types.BoolValue(false),
"preferred_node_uuid": types.StringValue(""),
"backup_node_uuid": types.StringValue(""),
},
"preferred_node_uuid": schema.StringAttribute{
Optional: true,
Computed: true,
// Default: stringdefault.StaticString(""),
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
"backup_node_uuid": schema.StringAttribute{
Optional: true,
Computed: true,
// Default: stringdefault.StaticString(""),
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
),
),
},
},
},
"id": schema.StringAttribute{
Computed: true,
Expand Down Expand Up @@ -357,13 +363,30 @@ func (r *HypercoreVMResource) Create(ctx context.Context, req resource.CreateReq

// Read Terraform plan data into the model
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
// tflog.Info(ctx, fmt.Sprintf("TTRT a ----------------------- : %v", data.AffinityStrategy))
if data.AffinityStrategy == nil {
data.AffinityStrategy = &AffinityStrategyModel{
StrictAffinity: types.BoolValue(false),
PreferredNodeUUID: types.StringValue(""),
BackupNodeUUID: types.StringValue(""),
}
}
if data.AffinityStrategy.StrictAffinity.IsUnknown() {
data.AffinityStrategy.StrictAffinity = types.BoolValue(false)
}
if data.AffinityStrategy.PreferredNodeUUID.IsUnknown() {
data.AffinityStrategy.PreferredNodeUUID = types.StringValue("")
}
if data.AffinityStrategy.BackupNodeUUID.IsUnknown() {
data.AffinityStrategy.BackupNodeUUID = types.StringValue("")
}
// tflog.Info(ctx, fmt.Sprintf("TTRT b ----------------------- : %v", data.AffinityStrategy))

if r.client == nil {
resp.Diagnostics.AddError(
"Unconfigured HTTP Client",
"Expected configured HTTP client. Please report this issue to the provider developers.",
)

return
}

Expand Down Expand Up @@ -457,6 +480,7 @@ func (r *HypercoreVMResource) Read(ctx context.Context, req resource.ReadRequest
data.SnapshotScheduleUUID = types.StringValue(utils.AnyToString(hc3_vm["snapshotScheduleUUID"]))

affinityStrategy := utils.AnyToMap(hc3_vm["affinityStrategy"])
data.AffinityStrategy = &AffinityStrategyModel{}
data.AffinityStrategy.StrictAffinity = types.BoolValue(utils.AnyToBool(affinityStrategy["strictAffinity"]))
data.AffinityStrategy.PreferredNodeUUID = types.StringValue(utils.AnyToString(affinityStrategy["preferredNodeUUID"]))
data.AffinityStrategy.BackupNodeUUID = types.StringValue(utils.AnyToString(affinityStrategy["backupNodeUUID"]))
Expand All @@ -477,7 +501,6 @@ func (r *HypercoreVMResource) Update(ctx context.Context, req resource.UpdateReq

// Read Terraform plan data into the model
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ resource "hypercore_vm" "test" {
memory = 4096
description = "testtf-vm-description"
// snapshot_schedule_uuid = ""
affinity_strategy = {}
}
`, vm_name)
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ resource "hypercore_vm" "test" {
meta_data = ""
preserve_mac_address = false
}
affinity_strategy = {}
}
`, vm_name, source_vm_uuid, requested_power_state)
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ resource "hypercore_vm" "test" {
path = %[5]q
file_name = %[6]q
}
affinity_strategy = {}
}
`, vm_name, smb_server, smb_username, smb_password, smb_path, smb_filename, requested_power_state)
}
42 changes: 24 additions & 18 deletions local/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,36 @@ terraform {
}

locals {
vm_name = "testtf-justin-nic-mac"
src_vm_name = "testtf-src-empty"
vm_name = "testtf-justin-affinity"
}

provider "hypercore" {}

data "hypercore_vms" "myvm" {
name = local.vm_name
}

resource "hypercore_nic" "nic_newly_created" {
vm_uuid = data.hypercore_vms.myvm.vms.0.uuid
type = "INTEL_E1000"
vlan = 11
data "hypercore_vms" "srcvm" {
name = local.src_vm_name
}

resource "hypercore_nic" "nic_imported" {
vm_uuid = data.hypercore_vms.myvm.vms.0.uuid
type = "VIRTIO"
vlan = 0

depends_on = [hypercore_nic.nic_newly_created]
resource "hypercore_vm" "myvm" {
name = local.vm_name
clone = {
source_vm_uuid = data.hypercore_vms.srcvm.vms.0.uuid
user_data = ""
meta_data = ""
}
# TODO - are computed, on HC3 side
memory = 1024
tags = [""]
vcpu = 1
description = ""
affinity_strategy = {
# strict_affinity = true
# preferred_node_uuid = "d676b39c-595f-4c3b-a8df-a18f308243c0"
}
}

import {
to = hypercore_nic.nic_imported
id = format("%s:%s:%d", data.hypercore_vms.myvm.vms.0.uuid, "VIRTIO", 0)
resource "hypercore_vm_power_state" "myvm" {
vm_uuid = hypercore_vm.myvm.id
# state = "SHUTOFF" # available states are: SHUTOFF, RUNNING, PAUSED
state = "RUNNING" # available states are: SHUTOFF, RUNNING, PAUSED
}
Loading