Manage Machines using Terraform

Hello,
I’m trying to create a infra to run k8s cluster on top of my metal.
The hardware is virtualized/hosted on vSphare. The OS has been provisioned to the ubuntu VM/hosts using Maas ( GUI )
What I want to do is to have the Maschines in terraform to be able to provision rke2 cluster nodes using Rancher. Rancher is able to interact with Terraform but I’m not sure how the resources should be defined in Terraform ( provider ) to be visible as a resources in the code for futhure to be able to manage the infra by Terraform provsioned by MAAS.

As I have machine:

 maas admin  machines read hostname=worker3
Success.
Machine-readable output follows:
[
    {
        "blockdevice_set": [
            {
                "firmware_version": "2.0",
                "partitions": [
                    {
                        "uuid": "7f057f3f-eb00-42d7-959a-5ba3798bcf97",
                        "size": 214739976192,
                        "bootable": false,
                        "tags": [],
                        "id": 2,
                        "used_for": "ext4 formatted filesystem mounted at /",
                        "type": "partition",
                        "device_id": 3,
                        "path": "/dev/disk/by-dname/sda-part2",
                        "system_id": "ny7qpr",
                        "filesystem": {
                            "fstype": "ext4",
                            "label": "root",
                            "uuid": "bb51fe18-4092-4600-a4a6-3c09bcec1236",
                            "mount_point": "/",
                            "mount_options": null
                        },
                        "resource_uri": "/MAAS/api/2.0/nodes/ny7qpr/blockdevices/3/partition/2"
                    }
                ],
                "type": "physical",
                "model": "Virtual disk",
                "id": 3,
                "id_path": "/dev/sda",
                "used_for": "GPT partitioned with 1 partition",
                "tags": [
                    "ssd"
                ],
                "filesystem": null,
                "storage_pool": null,
                "available_size": 0,
                "path": "/dev/disk/by-dname/sda",
                "uuid": null,
                "serial": "",
                "partition_table_type": "GPT",
                "size": 214748364800,
                "used_size": 214746267648,
                "block_size": 512,
                "numa_node": 0,
                "system_id": "ny7qpr",
                "name": "sda",
                "resource_uri": "/MAAS/api/2.0/nodes/ny7qpr/blockdevices/3/"
            }
        ],
        "cpu_test_status": -1,
        "other_test_status_name": "Unknown",
        "boot_disk": {
            "firmware_version": "2.0",
            "partitions": [
                {
                    "uuid": "7f057f3f-eb00-42d7-959a-5ba3798bcf97",
                    "size": 214739976192,
                    "bootable": false,
                    "tags": [],
                    "id": 2,
                    "used_for": "ext4 formatted filesystem mounted at /",
                    "type": "partition",
                    "device_id": 3,
                    "path": "/dev/disk/by-dname/sda-part2",
                    "system_id": "ny7qpr",
                    "filesystem": {
                        "fstype": "ext4",
                        "label": "root",
                        "uuid": "bb51fe18-4092-4600-a4a6-3c09bcec1236",
                        "mount_point": "/",
                        "mount_options": null
                    },
                    "resource_uri": "/MAAS/api/2.0/nodes/ny7qpr/blockdevices/3/partition/2"
                }
            ],
            "type": "physical",
            "model": "Virtual disk",
            "id": 3,
            "id_path": "/dev/sda",
            "used_for": "GPT partitioned with 1 partition",
            "tags": [
                "ssd"
            ],
            "filesystem": null,
            "storage_pool": null,
            "available_size": 0,
            "path": "/dev/disk/by-dname/sda",
            "uuid": null,
            "serial": "",
            "partition_table_type": "GPT",
            "size": 214748364800,
            "used_size": 214746267648,
            "block_size": 512,
            "numa_node": 0,
            "system_id": "ny7qpr",
            "name": "sda",
            "resource_uri": "/MAAS/api/2.0/nodes/ny7qpr/blockdevices/3/"
        },
        "bios_boot_method": "pxe",
        "status": 6,
        "zone": {
            "name": "default",
            "description": "",
            "id": 1,
            "resource_uri": "/MAAS/api/2.0/zones/default/"
        },
        "memory_test_status_name": "Unknown",
        "storage_test_status": -1,
        "netboot": false,
        "min_hwe_kernel": "hwe-20.04",
        "owner_data": {},
        "domain": {
            "authoritative": true,
            "ttl": null,
            "is_default": true,
            "id": 0,
            "resource_record_count": 1,
            "name": "maas",
            "resource_uri": "/MAAS/api/2.0/domains/0/"
        },
        "current_commissioning_result_id": 28,
        "hostname": "worker3",
        "commissioning_status": 2,
        "ephemeral_deploy": false,
        "default_gateways": {
            "ipv4": {
                "gateway_ip": "10.100.131.1",
                "link_id": null
            },
            "ipv6": {
                "gateway_ip": null,
                "link_id": null
            }
        },
        "memory": 16384,
        "power_state": "unknown",
        "network_test_status": -1,
        "node_type_name": "Machine",
        "storage_test_status_name": "Unknown",
        "next_sync": null,
        "power_type": "manual",
        "interface_test_status_name": "Unknown",
        "interface_set": [
            {
                "product": null,
                "type": "physical",
                "firmware_version": null,
                "interface_speed": 0,
                "id": 15,
                "params": {},
                "link_connected": false,
                "tags": [],
                "vlan": {
                    "vid": 0,
                    "mtu": 1500,
                    "dhcp_on": true,
                    "external_dhcp": null,
                    "relay_vlan": null,
                    "fabric_id": 0,
                    "id": 1,
                    "secondary_rack": null,
                    "space": "undefined",
                    "fabric": "fabric-0",
                    "name": "untagged",
                    "primary_rack": "gppxcx",
                    "resource_uri": "/MAAS/api/2.0/vlans/1/"
                },
                "links": [
                    {
                        "id": 23,
                        "mode": "static",
                        "ip_address": "10.100.131.15",
                        "subnet": {
                            "name": "oc-test",
                            "description": "",
                            "vlan": {
                                "vid": 0,
                                "mtu": 1500,
                                "dhcp_on": true,
                                "external_dhcp": null,
                                "relay_vlan": null,
                                "fabric_id": 0,
                                "id": 1,
                                "secondary_rack": null,
                                "space": "undefined",
                                "fabric": "fabric-0",
                                "name": "untagged",
                                "primary_rack": "gppxcx",
                                "resource_uri": "/MAAS/api/2.0/vlans/1/"
                            },
                            "cidr": "10.100.131.0/24",
                            "rdns_mode": 2,
                            "gateway_ip": "10.100.131.1",
                            "dns_servers": [],
                            "allow_dns": true,
                            "allow_proxy": true,
                            "active_discovery": true,
                            "managed": true,
                            "disabled_boot_architectures": [],
                            "id": 1,
                            "space": "undefined",
                            "resource_uri": "/MAAS/api/2.0/subnets/1/"
                        }
                    }
                ],
                "enabled": true,
                "link_speed": 0,
                "vendor": null,
                "mac_address": "00:50:56:a5:0f:62",
                "children": [],
                "parents": [],
                "numa_node": 0,
                "effective_mtu": 1500,
                "discovered": null,
                "system_id": "ny7qpr",
                "sriov_max_vf": 0,
                "name": "eth0",
                "resource_uri": "/MAAS/api/2.0/nodes/ny7qpr/interfaces/15/"
            }
        ],
        "description": "",
        "boot_interface": {
            "product": null,
            "type": "physical",
            "firmware_version": null,
            "interface_speed": 0,
            "id": 15,
            "params": {},
            "link_connected": false,
            "tags": [],
            "vlan": {
                "vid": 0,
                "mtu": 1500,
                "dhcp_on": true,
                "external_dhcp": null,
                "relay_vlan": null,
                "fabric_id": 0,
                "id": 1,
                "secondary_rack": null,
                "space": "undefined",
                "fabric": "fabric-0",
                "name": "untagged",
                "primary_rack": "gppxcx",
                "resource_uri": "/MAAS/api/2.0/vlans/1/"
            },
            "links": [
                {
                    "id": 23,
                    "mode": "static",
                    "ip_address": "10.100.131.15",
                    "subnet": {
                        "name": "oc-test",
                        "description": "",
                        "vlan": {
                            "vid": 0,
                            "mtu": 1500,
                            "dhcp_on": true,
                            "external_dhcp": null,
                            "relay_vlan": null,
                            "fabric_id": 0,
                            "id": 1,
                            "secondary_rack": null,
                            "space": "undefined",
                            "fabric": "fabric-0",
                            "name": "untagged",
                            "primary_rack": "gppxcx",
                            "resource_uri": "/MAAS/api/2.0/vlans/1/"
                        },
                        "cidr": "10.100.131.0/24",
                        "rdns_mode": 2,
                        "gateway_ip": "10.100.131.1",
                        "dns_servers": [],
                        "allow_dns": true,
                        "allow_proxy": true,
                        "active_discovery": true,
                        "managed": true,
                        "disabled_boot_architectures": [],
                        "id": 1,
                        "space": "undefined",
                        "resource_uri": "/MAAS/api/2.0/subnets/1/"
                    }
                }
            ],
            "enabled": true,
            "link_speed": 0,
            "vendor": null,
            "mac_address": "00:50:56:a5:0f:62",
            "children": [],
            "parents": [],
            "numa_node": 0,
            "effective_mtu": 1500,
            "discovered": null,
            "system_id": "ny7qpr",
            "sriov_max_vf": 0,
            "name": "eth0",
            "resource_uri": "/MAAS/api/2.0/nodes/ny7qpr/interfaces/15/"
        },
        "parent": null,
        "cpu_test_status_name": "Unknown",
        "commissioning_status_name": "Passed",
        "hardware_uuid": "82142542-5453-c2e8-df3a-0db0715380d1",
        "numanode_set": [
            {
                "index": 0,
                "memory": 16384,
                "cores": [
                    0,
                    1,
                    2,
                    3
                ],
                "hugepages_set": []
            }
        ],
        "node_type": 0,
        "testing_status_name": "Unknown",
        "raids": [],
        "locked": false,
        "virtualmachine_id": null,
        "hwe_kernel": "hwe-20.04",
        "address_ttl": null,
        "virtualblockdevice_set": [],
        "bcaches": [],
        "status_name": "Deployed",
        "current_testing_result_id": 27,
        "last_sync": null,
        "physicalblockdevice_set": [
            {
                "firmware_version": "2.0",
                "partitions": [
                    {
                        "uuid": "7f057f3f-eb00-42d7-959a-5ba3798bcf97",
                        "size": 214739976192,
                        "bootable": false,
                        "tags": [],
                        "id": 2,
                        "used_for": "ext4 formatted filesystem mounted at /",
                        "type": "partition",
                        "device_id": 3,
                        "path": "/dev/disk/by-dname/sda-part2",
                        "system_id": "ny7qpr",
                        "filesystem": {
                            "fstype": "ext4",
                            "label": "root",
                            "uuid": "bb51fe18-4092-4600-a4a6-3c09bcec1236",
                            "mount_point": "/",
                            "mount_options": null
                        },
                        "resource_uri": "/MAAS/api/2.0/nodes/ny7qpr/blockdevices/3/partition/2"
                    }
                ],
                "type": "physical",
                "model": "Virtual disk",
                "id": 3,
                "id_path": "/dev/sda",
                "used_for": "GPT partitioned with 1 partition",
                "tags": [
                    "ssd"
                ],
                "filesystem": null,
                "storage_pool": null,
                "available_size": 0,
                "path": "/dev/disk/by-dname/sda",
                "uuid": null,
                "serial": "",
                "partition_table_type": "GPT",
                "size": 214748364800,
                "used_size": 214746267648,
                "block_size": 512,
                "numa_node": 0,
                "system_id": "ny7qpr",
                "name": "sda",
                "resource_uri": "/MAAS/api/2.0/nodes/ny7qpr/blockdevices/3/"
            }
        ],
        "cache_sets": [],
        "storage": 214748.3648,
        "cpu_count": 4,
        "workload_annotations": {},
        "tag_names": [
            "virtual"
        ],
        "architecture": "amd64/generic",
        "status_message": "Deployed",
        "interface_test_status": -1,
        "current_installation_result_id": 35,
        "osystem": "ubuntu",
        "owner": "maasadmin",
        "ip_addresses": [
            "10.100.131.15"
        ],
        "disable_ipv4": false,
        "fqdn": "worker3.maas",
        "pool": {
            "name": "default",
            "description": "Default pool",
            "id": 0,
            "resource_uri": "/MAAS/api/2.0/resourcepool/0/"
        },
        "other_test_status": -1,
        "memory_test_status": -1,
        "network_test_status_name": "Unknown",
        "swap_size": null,
        "pod": null,
        "status_action": "",
        "distro_series": "focal",
        "error_description": "",
        "cpu_speed": 2400,
        "testing_status": -1,
        "hardware_info": {
            "system_vendor": "VMware, Inc.",
            "system_product": "VMware Virtual Platform",
            "system_family": "Unknown",
            "system_version": "Unknown",
            "system_sku": "Unknown",
            "system_serial": "VMware-42 25 14 82 53 54 e8 c2-df 3a 0d b0 71 53 80 d1",
            "cpu_model": "Intel(R) Xeon(R) Platinum 8260 CPU",
            "mainboard_vendor": "Intel Corporation",
            "mainboard_product": "440BX Desktop Reference Platform",
            "mainboard_serial": "Unknown",
            "mainboard_version": "Unknown",
            "mainboard_firmware_vendor": "Phoenix Technologies LTD",
            "mainboard_firmware_date": "11/12/2020",
            "mainboard_firmware_version": "6.00",
            "chassis_vendor": "No Enclosure",
            "chassis_type": "Other",
            "chassis_serial": "Unknown",
            "chassis_version": "N/A"
        },
        "sync_interval": null,
        "special_filesystems": [],
        "system_id": "ny7qpr",
        "enable_hw_sync": false,
        "volume_groups": [],
        "resource_uri": "/MAAS/api/2.0/machines/ny7qpr/"
    }
]

