CLI-only MAAS operation
MAAS provides a state-of-the-art User Interface (UI), which simplifies usage. But you may not know that MAAS also has a robust Command-line Interface (CLI), which actually provides more functionality than the UI. Everything you can do from the UI, you can do from the CLI, but not the other way round. Let’s walk through MAAS operations using only the CLI, and look at a few jq tricks to produce human-readable CLI output.
Quick questions you may have:
Installing MAAS
First, installation: note that our MAAS host is named “wintermute,” so you can ignore any references in the text that follows. Let’s be naive and start cold with MAAS 2.8. Step one is to install (but not initialise) the MAAS snap:
stormrider@wintermute:~$ sudo snap install maas --channel=2.8
...
maas (2.8/stable) 2.8.1-8567-g.c4825ca06 from Canonical installed
Looking over the MAAS initialisation modes, it looks like region+rack
mode will do just fine for this install. There’s no need for the complexity of separate rack controllers just yet. First, though, there’s a decision about whether to use the POC mode (with a test DB) or just install to full-up production mode. The latter seems like the most involved, so let’s go with production mode.
Production PostgreSQL
Running MAAS in production mode means a local PostgreSQL install, from packages. Like all package installs, this process begins with a quick package update:
stormrider@wintermute:~$ sudo apt update -y
...list of updates follows...
stormrider@wintermute:~$
This will grab any packages that might be needed for the install to succeed. Install the latest PostgreSQL package, which happens to be version 12 at this writing:
stormrider@wintermute:~$ sudo apt install -y postgresql
...install messages follow...
stormrider@wintermute:~$
Set up a PostgreSQL user and a suitable MAAS database, needed to configure what follows:
stormrider@wintermute:~$ sudo -u postgres psql -c \
"CREATE USER \"maascli\" WITH ENCRYPTED PASSWORD 'maascli'"
CREATE ROLE
stormrider@wintermute:~$ sudo -u postgres createdb -O \
"maascli" "maasclidb"
stormrider@wintermute:~$
Note that there’s no system response to the database creation command — the old UNIX rule of “no news is good news.” Not to worry, more than likely you would see an error message if something didn’t work.
Next, we need to add the new database to the PostgreSQL HBA configuration, by editing /etc/postgres/12/main/pg_hbq.conf
, adding a line to the bottom of the file for the new maas
database:
host maasclidb maascli 0/0 md5
Finally, we can initialise MAAS, like this:
stormrider@wintermute:~$ sudo maas init region+rack \
--database-uri \
"postgres://maascli:maascli@localhost/maasclidb"
MAAS URL [default=http://192.168.43.251]:
...MAAS setup notifications...
There’s an important bit of feedback there, the MAAS URL, which will be needed for the CLI login. That’s followed by a running commentary on the steps MAAS is taking to initialise, ending with the following message:
MAAS has been set up.
If you want to configure external authentication or use
MAAS with Canonical RBAC, please run
sudo maas configauth
To create admins when not using external authentication, run
sudo maas createadmin
Obviously, the next step is an easy call: run createadmin
to set up an admin user:
stormrider@wintermute:~$ sudo maas createadmin
[sudo] password for stormrider:
Username: admin
Password:
Again:
Email: <anything can go here, it's not used>
Import SSH keys [] (lp:user-id or gh:user-id): xxxxxxxxxxxx
This makes for an easy install of production MAAS, all via command line (since the installation is always at the CLI).
Configuring MAAS (CLI-only)
Now that MAAS is up and running, it’s time to configure it. You can see documentation on these steps in the CLI configuration journey, part of the new RAD documentation set. Since we’re covering the full range of CLI operations, we’ll go ahead and recap the journey here.
Logging in
The first step for any new CLI operations is logging in, which requires two steps in the CLI. First, we need to get the MAAS apikey
, which permits the CLI to access the MAAS API. Note that the MAAS API is actually the entry point for all MAAS actions through all access methods.
Here’s how we can retrieve and store the MAAS apikey
:
sudo maas apikey --username=admin > api-key-file
You can make sure you got a valid API key by displaying the contents of api-key-file:
stormrider@wintermute:~$: cat api-key-file
XXEjkeeqM:zXb7LkuPY7VxShFNhCFDaD8WnP8gLVL8V64GbSn:tTKdwWV64GbSn:tTKdwW
Note that the string above isn’t an actual API key, just characters that were made up for this example. Anyway, we can now login to MAAS — but first, let’s try maas --help
— there’s an important distinction that gets skipped over, causing some grief.
Getting help
In the MAAS CLI, you always get help by typing some variant of the basic command:
stormrider@wintermute:~$ maas --help
If you’re not logged in, or if you don’t type a “logged-in username” (referred to as a valid profile) after maas
, you get the following, very generic help output:
usage: maas [-h] COMMAND ...
optional arguments:
-h, --help show this help message and exit
drill down:
COMMAND
login Log in to a remote API, and remember its
description and credentials.
logout Log out of a remote API, purging any stored
credentials.
list List remote APIs that have been logged-in to.
refresh Refresh the API descriptions of all profiles.
init Initialise MAAS in the specified run mode.
config View or change controller configuration.
status Status of controller services.
migrate Perform migrations on connected database.
apikey Used to manage a user's API keys. Shows
existing keys unless --generate or --delete
is passed.
configauth Configure external authentication.
createadmin Create a MAAS administrator account.
changepassword
Change a MAAS user's password.
What you see above isn’t even half of what the MAAS CLI will do, but it’s all you get as an unrecognized user.
So now, let’s login and try that help again:
stormrider@wintermute:~$ maas login admin \
http://192.168.143.251:5240/MAAS < api-key-file
You are now logged in to the MAAS server at
http://192.168.43.251:5240/MAAS/api/2.0/ with the profile name
'admin'.
For help with the available commands, try:
maas admin --help
Having logged in, you get much more detailed help:
stormrider@wintermute:~$ maas admin --help
usage: maas admin [-h] COMMAND ...
Issue commands to the MAAS region controller at http://192.168.43.251:5240/MAAS/api/2.0/.
optional arguments:
-h, --help show this help message and exit
drill down:
COMMAND
account Manage the current logged-in user.
bcache-cache-set Manage bcache cache set on a machine.
bcache-cache-sets Manage bcache cache sets on a machine.
bcache Manage bcache device on a machine.
bcaches Manage bcache devices on a machine.
block-device Manage a block device on a machine.
block-devices Manage block devices on a machine.
boot-resource Manage a boot resource.
boot-resources Manage the boot resources.
boot-source Manage a boot source.
boot-source-selection
Manage a boot source selection.
boot-source-selections
Manage the collection of boot source
selections.
boot-sources Manage the collection of boot sources.
commissioning-script
Manage a custom commissioning script.
commissioning-scripts
Manage custom commissioning scripts.
dhcpsnippet Manage an individual DHCP snippet.
dhcpsnippets Manage the collection of all DHCP
snippets in MAAS.
dnsresource Manage dnsresource.
dnsresource-record Manage dnsresourcerecord.
dnsresource-records
Manage DNS resource records (e.g. CNAME,
MX, NS, SRV, TXT)
dnsresources Manage dnsresources.
device Manage an individual device.
devices Manage the collection of all the devices
in the MAAS.
discoveries Query observed discoveries.
discovery Read or delete an observed discovery.
domain Manage domain.
domains Manage domains.
events Retrieve filtered node events.
fabric Manage fabric.
fabrics Manage fabrics.
fan-network Manage Fan Network.
fan-networks Manage Fan Networks.
file Manage a FileStorage object.
files Manage the collection of all the files in
this MAAS.
ipaddresses Manage IP addresses allocated by MAAS.
iprange Manage IP range.
ipranges Manage IP ranges.
interface Manage a node's or device's interface.
interfaces Manage interfaces on a node.
license-key Manage a license key.
license-keys Manage the license keys.
maas Manage the MAAS server.
machine Manage an individual machine.
machines Manage the collection of all the machines
in the MAAS.
network Manage a network.
networks Manage the networks.
node Manage an individual Node.
node-results Read the collection of commissioning
script results.
node-script Manage or view a custom script.
node-script-result Manage node script results.
node-script-results
Manage node script results.
node-scripts Manage custom scripts.
nodes Manage the collection of all the nodes in
the MAAS.
notification Manage an individual notification.
notifications Manage the collection of all the
notifications in MAAS.
package-repositories
Manage the collection of all Package
Repositories in MAAS.
package-repository Manage an individual package repository.
partition Manage partition on a block device.
partitions Manage partitions on a block device.
pod Manage an individual pod.
pods Manage the collection of all the pod in
the MAAS.
rack-controller Manage an individual rack controller.
rack-controllers Manage the collection of all rack
controllers in MAAS.
raid Manage a specific RAID (Redundant Array
of Independent Disks) on a machine.
raids Manage all RAIDs (Redundant Array of
Independent Disks) on a machine.
region-controller Manage an individual region controller.
region-controllers Manage the collection of all region
controllers in MAAS.
resource-pool Manage a resource pool.
resource-pools Manage resource pools.
sshkey Manage an SSH key.
sshkeys Manage the collection of all the SSH keys
in this MAAS.
sslkey Manage an SSL key.
sslkeys Operations on multiple keys.
space Manage space.
spaces Manage spaces.
static-route Manage static route.
static-routes Manage static routes.
subnet Manage subnet.
subnets Manage subnets.
tag Tags are properties that can be
associated with a Node and serve as
criteria for selecting and allocating
nodes.
tags Manage all tags known to MAAS.
user Manage a user account.
users Manage the user accounts of this MAAS.
version Information about this MAAS instance.
vlan Manage a VLAN on a fabric.
vlans Manage VLANs on a fabric.
vm-host Manage an individual vm-host.
vm-hosts Manage the collection of all the vm-hosts
in the MAAS.
vmfs-datastore Manage VMFS datastore on a machine.
vmfs-datastores Manage VMFS datastores on a machine.
volume-group Manage volume group on a machine.
volume-groups Manage volume groups on a machine.
zone Manage a physical zone.
zones Manage physical zones.
This is a profile. Any commands you issue on this profile will
operate on the MAAS region server.
The command information you see here comes from the region
server's API; it may differ for different profiles. If you
believe the API may have changed, use the command's 'refresh'
sub-command to fetch the latest version of this help information
from the server.
You can see that the help is considerably more detailed when you log in and apply a profile name to the help request.
Setting DNS
The very first blank line you encounter in the MAAS UI is the DNS server IP address. In the UI, most people just type “8.8.8.8” (Google’s DNS server) and forget about it. But the CLI has no box, so how do you get there? Well, setting MAAS DNS is part of the set-config
commands:
stormrider@wintermute:~$ maas admin maas set-config \
name=upstream_dns value="8.8.8.8"
Success.
Machine-readable output follows:
OK
The value=
object does not have to be quoted, since it’s an IP address, which is continuous text without spaces — but it seems like a good habit to just type values in quotes.
Importing images
The next thing would be to import images. Looking at the dashboard, Ubuntu 18.04 has already been imported. We can bring in some other image (like Ubuntu 16.04 LTS) just to see how that works, and also confirm that the 18.04 (default) image is actually imported. We can check 18.04 with the following command:
stormrider@wintermute:~$ maas admin boot-resources read
Success.
Machine-readable output follows:
[
{
"id": 7,
"type": "Synced",
"name": "grub-efi-signed/uefi",
"architecture": "amd64/generic",
"resource_uri": "/MAAS/api/2.0/boot-resources/7/"
},
{
"id": 8,
"type": "Synced",
"name": "grub-efi/uefi",
"architecture": "arm64/generic",
"resource_uri": "/MAAS/api/2.0/boot-resources/8/"
},
{
"id": 9,
"type": "Synced",
"name": "grub-ieee1275/open-firmware",
"architecture": "ppc64el/generic",
"resource_uri": "/MAAS/api/2.0/boot-resources/9/"
},
{
"id": 10,
"type": "Synced",
"name": "pxelinux/pxe",
"architecture": "i386/generic",
"resource_uri": "/MAAS/api/2.0/boot-resources/10/"
},
{
"id": 1,
"type": "Synced",
"name": "ubuntu/bionic",
"architecture": "amd64/ga-18.04",
"resource_uri": "/MAAS/api/2.0/boot-resources/1/",
"subarches": "generic,hwe-p,hwe-q,hwe-r,hwe-s,hwe-t,hwe-u,hwe-v,hwe-w,ga-16.04,ga-16.10,ga-17.04,ga-17.10,ga-18.04"
},
{
"id": 2,
"type": "Synced",
"name": "ubuntu/bionic",
"architecture": "amd64/ga-18.04-lowlatency",
"resource_uri": "/MAAS/api/2.0/boot-resources/2/",
"subarches": "generic,hwe-p,hwe-q,hwe-r,hwe-s,hwe-t,hwe-u,hwe-v,hwe-w,ga-16.04,ga-16.10,ga-17.04,ga-17.10,ga-18.04"
},
{
"id": 3,
"type": "Synced",
"name": "ubuntu/bionic",
"architecture": "amd64/hwe-18.04",
"resource_uri": "/MAAS/api/2.0/boot-resources/3/",
"subarches": "generic,hwe-p,hwe-q,hwe-r,hwe-s,hwe-t,hwe-u,hwe-v,hwe-w,ga-16.04,ga-16.10,ga-17.04,ga-17.10,ga-18.04"
},
{
"id": 4,
"type": "Synced",
"name": "ubuntu/bionic",
"architecture": "amd64/hwe-18.04-edge",
"resource_uri": "/MAAS/api/2.0/boot-resources/4/",
"subarches": "generic,hwe-p,hwe-q,hwe-r,hwe-s,hwe-t,hwe-u,hwe-v,hwe-w,ga-16.04,ga-16.10,ga-17.04,ga-17.10,ga-18.04,hwe-18.10,hwe-19.04"
},
{
"id": 5,
"type": "Synced",
"name": "ubuntu/bionic",
"architecture": "amd64/hwe-18.04-lowlatency",
"resource_uri": "/MAAS/api/2.0/boot-resources/5/",
"subarches": "generic,hwe-p,hwe-q,hwe-r,hwe-s,hwe-t,hwe-u,hwe-v,hwe-w,ga-16.04,ga-16.10,ga-17.04,ga-17.10,ga-18.04"
},
{
"id": 6,
"type": "Synced",
"name": "ubuntu/bionic",
"architecture": "amd64/hwe-18.04-lowlatency-edge",
"resource_uri": "/MAAS/api/2.0/boot-resources/6/",
"subarches": "generic,hwe-p,hwe-q,hwe-r,hwe-s,hwe-t,hwe-u,hwe-v,hwe-w,ga-16.04,ga-16.10,ga-17.04,ga-17.10,ga-18.04,hwe-18.10,hwe-19.04"
}
]
That’s a lot of information, but it looks like several 18.04 images downloaded and synched. You can use grep
to simplify that output:
stormrider@wintermute:~$ maas admin boot-resources read \
| grep architecture
"architecture": "amd64/generic",
"architecture": "arm64/generic",
"architecture": "ppc64el/generic",
"architecture": "i386/generic",
"architecture": "amd64/ga-18.04",
"architecture": "amd64/ga-18.04-lowlatency",
"architecture": "amd64/hwe-18.04",
"architecture": "amd64/hwe-18.04-edge",
"architecture": "amd64/hwe-18.04-lowlatency",
"architecture": "amd64/hwe-18.04-lowlatency-edge",
That definitely confirms 18.04. But what are those three or four on top? Looking at the massive JSON output, we can see that they have names like “open-firmware,” “uefi,” and “pxe.” Okay, so those are images that can PXE-boot machines, basically. But how could we sort this information out in a neat way?
enter jq
If you’re going to use the MAAS CLI — or anything with JSON-based output — you’ll want to consider learning the command line tool jq. It’s quite handy for parsing the JSON output of the MAAS CLI. So, for example, if we want a formatted table of names and architectures, we can run the last command through jq
like this:
stormrider@wintermute:~$ maas admin boot-resources read \
| jq -r '.[] | "\(.name)\t\(.architecture)"'
grub-efi-signed/uefi amd64/generic
grub-efi/uefi arm64/generic
grub-ieee1275/open-firmware ppc64el/generic
pxelinux/pxe i386/generic
ubuntu/bionic amd64/ga-18.04
ubuntu/bionic amd64/ga-18.04-lowlatency
ubuntu/bionic amd64/hwe-18.04
ubuntu/bionic amd64/hwe-18.04-edge
ubuntu/bionic amd64/hwe-18.04-lowlatency
ubuntu/bionic amd64/hwe-18.04-lowlatency-edge
So you can see that we basically have (a) the images we need to boot machines, and (b) an 18.04 image (set) to deploy. That’s a good start, but let’s see if we can pull down another image with the CLI. We can select images with the boot-source-selections
command, so let’s try that with “Trusty” (Xenial Xerus, aka 16.04):
stormrider@wintermute:~$ maas admin boot-source-selections \
create 1 os="ubuntu" release="trusty" arches="amd64" \
subarches="*" labels="*"
Success.
Machine-readable output follows:
{
"os": "ubuntu",
"release": "trusty",
"arches": [
"amd64"
],
"subarches": [
"*"
],
"labels": [
"*"
],
"boot_source_id": 1,
"id": 2,
"resource_uri": "/MAAS/api/2.0/boot-sources/1/selections/2/"
}
You repeat the maas admin boot-resources read
command above to confirm that you’ve captured the 16.04 versions. Importing them is now a fairly simple command:
stormrider@wintermute:~$ maas admin boot-resources import
Success.
Machine-readable output follows:
Import of boot resources started
This blog post is fairly long, so let’s pause here and continue the MAAS CLI operations process in the next post.