tessl install tessl/pypi-python-libmaas@0.6.0Python client library for MAAS 2.0+ with sync/async support, providing machine provisioning, network management, and storage configuration.
Manage operating system images and boot sources for machine deployment.
Operating system images available for deployment.
client.boot_resources.list()
client.boot_resources.get(id)
client.boot_resources.create(**params)
client.boot_resources.start_import()
client.boot_resources.stop_import()from maas.client import connect
client = connect('http://maas.example.com:5240/MAAS/', apikey='key')
# List boot resources
resources = client.boot_resources.list()
for resource in resources:
print(f"{resource.name}: {resource.architecture}")
# Get specific resource
resource = client.boot_resources.get(1)
# Start importing boot resources
client.boot_resources.start_import()
# Stop import
client.boot_resources.stop_import()Boot resource properties:
id (int, readonly): Unique resource identifier (primary key)name (str, readonly): OS name in format 'os/release' (e.g., 'ubuntu/focal', 'ubuntu/jammy')architecture (str, readonly): Architecture in format 'arch/subarch' (e.g., 'amd64/generic', 'arm64/generic')title (str, readonly): Human-readable titletype (str, readonly): Resource type (e.g., 'synced', 'uploaded')subarches (str, readonly): Supported sub-architectures (e.g., 'generic,hwe-20.04')sets (dict[str, BootResourceSet], readonly): Dictionary of resource sets keyed by versionImportant Notes:
start_import()/stop_import()), not manual creation.create() method exists for uploading custom boot images, but most users should use the import process.A BootResourceSet represents a specific version or build of a boot resource. Each set contains one or more files.
class BootResourceSet:
"""A boot resource set (nested within BootResource)."""
version (str, readonly): Version identifier (e.g., '20220420', build date/time)
size (int, readonly): Total size of all files in bytes
label (str, readonly): Label (e.g., 'release', 'daily')
complete (bool, readonly): Whether all files are fully downloaded
files (dict[str, BootResourceFile], readonly): Dictionary of files keyed by filename# Access boot resource sets
resource = client.boot_resources.get(1)
for version, resource_set in resource.sets.items():
print(f"Version: {version}")
print(f" Size: {resource_set.size} bytes")
print(f" Label: {resource_set.label}")
print(f" Complete: {resource_set.complete}")
print(f" Files: {len(resource_set.files)}")A BootResourceFile represents an individual file within a boot resource set (e.g., kernel, initrd, root filesystem).
class BootResourceFile:
"""A boot resource file (nested within BootResourceSet)."""
filename (str, readonly): Filename (e.g., 'boot-kernel', 'boot-initrd', 'root-tgz')
filetype (str, readonly): File type ('tgz', 'ddtgz', etc.)
size (int, readonly): File size in bytes
sha256 (str, readonly): SHA256 checksum of the file
complete (bool, readonly): Whether file is fully downloaded# Access boot resource files
resource = client.boot_resources.get(1)
for version, resource_set in resource.sets.items():
print(f"\nVersion: {version}")
for filename, rfile in resource_set.files.items():
print(f" File: {filename}")
print(f" Type: {rfile.filetype}")
print(f" Size: {rfile.size} bytes")
print(f" SHA256: {rfile.sha256}")
print(f" Complete: {rfile.complete}")While most boot resources are synced from remote sources, you can upload custom images:
import io
# Prepare custom image content
with open('/path/to/custom-image.tgz', 'rb') as f:
content = io.BytesIO(f.read())
# Upload custom boot resource
resource = await client.boot_resources.create(
name='custom/image',
architecture='amd64/generic',
content=content,
title='Custom Boot Image',
filetype=BootResourceFileType.TGZ
)
print(f"Uploaded resource: {resource.name}")
print(f"Resource ID: {resource.id}")Sources for downloading boot resources.
client.boot_sources.list()
client.boot_sources.get(id)
BootSource.read(id)
client.boot_sources.create(url, keyring_filename=None, keyring_data=None)
boot_source.save()
boot_source.delete()# List boot sources
sources = client.boot_sources.list()
# Get specific source
source = client.boot_sources.get(1)
# Or use BootSource.read()
from maas.client.viscera import BootSource
source = await BootSource.read(1)
# Create custom boot source
source = await client.boot_sources.create(
url='http://images.maas.io/ephemeral-v3/stable/',
keyring_filename='/usr/share/keyrings/ubuntu-cloudimage-keyring.gpg'
)
# Create boot source with keyring data
import io
with open('/path/to/keyring.gpg', 'rb') as f:
keyring_data = f.read()
source = await client.boot_sources.create(
url='http://custom-mirror.example.com/images/',
keyring_data=io.BytesIO(keyring_data)
)
# Update boot source
source.url = 'http://updated-mirror.example.com/images/'
await source.save()
# Delete boot source
await source.delete()Boot source properties:
id (int, readonly): Unique source identifierurl (str): Source URLkeyring_filename (str): Path to keyring file on serverkeyring_data (str): GPG keyring datacreated (datetime, readonly): Creation timestampupdated (datetime, readonly): Last update timestampControl which OS images are imported from boot sources.
BootSourceSelections.read(boot_source)
BootSourceSelections.create(boot_source, os, release, arches=None, subarches=None, labels=None)
BootSourceSelection.read(boot_source, id)
selection.save()
selection.delete()from maas.client.viscera import BootSourceSelection, BootSourceSelections
# Get boot source
boot_source = client.boot_sources.get(1)
# List selections for boot source
selections = await BootSourceSelections.read(boot_source)
for selection in selections:
print(f"{selection.os}/{selection.release}: {selection.arches}")
# Get specific selection
selection = await BootSourceSelection.read(boot_source, 1)
# Create selection for Ubuntu 22.04 on amd64
selection = await BootSourceSelections.create(
boot_source,
os='ubuntu',
release='jammy',
arches=['amd64'],
subarches=['*'],
labels=['release']
)
# Create selection with wildcards (import all)
selection = await BootSourceSelections.create(
boot_source,
os='*',
release='*',
arches=['*'],
subarches=['*'],
labels=['*']
)
# Create selection for specific architectures
selection = await BootSourceSelections.create(
boot_source,
os='ubuntu',
release='focal',
arches=['amd64', 'arm64'],
subarches=['generic', 'hwe-20.04'],
labels=['release', 'daily']
)
# Update selection
selection.arches = ['amd64', 'arm64', 'ppc64el']
await selection.save()
# Delete selection
await selection.delete()Boot Source Selection properties:
id (int, readonly): Unique selection identifierboot_source (BootSource, readonly): Parent boot sourceos (str): Operating system to import (e.g., 'ubuntu', '*' for all)release (str): OS release to import (e.g., 'focal', 'jammy', '*' for all)arches (list): List of architectures (e.g., ['amd64', 'arm64'] or ['*'])subarches (list): List of sub-architectures (e.g., ['generic'] or ['*'])labels (list): List of image labels (e.g., ['release', 'daily'] or ['*'])Common use cases:
# Import only LTS releases for amd64
await BootSourceSelections.create(
boot_source,
os='ubuntu',
release='focal', # Or 'jammy', 'noble', etc.
arches=['amd64'],
subarches=['*'],
labels=['release']
)
# Import all Ubuntu releases, all architectures
await BootSourceSelections.create(
boot_source,
os='ubuntu',
release='*',
arches=['*'],
subarches=['*'],
labels=['*']
)
# Import specific daily builds for testing
await BootSourceSelections.create(
boot_source,
os='ubuntu',
release='noble',
arches=['amd64'],
subarches=['*'],
labels=['daily']
)