What is the proper definition for the resource ?

terraform {
required_providers {
maas = {
source = “maas/maas”
version = “~>1.0”
# source = “registry.terraform.io/ionutbalutoiu/maas
}
}
}

provider “maas” {
api_version = “2.0”
api_url= “http//10.10.10.10:5240/MAAS”
api_key= “myapikey”
}

resource “maas_instance” “worker3” {

}
As I understand the Terraform take any VM from Maas which is siutable for some parameter like min_cpu=value etc. ?

Can I take a VM as a resource using name=value ? like mac_address": “00:50:56:a5:0f:62”

The reference documentation of terraform and maas don’t seems to be clear for me. Any guidelines will be appriciate !
Cheers

Hi @jack0ne

First of all, our Terraform provider is moved under canonical. Therefore, you should fetch it from canonical/maas rather than maas/maas.

In addition, based on the Rancher provider documentation you need a custom cluster so that you can get the rancher2_cluster_v2.foo.cluster_registration_token.node_command here.

When you do, you need to create proper cloud-init user data and add them to your maas_instance:

resource "maas_instance" "demo" {
  deploy_params {
    distro_series = "jammy"
    user_data     = data.template_cloudinit_config.config.rendered
  }
}

data "template_cloudinit_config" "config" {
  gzip          = false
  base64_encode = false

  part {
    filename     = "init.sh"
    content_type = "text/x-shellscript"
    content      = data.template_file.script.rendered
  }
}

