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.
Object-oriented API with rich domain objects for advanced manipulation of MAAS resources. Provides more control than the Facade API while maintaining a structured approach.
Entry point for the Viscera API, similar to the high-level Client but with object-oriented resource access.
from maas.client.viscera import Origin
class Origin:
"""Entry point for viscera API."""
@classmethod
async def fromURL(cls, url, *, credentials=None, insecure=False):
"""
Create origin from URL.
Args:
url (str): MAAS server URL
credentials (Credentials, optional): OAuth credentials
insecure (bool, optional): Disable SSL verification
Returns:
Origin: Configured origin object
"""
@classmethod
def fromProfile(cls, profile):
"""
Create origin from profile.
Args:
profile (Profile): Connection profile
Returns:
Origin: Configured origin object
"""
@classmethod
def fromProfileName(cls, name):
"""
Create origin from profile name.
Args:
name (str): Profile name
Returns:
Origin: Configured origin object
"""
@classmethod
async def login(cls, url, *, username=None, password=None, insecure=False):
"""
Create origin with username/password authentication.
Args:
url (str): MAAS server URL
username (str, optional): Username
password (str, optional): Password
insecure (bool, optional): Disable SSL verification
Returns:
Origin: Authenticated origin object
"""
@classmethod
async def connect(cls, url, *, apikey=None, insecure=False):
"""
Create origin with API key authentication.
Args:
url (str): MAAS server URL
apikey (str, optional): API key
insecure (bool, optional): Disable SSL verification
Returns:
Origin: Authenticated origin object
"""Usage:
import asyncio
from maas.client.viscera import Origin
async def use_viscera_api():
# Connect with API key
origin = await Origin.connect(
'http://maas.example.com:5240/MAAS/',
apikey='consumer:token:secret'
)
# Access resource collections through origin
# origin.Machines, origin.Devices, etc.
machines = await origin.Machines.read()
for machine in machines:
print(machine.hostname)
# Run async
asyncio.run(use_viscera_api())Foundation classes for building domain objects.
from maas.client.viscera import Object, ObjectSet, ObjectField, ObjectMethod, ObjectType
class Object:
"""
Base class for all MAAS domain objects.
Provides:
- save(): Save changes to server
- refresh(): Reload from server
- delete(): Delete object
"""
class ObjectSet:
"""
Base class for collections of objects.
Provides:
- read(**filters): Fetch multiple objects
- create(**kwargs): Create new object
"""
class ObjectField:
"""Field descriptor for object attributes."""
class ObjectMethod:
"""Method descriptor for object methods."""
class ObjectType:
"""Metaclass for MAAS objects."""Helper functions for field validation and transformation.
from maas.client.viscera import (
check,
check_optional,
to,
parse_timestamp,
mapping_of
)
def check(expected):
"""
Create validator that checks type matches expected.
Args:
expected: Expected type or types
Returns:
Validator function
"""
def check_optional(expected):
"""
Create validator that checks optional type.
Args:
expected: Expected type or types
Returns:
Validator function
"""
def to(cls):
"""
Create converter that transforms value to class instance.
Args:
cls: Target class
Returns:
Converter function
"""
def parse_timestamp(created):
"""
Parse ISO 8601 timestamp string.
Args:
created (str): ISO timestamp
Returns:
datetime: Parsed datetime object
"""
def mapping_of(cls):
"""
Create validator for mappings of class instances.
Args:
cls: Expected value class
Returns:
Validator function
"""from maas.client.viscera import find_objects
def find_objects(modules):
"""
Find all Object subclasses in modules.
Args:
modules (list): List of modules to search
Returns:
dict: Mapping of class names to classes
"""All Viscera objects follow this pattern:
Machines, Devices, Subnets, etc.read(), create()Machine, Device, Subnet, etc.save(), refresh(), delete()Example:
# Collection access
machines = await origin.Machines.read()
# Instance operations
machine = machines[0]
machine.hostname = 'new-name'
await machine.save()
await machine.refresh()
await machine.delete()
# Domain-specific methods
await machine.deploy(distro_series='jammy')
await machine.power_on()Use Viscera when you need:
For most use cases, the high-level Facade API is recommended. Use Viscera for advanced scenarios requiring object-level control.