# LAA manager (aka. laam) - Python3 The LAA Manager is a python application that allows to interact with the LAA REST API. This is the documentation to use `laam` in a python script. ```{admonition} LAA manager v0.8.3 :class: warning The documentation refers to `laam v0.8.3`. [Version notes at the bottom](#version-notes) ``` ## Installation laam is available from [PyPI](https://pypi.org/project/laam): ```console python3 -m venv venv source venv/bin/activate python3 -m pip install --upgrade laam laam --help laam --version ``` ## Configuration You can create identities via [console](/software/laam_console.md#configuration) The identities can then be used in this way: ````console import laam LAA_1 = laam.LAA("identity-1"); ```` ```{admonition} Local Commands :class: note "local" commands are not defined for python. ``` ## LAA class ````{py:class} laam.LAA Main Abstraction class to interact with a Linaro Automation Appliance. This class provides the core object model and methods required to remotely interact with an LAA from the host machine using LAAM. It abstracts the underlying communication protocols (e.g., REST, WebSockets) necessary to control the Appliance's primary functions to control the Device Under Test mounted on the LAA itself. The functions include power cycling, logs, usb control, serial interaction, etc... ```{py:method} __init__(self, laa_identity="default") Initializes the interface object for the target LAA. This method prepares the interface object using the provided identity. The identity is critical for addressing and authenticating a specific LAA ** Authentication Note ** To authenticate and enable control, you must: 1. Create an API token on the LAA 2. Manually configure the LAAM environment to use the token **Parameters:** - **laa_identity** (*str*): A required unique string identifier the target LAA ``` ```` ## Properties, Classes, and Methods ### identities There is no `identities` property. `identities` commands are supposed to be configured manually via the console interface, not through automated Python scripts. ### dut There is no `dut` property. Device configuration files are supposed to be configured manually via the console interface, not through automated Python scripts. ### files Manage files in `/var/lib/lava/dispatcher/tmp` on the LAA. ```{py:property} laam.LAA.files Interface for remote file management on the LAA. Based on the class `Files`. help(laam.LAA.Files) for more info. ``` ````{py:class} laam.LAA.Files Class for file management and transfer on the LAA. NOTE: This class should NOT be instantiated directly by the user. Access to these functions is available only via the main LAA object.. ```{py:method} list(self) -> list Lists all the files in the working folder. Returns: - A list of file names. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} pull(self, name: str, file: pathlib.Path, force: bool = False) -> bool Downloads a file from the LAA the working folder to the local machine. Args: - **name** (**str**): The name of the file on the LAA to be downloaded. - **file** (**pathlib.Path**): The file path to save the file downloaded from the LAA. Returns: - **bool**: True if the file was downloaded successfully, False otherwise. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} push(self, name: str, file) -> bool Uploads a file from local machine to the LAA the working folder. Args: - **name** (**str**): The name of the file to be saved on the LAA as. - **file** (**str**, **pathlib.Path**, **os.PathLike**, **io.BufferedReader**): The file on the local machine to be uploaded. It can be a path to the object file itself. Returns: - **bool**: True if the file was uploaded successfully, False otherwise. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} remove(self, name: str) -> bool Removes a file in the LAA the working folder. Args: - **name** (**str**): The name of the file to be removed. Returns: - **bool**: True if the file was removed successfully, False otherwise. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```` ### laacli Execute [laacli](/software/laacli.md) commands on the LAA. ```{py:property} laam.LAA.laacli Interface for executing laacli commands. Based on the class `LAACli`. help(laam.LAA.LAACli) for more info. ``` ````{py:class} laam.LAA.LAACli Class for executing laacli commands on the LAA. NOTE: This class should NOT be instantiated directly by the user. Access to these functions is available only via the main LAA object.. ```{py:method} button(self, button: str, state: str) -> dict Controls the virtual buttons on the LAA. Args: - **button** (**str**): The virtual button to control. Available choices are: "1", "2", "power", "reset". - **state** (**str**): State to set on the button. Available choices are: "on", "off", "status". Returns: - **dict**: Returned command execution object. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} led(self, state: str) -> dict Controls the status LED on the LAA. Args: - **state** (**str**): The state of the LED. Available choices are: "on", "off". Returns: - **dict**: Returned command execution object Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} power(self, vbus: str, state: str) -> dict Controls the power rails on the LAA. Args: - **vbus** (**str**): Power rail to control. Available choices are: "1v8", "3v3", "5v", "12v". - **state** (**str**): State to set the rail. Available choices are: "on", "off", "reset", "status". Returns: - **dict**: Returned command execution object. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} rev(self) -> dict Returns the hardware revision of the LAA. Returns: - **dict**: Returned revision object. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} screenshot(self, filename) -> dict Screenshots the current OLED and downloads it as a file on the local machine. Args: - **filename** (**str**, **os.PathLike**, **pathlib.Path**, **io.BufferedWriter**): It can be the file path to save the file downloaded from the LAA, or the opened file object itself. Returns: - **dict**: Returned command execution object. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} temp(self, probe: str) -> dict Returns temperature information from the LAA. Args: - **probe** (**str**): Temperature probe to check. Available choices are: "amb", "dut", "sys". Returns: - **dict**: Temperature information. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} usb(self, port: int, state: str) -> dict Controls the four USB ports on the LAA (the ones pointing upwards). Args: - **port** (**int**): USB port to control. Available choices are: 0, 1, 2, 3, 4. Where 0 is the USB Hub controlling USB ports 1, 2, 3, 4. - **state** (**str**): State to set the port or just check the status. Available choices are: "on", "off", "reset", "start", "status". Returns: - **dict**: Returned command execution object. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} usbg_ms(self, state: str, filename: str = "") -> dict Controls the USBG-MS port on the LAA (the ones at the front marked as USB-OTG). Args: - **state** (**str**): State to set the port or just check the status. Available choices are: "on", "off", "status". - **filename** (**str**): File name of the image to be used, It is assumed to be located in the working LAA folder. Parameter needed only if the status is set to "on". Returns: - **dict**: Returned command execution object. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} watt(self, vbus: str) -> dict Returns power usage information from the LAA. Args: - **vbus** (**str**): Power rail to check. Available choices are: "1v8", "3v3", "5v", "12v". Returns: - **dict**: Power usage information. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```` ### network Manage LAA network configuration ```{py:property} laam.LAA.network Interface for monitoring the LAA's network interfaces. Based on the class `Network`. help(laam.LAA.Network) for more info. ``` ````{py:class} laam.LAA.Network Class for monitoring the LAA's network interfaces. NOTE: This class should NOT be instantiated directly by the user. Access to these functions is available only via the main LAA object.. ```{py:method} addresses(self) -> dict Returns the addresses of the LAA. Returns: - **dict**: Addresses information. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} hostname(self) -> dict Returns the hostname of the LAA. Returns: - **dict**: Returns the hostname. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} interfaces(self) -> list Returns the interfaces of the LAA. Returns: - **list**: Returns the interfaces. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} routes(self) -> dict Returns the network routes of the LAA. Returns: - **dict**: Returns the routes. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} settings(self) -> str Returns the network settings of the LAA. Returns: - **str**: Returns the settings. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```` ### serials List and interact with the different [serial consoles](/guides/device_type_enablement.md#ser2net-configuration) provided by the LAA. ```{py:property} laam.LAA.serials Interface for managing and interacting with the LAA's serial consoles. Based on the class `Serials`. help(laam.LAA.Serials) for more info. ``` ````{py:class} laam.LAA.Serials Class for managing and interacting with the LAA's serial consoles with the DUT. NOTE: This class should NOT be instantiated directly by the user. Access to these functions is available only via the main LAA object.. ```{py:method} list(self, ser_filter=None) -> list Lists all the serials accessible via the LAA. Args: - **ser_filter**: Filter value to log out specific serials. Returns: - **list**: Returns a list of serials. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} get(self, name: str) -> dict Returns the details of a specific serial console. Args: - **name** (**str**): Name of the serial console, example "ttyUSB0". Returns: - **dict**: Returns serial information. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} connect_async_fun( self, name: str, readonly: bool = False, istream: io.TextIOBase = sys.stdin, ostream: io.TextIOBase = sys.stdout, force_str: Optional[bool] = None ) -> int Connects to a serial console with the DUT in an async function. Args: - **name** (**str**): Name of the serial console, example "ttyUSB0". - **readonly** (**bool**): True to start a readonly serial connection. (Default) False for an interactive connection - **istream** (**io.TextIOBase**): Input stream used to send data to the DUT on the LAA. Defaults to sys.stdin. - **ostream** (**io.TextIOBase**): Output stream used to receive data from the DUT on the LAA. Defaults to sys.stdout. - **force_str** (**Optional[bool]**): True to exchange data as string. False to exchange data as bytes. (Default) None to automatically use the best option. Exposed mostly for testing purposes. Returns: - **int**: 0 if the serial connection completed by itself without errors. 1 if it failed or got interrupted. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} connect_async( self, name: str, readonly: bool = False, istream: io.TextIOBase = sys.stdin, ostream: io.TextIOBase = sys.stdout, force_str: Optional[bool] = None ) -> asyncio.Task Connects to a serial console with the DUT in an async task. Basically a wrapper for connect_async_fun that returns the task. Args: - **name** (**str**): Name of the serial console, example "ttyUSB0". - **readonly** (**bool**): True to start a readonly serial connection. (Default) False for an interactive connection - **istream** (**io.TextIOBase**): Input stream used to send data to the DUT on the LAA. Defaults to sys.stdin. - **ostream** (**io.TextIOBase**): Output stream used to receive data from the DUT on the LAA. Defaults to sys.stdout. - **force_str** (**Optional[bool]**): True to exchange data as string. False to exchange data as bytes. (Default) None to automatically use the best option. Exposed mostly for testing purposes. Returns: - **asyncio.Task**: Returns an async tasks that can be easily managed. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} connect_pexpect( self, name: str, readonly: bool = False ) -> laam.utils.ConnectPexpect Connects to a serial console with the DUT in an Pexpect object. Args: - **name** (**str**): Name of the serial console, example "ttyUSB0". - **readonly** (**bool**): True to start a readonly serial connection. (Default) False for an interactive connection. Returns: - **laam.utils.ConnectPexpect**: Custom Pexpect object. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```` ### services Monitor systemd services running on the LAA. ```{py:property} laam.LAA.services Interface for monitoring system services on the LAA. Based on the class `Services`. help(laam.LAA.Services) for more info. ``` ````{py:class} laam.LAA.Services Class for monitoring system services on the LAA. NOTE: This class should NOT be instantiated directly by the user. Access to these functions is available only via the main LAA object.. ```{py:method} list(self) -> list Lists all the services on the LAA. Returns: - **list**: Returns a list of services. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} logs(self, name: str) -> list Returns the logs of a specific service. Args: - **name** (**str**): Name of the service. Returns: - **list**: Returns logs information. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```` ### system Display LAA system information. ```{py:property} laam.LAA.system Interface for general system-level monitoring. Based on the class `System`. help(laam.LAA.System) for more info. ``` ````{py:class} laam.LAA.System Class for general system-level monitoring. NOTE: This class should NOT be instantiated directly by the user. Access to these functions is available only via the main LAA object.. ```{py:method} version(self) -> list Returns the OS software version on the LAA. Returns: - **str**: Returns the version. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} fleet(self) -> list Returns information of the fleet that the LAA is registered with. Returns: - **dict**: Returns fleet information. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} logs(self) -> list Returns system logs from the LAA. Returns: - **list**: Returns logs. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```` ### usbs Display usb devices. ```{py:property} laam.LAA.usbs Interface for monitoring the LAA's USB sub-system. Based on the class `USBs`. help(laam.LAA.USBs) for more info. ``` ````{py:class} laam.LAA.USBs Class for monitoring the LAA's USB sub-system. NOTE: This class should NOT be instantiated directly by the user. Access to these functions is available only via the main LAA object.. ```{py:method} list(self) -> list Lists all the active usb connections seen by the operating system. Returns: - **list**: Returns a list of active usb connections with bus and device details. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} get(self, bus: str, device: str) -> str Get details of a USB device on a particular bus. Args: - **bus** (**str**): Name of the bus to look into. - **device** (**str**): Name of the device to get details of. Returns: - **str**: Returns the details of the device. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```` ### workers Manage LAVA workers running on the LAA. ```{py:property} laam.LAA.workers Interface for monitoring workers on the LAA. Based on the class `Workers`. help(laam.LAA.Workers) for more info. ``` ````{py:class} laam.LAA.Workers Class for monitoring workers on the LAA. NOTE: This class should NOT be instantiated directly by the user. Access to these functions is available only via the main LAA object.. ```{py:method} dockerfile(self, worker_id: int) -> str Returns the dockerfile of the specified worker. Args: - **worker_id** (**int**): identifier of the worker. Returns: - **str**: Returns a dockerfile content. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} list(self) -> list Lists all the workers active on the LAA. Returns: - **str**: Returns a list of workers with main information. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} logs(self, worker_id: int) -> list Returns the logs of the specified worker. Args: - **worker_id** (int): identifier of the worker. Returns: - **str**: Returns logs. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} get(self, worker_id: int) -> dict Returns details of the specified worker. Args: - **worker_id** (**int**): identifier of the worker. Returns: - **str**: Returns worker details. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```{py:method} test(self, worker_id: int) -> dict Returns the connection status of the worker with its LAVA instance. Args: - **worker_id** (**int**): identifier of the worker. Returns: - **str**: Returns connection status. Raises: - `LAAError`: If the LAA is offline or the request fails. ``` ```` ## Exceptions The following are the main exceptions that can be thrown by using an LAA object. ```{py:exception} LAAError(Exception) Base exception class for all LAA application errors. Attributes: - **message** (**str**): The detailed error message describing the issue. ``` ```{py:exception} LAAConnectionError(LAAError) Exception class for connection errors with the LAA (like wrong IP address or device offline). Attributes: - **message** (**str**): The detailed error message describing the issue. ``` ```{py:exception} LAAApiError(LAAError) Exception class for all HTTP API errors from the LAA. Attributes: - **message** (**str**): The detailed error message describing the issue. - **http_code** (**int**): The relevant HTTP status code (e.g., 400, 500). ``` ```{py:exception} LAACliError(LAAError) Exception class for all errors when running commands of the LAA itself. Attributes: - **message** (**str**): The detailed error message describing the issue. - **ret_json** (**dict**): The error object returned from the LAA with 'stdout','sterr', and 'code' ``` ## ConnectPexpect class The laam.utils.ConnectPexpect is based on [Pexpect.spawn class](https://pexpect.readthedocs.io/en/stable/api/pexpect.html#pexpect.spawn) ```{py:class} ConnectPexpect(pexpect.spawn) ``` ## Examples Here a few examples on how to use the LAA object in a script. ### Example 1 List Files in my LAA ``` from laam import LAA my_laa = LAA("my_laa_id") print(my_laa.files.list()) => ["file1", "file2", "file2"] ``` ### Example 2 Connect to a Serial in my LAA ``` from laam import LAA import time my_laa = LAA("my_laa_id") # Assuming the DUT on the LAA uses `ttymxc3` pexp_connection = my_laa.serials.connect_pexpect(name="ttymxc3") time.sleep(1) pexp_connection.expect("Connected to port 2001", timeout=2) pexp_connection.sendline("") # Waiting for uBoot on the DUT on my LAA pexp_connection.expect("=>", timeout=40) pexp_connection.send(b"usb start; usb info\n") pexp_connection.expect("LAA USB Mass Storage Gadget", timeout=1) ``` ## Issues In case you of problems [Open an Issue](https://gitlab.com/LinaroLtd/lava/appliance/laam/-/issues) ## Version notes ```{admonition} LAA module availability :class: warning The LAA python object is available from `laam` => v0.8.2. ``` ```{admonition} LED sub-command :class: note laa.laacli.led(state) is working from LAA OS > v1.6.1. ``` ```{admonition} LAA OS v1.4 :class: warning The REST API used by `laam` is only available in LAA OS v1.4 and after. ``` ```{admonition} LAA manager =< v0.8.1 :class: warning laa.serials.connect_async_fun(), laa.serials.connect_async(), and laa.serials.connect_pexpect() cannot connect with LAA OS =< v1.5.5. ``` ```{admonition} LAA manager v0.8.3 :class: warning "laa,network.settings()" command fails. This has been fixed in `laam` v0.8.3 ```