data "template_file" "script" {
  template = file("${path.module}/templates/cloud_init.tpl")

  vars = {
    rancher_command = rancher2_cluster_v2.foo.cluster_registration_token.node_command
  }
}
cat templates/cloud_init.tpl

#!/bin/bash

set -x

# echo Rancher command
echo "${rancher_command}"

It is up to you to decide what the contents of that cloud-init script should be.

This is also an example to pick a Ready MAAS machine for deployment (including a VM from your MAAS VM Host) based on criteria:

resource "maas_instance" "demo" {
  allocate_params {
    hostname      = maas_vm_host_machine.foo.hostname
    # or
    hostname      = maas_machine.foo.hostname
    min_cpu_count = 1
  }
}

A detailed list of the available allocate_params can be found at the provider’s documentation.

Hello Skatsaounis,
First of all many thanks for respond from your side.
I did the change for reuired_providers to:
source = cannonical/maas version - ~>2.0

Because this project is my first on maybe I don’t describe the issue which I’m facing here ( sory for that )
My main goal is to give a rancher infrastructure to provision rke2 cluster on the vm. The vm are provisioned by the maas ( all is virtualized on vspahre - I saw that tarraform can interact directly with vSphare but now it’s not possible to me as I don’t have all persmisiont to vSphare and the are able only to give me the vm’s ) As the VM’s has been deployed in MAAS I would like to describe them using terraform.
I’m aware that I can provision the rancher command using this node_command but this is much more later steps to set up the cluster - currently I’m not able to build the code for infra :confused:

