Skip to content
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
28 changes: 28 additions & 0 deletions config.example/maas-inventory.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# MAAS Dynamic Inventory Configuration
#
# This file is copied to config/maas-inventory.yml by scripts/setup.sh.
# Edit your private copy there (config/ is gitignored).
#
# You can also set MAAS_INVENTORY_CONFIG=/path/to/config.yml or use
# environment variables (MAAS_API_URL, MAAS_API_KEY, etc.).
# Environment variables take precedence over config file values.

# MAAS API endpoint (required)
api_url: "http://<maas-server>:5240/MAAS/api/2.0"

# MAAS API key in consumer_key:token_key:token_secret format (required)
# Generate with: sudo maas apikey --username=<your-user>
# Or find in MAAS web UI: your profile -> API keys
api_key: "CONSUMER_KEY:TOKEN_KEY:TOKEN_SECRET"

# Default SSH user for all hosts (default: ubuntu)
ssh_user: "ubuntu"

# Preferred network prefix for selecting ansible_host IP (optional)
# Machines may have multiple IPs; this selects the one on your target network
#network: "10.0.0"

# SSH bastion/jumpbox for ProxyJump (optional)
# Only needed if target machines are on a private network that requires
# jumping through a bastion host. Leave commented out for direct access.
#ssh_bastion: "user@bastion-host"
133 changes: 128 additions & 5 deletions docs/pxe/maas.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ OS Provisioning with MAAS
- [Releasing and reinstalling the machine](#releasing-and-reinstalling-the-machine)
- [Scaling up](#scaling-up)
- [Creating a DGX OS image installable by MAAS](#creating-a-dgx-os-image-installable-by-maas)
- [Dynamic Inventory](#dynamic-inventory)

## Introduction

Expand All @@ -27,7 +28,7 @@ By default, this playbook will set up a single-node MAAS install which can then

In most cases, you will use MAAS to provision the OS on multiple bare-metal servers.
However, MAAS can also be used to provision VMs, and this guide will walk through an example using two virtual machines for ease of demonstration.
This guide was written using MAAS 2.8.
This guide was originally written using MAAS 2.8; current MAAS releases are 3.x.

MAAS has a lot of different configuration options which are outside the scope of this guide.
For the best reference on how to use MAAS in general, see the [documentation on maas.io](https://maas.io/docs).
Expand All @@ -36,7 +37,7 @@ For the best reference on how to use MAAS in general, see the [documentation on

In order to set up and use MAAS, you should at minimum have the following components:

- An Ubuntu 18.04 server which you can use to run MAAS
- An Ubuntu 22.04 or 24.04 server which you can use to run MAAS
- One or more servers which you will manage using MAAS
- A network connection between all the servers on which you can safely run DHCP. This is needed so that MAAS can provision IP addresses to the nodes it manages.
- A network connection which you can use to log into the MAAS server. This may be the same network as the inter-node network, or it may be a separate network.
Expand All @@ -47,7 +48,7 @@ In this example, we will use:

- An internal (VM-only) network on which we'll use the subnet `192.168.1.0/24`
- An external network connection on which we'll use the subnet `192.168.122.0/24`
- `maas-vm`, a pre-installed Ubuntu 18.04 virtual machine
- `maas-vm`, a pre-installed Ubuntu 22.04 (or 24.04) virtual machine
- `maas-vm` has IP `192.168.1.1` on the internal network, and `192.168.122.90` on the external network
- `test-vm`, a "blank" virtual machine with no OS, on the same VM host
- `test-vm` has a connection only to the internal network, which is not configured yet
Expand All @@ -72,7 +73,7 @@ Please consult your hypervisor documentation for instructions on doing this.
maas_dns_domain: 'deepops.local'
maas_region_controller: '192.168.1.1'
maas_region_controller_url: 'http://{{ maas_region_controller }}:5240/MAAS'
maas_repo: 'ppa:maas/2.8'
maas_repo: 'ppa:maas/3.5'
```
1. Run the Ansible playbook to install:
```bash
Expand Down Expand Up @@ -104,7 +105,7 @@ After entering SSH keys, you will be redirected to an intro configuration page o
- The source and versions of Ubuntu which will be downloaded by MAAS to install

In this example, I'm leaving all these parameters at their default values.
This will enable us to install Ubuntu 18.04 on the VM we are installing.
This will enable us to install Ubuntu on the VM we are provisioning.

MAAS will sync the necessary package repositories for the installation to your provisioning server (`maas-vm`), which may take some time.
If the repositories are still syncing, the "Continue" button at the bottom will be grayed out.
Expand Down Expand Up @@ -201,3 +202,125 @@ then commission them and provision them by selecting them as a group in the Mach

The official NVIDIA DGX OS version 5.0 and higher is installable by MAAS by creating a custom OS image.
The code is located in the `submodules/packer-maas` directory. For more information, see: https://github.com/DeepOps/packer-maas/tree/master/dgxos5

## Dynamic Inventory

DeepOps includes a dynamic inventory script that queries your MAAS server's
API to automatically discover deployed machines and map them to Ansible groups
using MAAS tags. This eliminates the need to manually edit `config/inventory`
when machines are provisioned, released, or reassigned.
Comment thread
dholt marked this conversation as resolved.

### Prerequisites

- A MAAS server with the REST API enabled (default port 5240)
- A MAAS API key (generate one from the MAAS web UI under your profile,
or run `sudo maas apikey --username=<your-user>` on the MAAS server)
- Python 3 on the Ansible control machine (no additional packages required)

### Setup

1. Run `scripts/setup.sh` (or manually copy `config.example/` to `config/`).

2. Edit `config/maas-inventory.yml` with your MAAS server details:

```yaml
api_url: "http://maas-server:5240/MAAS/api/2.0"
api_key: "consumer_key:token_key:token_secret"
ssh_user: "ubuntu"
```

3. Optionally set `network` to prefer a specific subnet when machines have
multiple IPs, and `ssh_bastion` if your machines are behind a jumpbox:

```yaml
network: "10.0.0"
ssh_bastion: "user@bastion-host"
```

4. Test the inventory:

```bash
./scripts/maas_inventory.py --list
ansible -i scripts/maas_inventory.py all -m ping
```

### Tag-Based Group Assignment

The script maps MAAS tags directly to Ansible groups. To assign a machine to
the `[slurm-master]` group, tag it `slurm-master` in MAAS. A machine can
have multiple tags and will appear in all corresponding groups.

DeepOps parent groups (`slurm-cluster`, `k8s-cluster`, etc.) are
automatically created with the correct `children` relationships, so you
only need to tag leaf groups.

**Recommended tags** (matching DeepOps inventory groups):

| Tag | Ansible Group | Used By |
|-----|--------------|---------|
| `kube-master` | `[kube-master]` | K8s control plane |
| `kube-node` | `[kube-node]` | K8s worker nodes |
| `slurm-master` | `[slurm-master]` | Slurm head node |
| `slurm-node` | `[slurm-node]` | Slurm compute nodes |
| `slurm-nfs` | `[slurm-nfs]` | Slurm NFS server |

**Example: switching between Slurm and K8s testing:**

```bash
# Tag machines for Slurm
maas admin tag update-nodes slurm-master add=<vm01_system_id>
maas admin tag update-nodes slurm-node add=<vm02_system_id> add=<vm03_system_id>

# Run Slurm deployment
ansible-playbook -i scripts/maas_inventory.py playbooks/slurm-cluster.yml

# Later, retag for K8s
maas admin tag update-nodes slurm-master remove=<vm01_system_id>
maas admin tag update-nodes kube-master add=<vm01_system_id>
maas admin tag update-nodes kube-node add=<vm02_system_id> add=<vm03_system_id>

# Run K8s deployment
ansible-playbook -i scripts/maas_inventory.py playbooks/k8s-cluster.yml
```

### Configuration Reference

Configuration is loaded from environment variables or `config/maas-inventory.yml`.
Environment variables take precedence.

| Config Key | Env Variable | Required | Description |
|-----------|-------------|----------|-------------|
| `api_url` | `MAAS_API_URL` | Yes | MAAS API endpoint |
| `api_key` | `MAAS_API_KEY` | Yes | OAuth1 API key (`consumer:token:secret`) |
| `ssh_user` | `MAAS_SSH_USER` | No | SSH user (default: `ubuntu`) |
| `network` | `MAAS_NETWORK` | No | Preferred IP network prefix |
| `ssh_bastion` | `MAAS_SSH_BASTION` | No | SSH bastion for ProxyJump |

### Host Variables

The script exposes MAAS metadata as Ansible host variables:

| Variable | Example | Description |
|----------|---------|-------------|
| `maas_system_id` | `4fcb8q` | MAAS machine ID |
| `maas_fqdn` | `node01.maas` | Fully qualified domain name |
| `maas_os` | `ubuntu` | Operating system |
| `maas_distro` | `noble` | Distribution series |
| `maas_tags` | `["slurm-master", "virtual"]` | All tags on the machine |
| `maas_cpus` | `4` | CPU count |
| `maas_memory_mb` | `8192` | Memory in MB |
| `maas_arch` | `amd64/generic` | Architecture |
| `maas_zone` | `default` | MAAS availability zone |
| `maas_pool` | `default` | MAAS resource pool |

### Static vs Dynamic Inventory

You can use either approach:

- **Static** (`config/inventory`): Manually list hosts and groups. Simpler
for fixed environments. This is the default set up by `scripts/setup.sh`.
- **Dynamic** (`scripts/maas_inventory.py`): Auto-discovers machines from
MAAS. Better for environments where machines are frequently provisioned
or reassigned.

Both can be combined by passing multiple `-i` flags to `ansible-playbook`.
Loading
Loading