Your submission was sent successfully! Close

You have successfully unsubscribed! Close

Thank you for signing up for our newsletter!
In these regular emails you will find the latest updates about Ubuntu and upcoming events where you can meet our team.Close

MAAS CLI-only machine creation

Bill Wear

on 2 December 2020

This article was last updated 2 years ago.


The whole point of MAAS configuration is to get machines deployed. If you read the previous post in this series, you know how to install MAAS and do basic configuration using only the MAAS Command-Line Interface (CLI).  So far, so good, but now we need to enable networking and create some machines.

Enabling DHCP

The next step in any MAAS install is to get DHCP working on a MAAS VLAN. Usually, we choose the default, untagged VLAN. In the UI, that’s easy to find by inspection, but how do we find it using only the CLI? Well, we need to know two things besides the VLAN name (“untagged”): the the fabric ID and the primary rack controller name.

Actually, to start with, all the fabrics will be on the same untagged VLAN, so any fabric will do. In turn, I can find a valid fabric ID by reading it from any subnet, so I’ll just pick one I know (192.168.123.0/24, the subnet for my virtual bridge). That means we can find a usable fabric ID like this:

stormrider@wintermute:~$ maas admin subnet read 192.168.123.0/24 | grep fabric_id

"fabric_id": 2,

Note that we could use a fancy jq invocation to get fancier output, but given that there’s only one fabric_id in the returned JSON, that’s overkill. Now that we have a fabric ID, we need to find the name of the primary rack controller. That should be the laptop hostname (wintermute), but for purposes of argument, assume we don’t know it and use a command like this:

stormrider@wintermute:~$ maas admin rack-controllers \
read | grep hostname | cut -d '"' -f 4

wintermute

Predictable, but worth knowing how to do; and this would mean we can turn on DHCP like this:

stormrider@wintermute:~$ maas admin vlan update 2 \
untagged dhcp_on=True primary_rack=wintermute

{"dhcp_on": ["dhcp can only be turned on when a dynamic IP range is defined."]}

Whoops; we need to define a dynamic IP range. Well, given that the virtual bridge on this system is 192.168.123.0/24, let’s just use a range on that subnet:

stormrider@wintermute:~$ maas admin ipranges create \
type=dynamic start_ip=192.168.123.190 \
end_ip=192.168.123.253

Success.
Machine-readable output follows:
{
    "subnet": {
        "name": "192.168.123.0/24",
        "description": "",
        "vlan": {
            "vid": 0,
            "mtu": 1500,
            "dhcp_on": false,
            "external_dhcp": null,
            "relay_vlan": null,
            "fabric": "fabric-2",
            "primary_rack": null,
            "name": "untagged",
            "id": 5003,
            "space": "undefined",
            "secondary_rack": null,
            "fabric_id": 2,
            "resource_uri": "/MAAS/api/2.0/vlans/5003/"
        },
        "cidr": "192.168.123.0/24",
        "rdns_mode": 2,
        "gateway_ip": null,
        "dns_servers": [],
        "allow_dns": true,
        "allow_proxy": true,
        "active_discovery": false,
        "managed": true,
        "id": 4,
        "space": "undefined",
        "resource_uri": "/MAAS/api/2.0/subnets/4/"
    },
    "type": "dynamic",
    "start_ip": "192.168.123.190",
    "end_ip": "192.168.123.253",
    "user": {
        "is_superuser": true,
        "username": "admin",
        "email": "admin@admin.com",
        "is_local": true,
        "resource_uri": "/MAAS/api/2.0/users/admin/"
    },
    "comment": "",
    "id": 1,
    "resource_uri": "/MAAS/api/2.0/ipranges/1/"
}

Okay, so let’s try switching on DHCP one more time:

stormrider@wintermute:~$ maas admin vlan update 2 \
untagged dhcp_on=True primary_rack=wintermute

Success.
Machine-readable output follows:
{
    "vid": 0,
    "mtu": 1500,
    "dhcp_on": true,
    "external_dhcp": null,
    "relay_vlan": null,
    "fabric": "fabric-2",
    "space": "undefined",
    "primary_rack": "8dwnne",
    "secondary_rack": null,
    "name": "untagged",
    "fabric_id": 2,
    "id": 5003,
    "resource_uri": "/MAAS/api/2.0/vlans/5003/"
}

