storage¶
The storage package provides a repository pattern for persisting and retrieving data (currently backed by JSON files).
- class otto.storage.protocol.LabRepository(*args, **kwargs)¶
Bases:
ProtocolProtocol defining DB-agnostic interface for loading labs.
-
load_lab(name, search_paths, defaults=
None)¶ Load a lab by name from the repository.
Parameters¶
- namestr
Name of the lab to load
- search_pathslist[Path]
Directories to search for the lab data
- defaultsdict[str, dict[str, Any]] | None
Optional repo-level option defaults forwarded to the host factory. Backends should pass this through unchanged; the factory handles per-key merging beneath each host’s own
*_options.Nonereproduces today’s behavior.
Returns¶
- Lab
Fully constructed Lab object with all hosts
Raises¶
- FileNotFoundError
If lab cannot be found in any search path
- ValueError
If lab data is malformed
- ImportError
If module loading fails (Python repository only)
- supports_location(path)¶
Check if this repository can handle data at the given location.
- Return type:¶
bool
Parameters¶
- pathPath
Location to check
Returns¶
- bool
True if this repository can load from this location
- list_labs(search_paths)¶
List all valid lab names available in the search paths.
- Return type:¶
list[str]
Parameters¶
- search_pathslist[Path]
Directories to search for labs
Returns¶
- list[str]
List of lab names found in the search paths
-
load_lab(name, search_paths, defaults=
- class otto.storage.json_repository.JsonFileLabRepository¶
Bases:
objectRepository implementation for loading labs from a hosts.json file.
Each search-path directory may contain a hosts.json file holding all known hosts. Each host carries a ‘labs’ field listing the lab names it belongs to, mirroring a database row-with-membership design.
- supports_location(path)¶
Check if path is a directory that could contain a hosts.json file.
- Return type:¶
bool
-
load_lab(name, search_paths, defaults=
None)¶ Load a lab by filtering hosts from hosts.json files.
Searches all search paths for hosts.json files, merges all hosts, then returns only those whose ‘labs’ field contains the requested name.
Parameters¶
- namestr
Name of the lab to load
- search_pathslist[Path]
Directories to search for hosts.json files
- defaultsdict[str, dict[str, Any]] | None
Optional repo-level option defaults forwarded to the host factory; merged per-key beneath each host’s own
*_options.
Returns¶
- Lab
Constructed Lab object with all matching hosts added
Raises¶
- FileNotFoundError
If no hosts.json found in any search path, or no hosts belong to the requested lab
- ValueError
If a hosts.json file doesn’t contain a JSON array or host data is invalid
- json.JSONDecodeError
If a hosts.json file contains malformed JSON
- list_labs(search_paths)¶
List all lab names referenced by hosts across all hosts.json files.
- Return type:¶
list[str]
Parameters¶
- search_pathslist[Path]
Directories to search for hosts.json files
Returns¶
- list[str]
Sorted list of unique lab names found
-
otto.storage.factory.OPTIONS_KEYS : frozenset[str] =
frozenset({'ftp_options', 'nc_options', 'scp_options', 'sftp_options', 'ssh_options', 'telnet_options'})¶ Names of the per-protocol option tables accepted on host dicts and as repo-level
[host_defaults.<key>]tables.
-
otto.storage.factory.create_host_from_dict(host_data, defaults=
None)¶ Create the appropriate
RemoteHostsubclass from a host dict.The
osTypefield names a registeredOsProfile, which selects the base host class to build and carries a bundle of default field values: :rtype:RemoteHostunix(the default whenosTypeis absent) →UnixHostembedded→EmbeddedHostany custom profile registered via
register_os_profileor an[os_profiles.<name>]settings table → its declared base class
Field precedence, highest to lowest:
the host’s own value in host_data;
the profile’s
defaults;repo-level
*_optionsdefaults from defaults (per-key, options only);the base class’s stock dataclass default.
Parameters¶
- host_datadict[str, Any]
Dictionary containing host configuration. The accepted keys depend on the profile’s base family; see
validate_host_dict()for the required set. Common keys:ip,ne,creds,user,board,slot,neId,resources,hop,log,log_stdout,name,osType,osName,osVersion. Unix hosts additionally acceptdocker_capable,toolchain, and the*_optionstables; embedded hosts accepttelnet_optionsonly.- defaultsdict[str, dict[str, Any]] | None
Optional repo-level option defaults, keyed by
*_optionstable name. When supplied, each table is merged per-key beneath the profile’s and the host’s own*_options(host keys win, then profile keys).None(the default) applies no repo-level defaults.
Returns¶
- RemoteHost
A
UnixHostorEmbeddedHost, selected by the profile’s base family.
Raises¶
- ValueError
If
osTypenames no registered profile, or if an embedded host declaresdocker_capable.- TypeError
If required fields are missing or field types are incorrect.
- otto.storage.factory.validate_host_dict(host_data)¶
Validate host dictionary structure without creating a Host object.
osTypemust name a registeredOsProfile; the profile’s base family determines the required-field set and the family-specific checks. The checks run against the effective dict — the host’s fields layered over the profile’sdefaults— so a value supplied by the profile (e.g.credsorfilesystem) satisfies/validates the same as a host field. :rtype:Noneunixbase (the default whenosTypeis absent):ip,creds,nerequired.embeddedbase:ip,nerequired —credsis optional, since the RTOS telnet shell typically has no login step.
Parameters¶
- host_datadict[str, Any]
Host data dictionary to validate
Raises¶
- ValueError
If
osTypenames no registered profile, a required field is missing, a field has the wrong type, an embedded host declaresdocker_capable, or an embedded host’stransfervalue is notconsoleortftp.