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.
Direct HTTP session access for advanced use cases requiring fine-grained control over MAAS API interactions.
Low-level HTTP session for making direct MAAS API calls.
from maas.client.bones import SessionAPI
class SessionAPI:
"""Low-level HTTP session for MAAS API."""
def __init__(self, description, credentials=None):
"""
Initialize session.
Args:
description (dict): Session description with URL and version info
credentials (Credentials, optional): OAuth credentials
"""
@classmethod
async def fromURL(cls, url, *, credentials=None, insecure=False):
"""
Create session from URL.
Args:
url (str): MAAS server URL
credentials (Credentials, optional): OAuth credentials
insecure (bool, optional): Disable SSL verification
Returns:
SessionAPI: Configured session
"""
@classmethod
def fromProfile(cls, profile):
"""
Create session from profile.
Args:
profile (Profile): Connection profile
Returns:
SessionAPI: Configured session
"""
@classmethod
def fromProfileName(cls, name):
"""
Create session from profile name.
Args:
name (str): Profile name
Returns:
SessionAPI: Configured session
Raises:
ProfileNotFound: If profile doesn't exist
"""
@classmethod
async def login(cls, url, *, username=None, password=None, insecure=False):
"""
Create session 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:
SessionAPI: Authenticated session
"""
@classmethod
async def connect(cls, url, *, apikey=None, insecure=False):
"""
Create session with API key authentication.
Args:
url (str): MAAS server URL
apikey (str, optional): API key
insecure (bool, optional): Disable SSL verification
Returns:
SessionAPI: Authenticated session
"""
@property
def is_anonymous(self):
"""Check if session is anonymous (no credentials)."""
@property
def credentials(self):
"""Get session credentials."""
@property
def description(self):
"""Get session description."""
@property
def handlers(self):
"""Get API handlers for making requests."""
@property
def session(self):
"""Get underlying aiohttp session."""Usage:
import asyncio
from maas.client.bones import SessionAPI
from maas.client.utils.creds import Credentials
async def use_bones_api():
# Create session from URL
session = await SessionAPI.fromURL(
'http://maas.example.com:5240/MAAS/',
credentials=Credentials('consumer', 'token', 'secret')
)
# Check session status
print(f"Anonymous: {session.is_anonymous}")
# Access handlers for API calls
handlers = session.handlers
# Use handlers to make direct API requests
# Create session from profile
session2 = SessionAPI.fromProfileName('production')
# Run async
asyncio.run(use_bones_api())Core Bones API exceptions:
from maas.client.bones import SessionError, CallError
class SessionError(Exception):
"""Raised for session-related errors."""
class CallError(Exception):
"""Raised when API call fails."""Connection and authentication exceptions from maas.client.bones.helpers:
from maas.client.bones.helpers import (
ConnectError,
LoginError,
LoginNotSupported,
PasswordWithoutUsername,
UsernameWithoutPassword,
RemoteError
)
class ConnectError(Exception):
"""
Raised when connection to MAAS server fails.
Common causes:
- Invalid URL
- Server not reachable
- Network connectivity issues
"""
class LoginError(Exception):
"""
Raised when login authentication fails.
Common causes:
- Invalid username or password
- Account locked or disabled
- Authentication service unavailable
"""
class LoginNotSupported(LoginError):
"""
Raised when the MAAS server doesn't support password-based login.
This can occur if:
- External authentication (LDAP, SAML) is required
- API-only authentication is enforced
"""
class PasswordWithoutUsername(ValueError):
"""Raised when password is provided without username."""
class UsernameWithoutPassword(ValueError):
"""Raised when username is provided without password."""
class RemoteError(Exception):
"""
Raised when MAAS server returns an error response.
Attributes:
status: HTTP status code
content: Error response content
"""Comprehensive error handling:
import asyncio
from maas.client.bones import SessionAPI, SessionError, CallError
from maas.client.bones.helpers import (
ConnectError,
LoginError,
LoginNotSupported,
PasswordWithoutUsername,
UsernameWithoutPassword,
RemoteError
)
async def connect_with_error_handling():
try:
# Attempt connection with API key
session = await SessionAPI.connect(
'http://maas.example.com:5240/MAAS/',
apikey='consumer:token:secret'
)
print("Connected successfully")
except ConnectError as e:
print(f"Connection failed: {e}")
print("Check URL and network connectivity")
except RemoteError as e:
print(f"Server error (status {e.status}): {e.content}")
print("Check API key validity")
except SessionError as e:
print(f"Session error: {e}")
async def login_with_error_handling():
try:
# Attempt login with credentials
session = await SessionAPI.login(
'http://maas.example.com:5240/MAAS/',
username='admin',
password='password'
)
print("Logged in successfully")
except PasswordWithoutUsername as e:
print("Password provided without username")
except UsernameWithoutPassword as e:
print("Username provided without password")
except LoginNotSupported as e:
print(f"Login not supported: {e}")
print("Server may require external authentication or API key")
except LoginError as e:
print(f"Login failed: {e}")
print("Check username and password")
except ConnectError as e:
print(f"Connection failed: {e}")
# Run examples
asyncio.run(connect_with_error_handling())
asyncio.run(login_with_error_handling())Use the Bones API when you need:
For most use cases, the high-level Facade API (via connect() or login()) is recommended.