Skip to content

Support mapping compute & login instances to Ironic nodes #573

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
Feb 13, 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env python
""" opentofu external data program to list baremetal nodes

Example usage:

data "external" "example" {
program = [this_file]
}

The external data resource's result attribute then contains a mapping of
Ironic node names to their UUIDs.

An empty list is returned if:
- There are no baremetal nodes
- The listing fails for any reason, e.g.
- there is no baremetal service
- admin credentials are required and are not provided
"""

import openstack
import json

nodes = []
proxy = None
output = {}
conn = openstack.connection.from_config()
try:
proxy = getattr(conn, 'baremetal', None)
except Exception:
pass
if proxy is not None:
nodes = proxy.nodes()
for node in nodes:
output[node.name] = node.id
print(json.dumps(output))
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,19 @@ module "compute" {
volume_backed_instances = lookup(each.value, "volume_backed_instances", var.volume_backed_instances)
root_volume_size = lookup(each.value, "root_volume_size", var.root_volume_size)

# optionally set for group
# optionally set for group:
networks = concat(var.cluster_networks, lookup(each.value, "extra_networks", []))
extra_volumes = lookup(each.value, "extra_volumes", {})
compute_init_enable = lookup(each.value, "compute_init_enable", [])
ignore_image_changes = lookup(each.value, "ignore_image_changes", false)
match_ironic_node = lookup(each.value, "match_ironic_node", false)
availability_zone = lookup(each.value, "availability_zone", "nova")

# computed
k3s_token = local.k3s_token
# not using openstack_compute_instance_v2.control.access_ip_v4 to avoid
# updates to node metadata on deletion/recreation of the control node:
control_address = openstack_networking_port_v2.control[var.cluster_networks[0].network].all_fixed_ips[0]
security_group_ids = [for o in data.openstack_networking_secgroup_v2.nonlogin: o.id]
baremetal_nodes = data.external.baremetal_nodes.result
}
13 changes: 13 additions & 0 deletions environments/skeleton/{{cookiecutter.environment}}/tofu/data.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
data "external" "inventory_secrets" {
program = ["${path.module}/read-inventory-secrets.py"]

query = {
path = var.inventory_secrets_path == "" ? "${path.module}/../inventory/group_vars/all/secrets.yml" : var.inventory_secrets_path
}
}

data "external" "baremetal_nodes" {
# returns an empty map if cannot list baremetal nodes
program = ["${path.module}/baremetal-node-list.py"]
query = {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ module "login" {
extra_volumes = lookup(each.value, "extra_volumes", {})
fip_addresses = lookup(each.value, "fip_addresses", [])
fip_network = lookup(each.value, "fip_network", "")
match_ironic_node = lookup(each.value, "match_ironic_node", false)
availability_zone = lookup(each.value, "availability_zone", "nova")

# can't be set for login
compute_init_enable = []
Expand All @@ -36,4 +38,5 @@ module "login" {
# updates to node metadata on deletion/recreation of the control node:
control_address = openstack_networking_port_v2.control[var.cluster_networks[0].network].all_fixed_ips[0]
security_group_ids = [for o in data.openstack_networking_secgroup_v2.login: o.id]
baremetal_nodes = data.external.baremetal_nodes.result
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ resource "openstack_compute_instance_v2" "compute_fixed_image" {
fqdn: ${var.cluster_name}-${each.key}.${var.cluster_name}.${var.cluster_domain_suffix}
EOF

availability_zone = var.match_ironic_node ? "${var.availability_zone}::${var.baremetal_nodes[each.key]}" : null

lifecycle {
ignore_changes = [
image_id,
Expand Down Expand Up @@ -140,7 +142,7 @@ resource "openstack_compute_instance_v2" "compute" {
k3s_token = var.k3s_token
control_address = var.control_address
access_ip = openstack_networking_port_v2.compute["${each.key}-${var.networks[0].network}"].all_fixed_ips[0]
},
},
{for e in var.compute_init_enable: e => true}
)

Expand All @@ -149,6 +151,8 @@ resource "openstack_compute_instance_v2" "compute" {
fqdn: ${var.cluster_name}-${each.key}.${var.cluster_name}.${var.cluster_domain_suffix}
EOF

availability_zone = var.match_ironic_node ? "${var.availability_zone}::${var.baremetal_nodes[each.key]}" : null

}

resource "openstack_networking_floatingip_associate_v2" "fip" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,20 @@ variable "fip_network" {
EOT
default = ""
}

variable "match_ironic_node" {
type = bool
description = "Whether to launch instances on the Ironic node of the same name as each cluster node"
default = false
}

variable "availability_zone" {
type = string
description = "Name of availability zone - ignored unless match_ironic_node is true"
default = "nova"
}

variable "baremetal_nodes" {
type = map(string)
default = {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ variable "login" {
fip_network: Name of network containing ports to attach FIPs to. Only
required if multiple networks are defined.

match_ironic_node: Set true to launch instances on the Ironic node of the same name as each cluster node
availability_zone: Name of availability zone - ignored unless match_ironic_node is true (default: "nova")
EOF
}

Expand Down Expand Up @@ -93,6 +95,8 @@ variable "compute" {
Values are a mapping with:
size: Size of volume in GB
**NB**: The order in /dev is not guaranteed to match the mapping
match_ironic_node: Set true to launch instances on the Ironic node of the same name as each cluster node
availability_zone: Name of availability zone - ignored unless match_ironic_node is true (default: "nova")
EOF
}

Expand Down Expand Up @@ -186,14 +190,6 @@ variable "inventory_secrets_path" {
default = ""
}

data "external" "inventory_secrets" {
program = ["${path.module}/read-inventory-secrets.py"]

query = {
path = var.inventory_secrets_path == "" ? "${path.module}/../inventory/group_vars/all/secrets.yml" : var.inventory_secrets_path
}
}

locals {
k3s_token = data.external.inventory_secrets.result["vault_k3s_token"]
}