As you inspired me to try to define the resource=maas_instance I’m facing the issue with resource maas_machine ( the power_parameter are required and I don’t know wher/how to get them - tryided to search maas admin mahines read hostname=worker3 .
This whole terraform docs don’t seems to be clear to me. I’m searhing the examples of sytax/definitions for this tech combo but no results - and that’s why I’m asking here :slight_smile:

Cheers

Let me try to expand more on maas_machine vs maas_instance vs maas_vm_host_machine:

  • maas_machine: it will get the power parameters and the MAC address of a machine and it will try to create it in MAAS and commission it. In the end it will move the machine in state Ready.
  • maas_vm_host_machine: it will use a specified MAAS VM Host and compose a VM machine, that after commissioning, it will reach to state Ready.
  • maas_instance: it will try to allocate a Ready machine in MAAS (physical or VM) based on allocate_params and then try to deploy it with the options being specified to deploy_params. As such, it will move the machine to state Deployed.

So in your case you can use a combination of maas_vm_host_machine, maas_instance to get where you need to be:

resource "maas_vm_host_machine" "foo" {
  hostname = "rancher-node-0"
  vm_host  = __vm-host-id-on-maas-db__
  cores    = 1
  memory   = 2048

  storage_disks {
    size_gigabytes = 15
  }
}

resource "maas_instance" "demo" {
  allocate_params {
    hostname      = maas_vm_host_machine.foo.hostname
  }
  deploy_params {
    distro_series = "jammy"
    user_data     = data.template_cloudinit_config.config.rendered
  }
}

data "template_cloudinit_config" "config" {
  gzip          = false
  base64_encode = false

  part {
    filename     = "init.sh"
    content_type = "text/x-shellscript"
    content      = data.template_file.script.rendered
  }
}

data "template_file" "script" {
  template = file("${path.module}/templates/cloud_init.tpl")

  vars = {
    rancher_command = rancher2_cluster_v2.foo.cluster_registration_token.node_command
  }
}

resource "rancher2_cluster_v2" "foo" {
  name = "foo"
  kubernetes_version = "rke2-/k3s-version"
}

To get vm-host id in MAAS you need:

maas admin vm-hosts read | jq -r '.[] | [.id, .name]'

In the future we will implement a data source for vm hosts so that you can do this query more naturally with Terraform.

So you have to deploy the machines

Hello skatsaounis,
thank for next steps. It help a little bit as I implemented resources based on you tips.
output from:
maas admin vm-hosts read | jq -r ‘.[] | [.id, .name]’
[
4,
“worker4”
]
Resources definition and terraform apply --auto-approve

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # maas_instance.mi_w4 will be created
  + resource "maas_instance" "mi_w4" {
      + cpu_count    = (known after apply)
      + fqdn         = (known after apply)
      + hostname     = (known after apply)
      + id           = (known after apply)
      + ip_addresses = (known after apply)
      + memory       = (known after apply)
      + pool         = (known after apply)
      + tags         = (known after apply)
      + zone         = (known after apply)

      + allocate_params {
          + hostname      = "rancher-w4"
          + min_cpu_count = 0
          + min_memory    = 0
        }

      + deploy_params {
          + distro_series = "focal"
        }
    }

  # maas_vm_host_machine.worker4 will be created
  + resource "maas_vm_host_machine" "worker4" {
      + cores    = 4
      + domain   = (known after apply)
      + hostname = "rancher-w4"
      + id       = (known after apply)
      + memory   = 16384
      + pool     = (known after apply)
      + vm_host  = "4"
      + zone     = (known after apply)
    }

Plan: 2 to add, 0 to change, 0 to destroy.
maas_vm_host_machine.worker4: Creating...
╷
│ Error: Get "/http//10.100.131.17:5240/MAAS/api/2.0/pods/": unsupported protocol scheme ""
│
│   with maas_vm_host_machine.worker4,
│   on main.tf line 17, in resource "maas_vm_host_machine" "worker4":
│   17: resource "maas_vm_host_machine" "worker4" {

this output indicates a wrongly set MAAS_URL in case you are setting it as an environment variable or maas_url in case you are doing it inside provider.tf.

So it has to be /http//10.100.131.17:5240/MAAS http://10.100.131.17:5240/MAAS

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.