It says, “Success,” but if you’re doubtful, you can look at the UI and see that DHCP is indeed enabled.

Creating machines

In order to deploy machines, we’ll have to create some. It’s a relatively simple operation with the UI, but for this exercise, we’re only using the CLI. Since MAAS uses the “collections” idea, creating a machine is considered adding to the collection, so the object (“machines”) is plural, producing a command like this on our MAAS host, wintermute:

stormrider@wintermute:~$ maas admin machines create \
architecture=amd64 \
mac_addresses=52:54:00:15:36:f2 \
power_type=virsh \
power_parameters_power_id=f677a842-571c-4e65-adc9-11e2cf92d363 \
power_parameters_power_address=qemu+ssh://stormrider@192.168.123.1/system \
power_parameters_power_pass=xxxxxxxx

Success.
Machine-readable output follows:
{
    "storage": 0.0,
    "tag_names": [],
    "special_filesystems": [],
    "memory": 0,
    "boot_disk": null,
    "virtualblockdevice_set": [],
    "hardware_info": {
        "system_vendor": "Unknown",
        "system_product": "Unknown",
        "system_family": "Unknown",
        "system_version": "Unknown",
        "system_sku": "Unknown",
        "system_serial": "Unknown",
        "cpu_model": "Unknown",
        "mainboard_vendor": "Unknown",
        "mainboard_product": "Unknown",
        "mainboard_serial": "Unknown",
        "mainboard_version": "Unknown",
        "mainboard_firmware_vendor": "Unknown",
        "mainboard_firmware_date": "Unknown",
        "mainboard_firmware_version": "Unknown",
        "chassis_vendor": "Unknown",
        "chassis_type": "Unknown",
        "chassis_serial": "Unknown",
        "chassis_version": "Unknown"
    },
    "address_ttl": null,
    "memory_test_status": -1,
    "other_test_status_name": "Unknown",
    "osystem": "",
    "status_message": "Commissioning",
    "netboot": true,
    "physicalblockdevice_set": [],
    "node_type": 0,
    "cpu_test_status": -1,
    "memory_test_status_name": "Unknown",
    "bcaches": [],
    "storage_test_status": 0,
    "system_id": "bhxws3",
    "status": 1,
    "commissioning_status": 0,
    "power_type": "virsh",
    "locked": false,
    "numanode_set": [
        {
            "index": 0,
            "memory": 0,
            "cores": []
        }
    ],
    "bios_boot_method": null,
    "fqdn": "ace-swan.maas",
    "node_type_name": "Machine",
    "hostname": "ace-swan",
    "volume_groups": [],
    "testing_status": 0,
    "network_test_status": -1,
    "other_test_status": -1,
    "interface_test_status": -1,
    "hwe_kernel": null,
    "blockdevice_set": [],
    "testing_status_name": "Pending",
    "power_state": "unknown",
    "min_hwe_kernel": "",
    "owner": "admin",
    "distro_series": "",
    "storage_test_status_name": "Pending",
    "cpu_speed": 0,
    "swap_size": null,
    "cpu_test_status_name": "Unknown",
    "hardware_uuid": null,
    "architecture": "amd64/generic",
    "pool": {
        "name": "default",
        "description": "Default pool",
        "id": 0,
        "resource_uri": "/MAAS/api/2.0/resourcepool/0/"
    },
    "cache_sets": [],
    "pod": null,
    "iscsiblockdevice_set": [],
    "disable_ipv4": false,
    "status_action": "",
    "boot_interface": {
        "name": "eth0",
        "id": 10,
        "product": null,
        "system_id": "bhxws3",
        "effective_mtu": 1500,
        "children": [],
        "link_connected": true,
        "enabled": true,
        "interface_speed": 0,
        "numa_node": 0,
        "firmware_version": null,
        "parents": [],
        "discovered": null,
        "params": "",
        "links": [],
        "sriov_max_vf": 0,
        "tags": [],
        "type": "physical",
        "vlan": null,
        "vendor": null,
        "link_speed": 0,
        "mac_address": "52:54:00:15:36:f2",
        "resource_uri": "/MAAS/api/2.0/nodes/bhxws3/interfaces/10/"
    },
    "cpu_count": 0,
    "domain": {
        "authoritative": true,
        "ttl": null,
        "resource_record_count": 0,
        "name": "maas",
        "is_default": true,
        "id": 0,
        "resource_uri": "/MAAS/api/2.0/domains/0/"
    },
    "current_testing_result_id": 7,
    "default_gateways": {
        "ipv4": {
            "gateway_ip": null,
            "link_id": null
        },
        "ipv6": {
            "gateway_ip": null,
            "link_id": null
        }
    },
    "interface_set": [
        {
            "name": "eth0",
            "id": 10,
            "product": null,
            "system_id": "bhxws3",
            "effective_mtu": 1500,
            "children": [],
            "link_connected": true,
            "enabled": true,
            "interface_speed": 0,
            "numa_node": 0,
            "firmware_version": null,
            "parents": [],
            "discovered": null,
            "params": "",
            "links": [],
            "sriov_max_vf": 0,
            "tags": [],
            "type": "physical",
            "vlan": null,
            "vendor": null,
            "link_speed": 0,
            "mac_address": "52:54:00:15:36:f2",
            "resource_uri": "/MAAS/api/2.0/nodes/bhxws3/interfaces/10/"
        }
    ],
    "status_name": "Commissioning",
    "commissioning_status_name": "Pending",
    "owner_data": {},
    "ip_addresses": [],
    "raids": [],
    "network_test_status_name": "Unknown",
    "description": "",
    "current_commissioning_result_id": 6,
    "interface_test_status_name": "Unknown",
    "current_installation_result_id": null,
    "zone": {
        "name": "default",
        "description": "",
        "id": 1,
        "resource_uri": "/MAAS/api/2.0/zones/default/"
    },
    "resource_uri": "/MAAS/api/2.0/machines/bhxws3/"
}

That’s a long JSON response, but it’s worth studying for a minute, since that’s essentially what a machine looks like to the MAAS CLI. If you’re going to query MAAS via the CLI about machines, you’ll be asking for some combination of those JSON keys.

Since MAAS on wintermute is set to commission upon creation (the default), you could now check the UI and see that the machine is commissioning. A lot of the parameters there are a little hard to discover, as some are in the documentation, and others are buried in the help or one of the “read” outputs.

Commissioning by CLI

When commissioning finishes, we’ll have a machine in the “Ready” state. At that point, let’s take a minute to get familiar with the CLI commands to commission a machine. All that’s really needed is the system ID, which is the text between the last pair of slashes in the last JSON key, “resource_uri” above. Just for practice, though, let’s go ahead and retrieve the system ID using the CLI — which will be simple to recognize, since there’s only one machine right now:

stormrider@wintermute:~$ maas admin machines read \
| jq '.[] | .hostname, .system_id'

"ace-swan"
"bhxws3"

Notice the first parameter is the hostname, which we allowed to be MAAS-assigned when the machine was created. The second parameter is the system_ID, which we need to commission the machine, like this:

stormrider@wintermute:~$ maas admin machine \
commission bhxws3

Success.
Machine-readable output follows:
{
    "storage_test_status_name": "Pending",
    "bcaches": [],
    "cpu_count": 1,
    "interface_set": [
        {
            "params": "",
            "numa_node": 0,
            "tags": [],
            "id": 10,
            "mac_address": "52:54:00:15:36:f2",
            "vendor": "Red Hat, Inc.",
            "children": [],
            "effective_mtu": 1500,
            "discovered": [],
            "links": [],
            "link_speed": 0,
            "link_connected": true,
            "system_id": "bhxws3",
            "enabled": true,
            "interface_speed": 0,
            "firmware_version": null,
            "name": "ens3",
            "sriov_max_vf": 0,
            "product": null,
            "vlan": {
                "vid": 0,
                "mtu": 1500,
                "dhcp_on": true,
                "external_dhcp": null,
                "relay_vlan": null,
                "fabric": "fabric-2",
                "primary_rack": "8dwnne",
                "name": "untagged",
                "id": 5003,
                "space": "undefined",
                "secondary_rack": null,
                "fabric_id": 2,
                "resource_uri": "/MAAS/api/2.0/vlans/5003/"
            },
            "parents": [],
            "type": "physical",
            "resource_uri": "/MAAS/api/2.0/nodes/bhxws3/interfaces/10/"
        }
    ],
    "network_test_status_name": "Unknown",
    "numanode_set": [
        {
            "index": 0,
            "memory": 985,
            "cores": [
                0
            ]
        }
    ],
    "locked": false,
    "hardware_uuid": "F677A842-571C-4E65-ADC9-11E2CF92D363",
    "default_gateways": {
        "ipv4": {
            "gateway_ip": null,
            "link_id": null
        },
        "ipv6": {
            "gateway_ip": null,
            "link_id": null
        }
    },
    "status_action": "",
    "status_message": "Commissioning",
    "cpu_test_status_name": "Unknown",
    "memory_test_status": -1,
    "virtualblockdevice_set": [],
    "pool": {
        "name": "default",
        "description": "Default pool",
        "id": 0,
        "resource_uri": "/MAAS/api/2.0/resourcepool/0/"
    },
    "current_testing_result_id": 9,
    "current_installation_result_id": null,
    "netboot": true,
    "description": "",
    "special_filesystems": [],
    "testing_status": 0,
    "memory": 1024,
    "current_commissioning_result_id": 8,
    "storage": 5368.70912,
    "commissioning_status": 0,
    "cpu_test_status": -1,
    "tag_names": [
        "virtual"
    ],
    "memory_test_status_name": "Unknown",
    "swap_size": null,
    "status_name": "Commissioning",
    "other_test_status": -1,
    "pod": null,
    "storage_test_status": 0,
    "blockdevice_set": [
        {
            "id_path": "/dev/disk/by-id/ata-QEMU_HARDDISK_QM00001",
            "size": 5368709120,
            "block_size": 512,
            "tags": [
                "ssd"
            ],
            "serial": "QM00001",
            "uuid": null,
            "numa_node": 0,
            "available_size": 5368709120,
            "id": 3,
            "partition_table_type": null,
            "model": "QEMU HARDDISK",
            "path": "/dev/disk/by-dname/sda",
            "storage_pool": null,
            "used_for": "Unused",
            "filesystem": null,
            "system_id": "bhxws3",
            "used_size": 0,
            "partitions": [],
            "name": "sda",
            "type": "physical",
            "resource_uri": "/MAAS/api/2.0/nodes/bhxws3/blockdevices/3/"
        }
    ],
    "other_test_status_name": "Unknown",
    "distro_series": "",
    "testing_status_name": "Pending",
    "ip_addresses": [],
    "address_ttl": null,
    "system_id": "bhxws3",
    "physicalblockdevice_set": [
        {
            "firmware_version": "2.5+",
            "serial": "QM00001",
            "uuid": null,
            "numa_node": 0,
            "available_size": 5368709120,
            "size": 5368709120,
            "tags": [
                "ssd"
            ],
            "id": 3,
            "partition_table_type": null,
            "id_path": "/dev/disk/by-id/ata-QEMU_HARDDISK_QM00001",
            "model": "QEMU HARDDISK",
            "path": "/dev/disk/by-dname/sda",
            "storage_pool": null,
            "used_for": "Unused",
            "filesystem": null,
            "system_id": "bhxws3",
            "used_size": 0,
            "partitions": [],
            "name": "sda",
            "block_size": 512,
            "type": "physical",
            "resource_uri": "/MAAS/api/2.0/nodes/bhxws3/blockdevices/3/"
        }
    ],
    "fqdn": "ace-swan.maas",
    "osystem": "",
    "domain": {
        "authoritative": true,
        "ttl": null,
        "resource_record_count": 0,
        "name": "maas",
        "id": 0,
        "is_default": true,
        "resource_uri": "/MAAS/api/2.0/domains/0/"
    },
    "boot_interface": {
        "params": "",
        "numa_node": 0,
        "tags": [],
        "id": 10,
        "mac_address": "52:54:00:15:36:f2",
        "vendor": "Red Hat, Inc.",
        "children": [],
        "effective_mtu": 1500,
        "discovered": [],
        "links": [],
        "link_speed": 0,
        "link_connected": true,
        "system_id": "bhxws3",
        "enabled": true,
        "interface_speed": 0,
        "firmware_version": null,
        "name": "ens3",
        "sriov_max_vf": 0,
        "product": null,
        "vlan": {
            "vid": 0,
            "mtu": 1500,
            "dhcp_on": true,
            "external_dhcp": null,
            "relay_vlan": null,
            "fabric": "fabric-2",
            "primary_rack": "8dwnne",
            "name": "untagged",
            "id": 5003,
            "space": "undefined",
            "secondary_rack": null,
            "fabric_id": 2,
            "resource_uri": "/MAAS/api/2.0/vlans/5003/"
        },
        "parents": [],
        "type": "physical",
        "resource_uri": "/MAAS/api/2.0/nodes/bhxws3/interfaces/10/"
    },
    "hostname": "ace-swan",
    "network_test_status": -1,
    "min_hwe_kernel": "",
    "power_state": "off",
    "interface_test_status_name": "Unknown",
    "owner_data": {},
    "volume_groups": [],
    "power_type": "virsh",
    "node_type": 0,
    "owner": "admin",
    "cache_sets": [],
    "architecture": "amd64/generic",
    "hwe_kernel": null,
    "zone": {
        "name": "default",
        "description": "",
        "id": 1,
        "resource_uri": "/MAAS/api/2.0/zones/default/"
    },
    "disable_ipv4": false,
    "boot_disk": {
        "firmware_version": "2.5+",
        "serial": "QM00001",
        "uuid": null,
        "numa_node": 0,
        "available_size": 5368709120,
        "size": 5368709120,
        "tags": [
            "ssd"
        ],
        "id": 3,
        "partition_table_type": null,
        "id_path": "/dev/disk/by-id/ata-QEMU_HARDDISK_QM00001",
        "model": "QEMU HARDDISK",
        "path": "/dev/disk/by-dname/sda",
        "storage_pool": null,
        "used_for": "Unused",
        "filesystem": null,
        "system_id": "bhxws3",
        "used_size": 0,
        "partitions": [],
        "name": "sda",
        "block_size": 512,
        "type": "physical",
        "resource_uri": "/MAAS/api/2.0/nodes/bhxws3/blockdevices/3/"
    },
    "status": 1,
    "iscsiblockdevice_set": [],
    "raids": [],
    "node_type_name": "Machine",
    "hardware_info": {
        "system_vendor": "QEMU",
        "system_product": "Standard PC (i440FX + PIIX, 1996)",
        "system_family": "Unknown",
        "system_version": "pc-i440fx-focal",
        "system_sku": "Unknown",
        "system_serial": "Unknown",
        "cpu_model": "Intel Core Processor (Skylake, IBRS)",
        "mainboard_vendor": "Unknown",
        "mainboard_product": "Unknown",
        "mainboard_serial": "Unknown",
        "mainboard_version": "Unknown",
        "mainboard_firmware_vendor": "SeaBIOS",
        "mainboard_firmware_date": "04/01/2014",
        "mainboard_firmware_version": "1.13.0-1ubuntu1",
        "chassis_vendor": "QEMU",
        "chassis_type": "Other",
        "chassis_serial": "Unknown",
        "chassis_version": "pc-i440fx-focal"
    },
    "commissioning_status_name": "Pending",
    "bios_boot_method": "pxe",
    "interface_test_status": -1,
    "cpu_speed": 0,
    "resource_uri": "/MAAS/api/2.0/machines/bhxws3/"
}

As you can see, the CLI produces some very long strings of JSON for some operations, so you’ll want to master jq if you’re going to use the CLI a lot. Not to worry, the last blog post in this series will go into that tool, in some detail. For the moment, though, this is a good place to pause, and take up the topics of acquiring and deploying machines (via CLI) in the next post.

Ubuntu cloud

Ubuntu offers all the training, software infrastructure, tools, services and support you need for your public and private clouds.

Newsletter signup

Get the latest Ubuntu news and updates in your inbox.

By submitting this form, I confirm that I have read and agree to Canonical's Privacy Policy.

Related posts

A call for community

Introduction Open source projects are a testament to the possibilities of collective action. From small libraries to large-scale systems, these projects rely...

MAAS Outside the Lines

Far from the humdrum of server setups, this is about unusual deployments – Raspberry Pis, loose laptops, cheap NUCs, home appliances, and more. What the heck...

No more DHCP(d)

“He’s dead, Jim.”  Dr. McCoy DHCP is dead; long live DHCP. Yes, the end-of-life announcement for ISC DHCP means that the ISC will no longer provide official...