host.remoteHost

Remote host class

Remote hosts manage 2 main things:

  • Command execution

    • SSH (via asyncssh)

    • telnet (via telnetlib3)

  • File transfers

    • SCP (via asyncssh)

    • SFTP (via asyncssh)

    • FTP (via aioftp)

    • netcat (via commands on the client and host)

All kinds of host connections, for command execution and for file transfers, should be able to establish a connection first, keep it open, and then use it for multiple commands and transfers. Host connections can be explictly closed by calling the .close() method or in the destructor of the host object.

The .run() method runs a single command (str) or a list of commands. Depending on the .term value the correct connection type (ssh or telnet) is used without being specified as an argument.

The .put() and .get() methods both take a single file or a list of files. Depending on the .transfer value the correct connection type (scp, sftp, ftp, or netcat) is used without being specified as an argument.

class otto.host.remoteHost.RemoteHost(ip, creds, ne, name=None, user=None, neId=None, board=None, slot=None, hw_version=None, sw_version=None, term='ssh', is_virtual=False, docker_capable=False, transfer='scp', ssh_options=<factory>, telnet_options=<factory>, sftp_options=<factory>, scp_options=<factory>, ftp_options=<factory>, nc_options=<factory>, hop=None, resources=<factory>, log=True, log_stdout=True, toolchain=<factory>, _connection_factory=None)

Bases: BaseHost

Remote host accessed via SSH/network protocols.

ip : --is-rst--:py:class:`str`

IP address of the host.

creds : --is-rst--:py:class:`dict`\ \[:py:class:`str`, :py:class:`str`]

Users and their respective passwords for this host.

ne : --is-rst--:py:class:`str`

Network element to which this host belongs.

name : --is-rst--:py:class:`str`

Human readable name to represent the host. Automatically generated if not provided.

user : --is-rst--:py:data:`~typing.Optional`\ \[:py:class:`str`]

User with which to log in. If not provided, the first user in the creds dict will be used.

neId : --is-rst--:py:data:`~typing.Optional`\ \[:py:class:`int`]

Network element identifier to which this host belongs. None indicates there are no other NEs of this type and a number is not needed.

board : --is-rst--:py:data:`~typing.Optional`\ \[:py:class:`str`]

Name of the board type to which this host belongs.

slot : --is-rst--:py:data:`~typing.Optional`\ \[:py:class:`int`]

Phyiscal slot number of the board to which this host belongs.

hw_version : --is-rst--:py:data:`~typing.Optional`\ \[:py:class:`str`]

Hardware version description.

sw_version : --is-rst--:py:data:`~typing.Optional`\ \[:py:class:`str`]

Software version description.

term : --is-rst--:py:data:`~typing.Literal`\ \[``'ssh'``, ``'telnet'``]

Protocol used to issue terminal commands.

is_virtual : --is-rst--:py:class:`bool`

Determines whether a host is a VM or not.

docker_capable : --is-rst--:py:class:`bool`

Whether this host can run Docker containers (i.e., has a docker daemon and the configured user can talk to it). Containers declared by projects are scheduled onto docker-capable hosts; non-capable hosts are skipped.

transfer : --is-rst--:py:data:`~typing.Literal`\ \[``'scp'``, ``'sftp'``, ``'ftp'``, ``'nc'``]

Protocol used to transfer files.

ssh_options : --is-rst--:py:class:`~otto.host.options.SshOptions`

Connection options for SSH sessions (port, timeout, known_hosts, port-forwarding rules, etc.).

telnet_options : --is-rst--:py:class:`~otto.host.options.TelnetOptions`

Connection options for telnet sessions (port, cols/rows, auto-resize, etc.).

sftp_options : --is-rst--:py:class:`~otto.host.options.SftpOptions`

Connection options for SFTP file transfers.

scp_options : --is-rst--:py:class:`~otto.host.options.ScpOptions`

Connection options for SCP file transfers.

ftp_options : --is-rst--:py:class:`~otto.host.options.FtpOptions`

Connection options for FTP file transfers (port, encoding, FTPS, etc.).

nc_options : --is-rst--:py:class:`~otto.host.options.NcOptions`

Connection options for netcat file transfers (nc executable, port strategy, listener check, etc.).

hop : --is-rst--:py:data:`~typing.Optional`\ \[:py:class:`str`]

Host ID of the intermediate hop used to reach this host, or None for direct connection.

resources : --is-rst--:py:class:`set`\ \[:py:class:`str`]

Names of resources required to use this host.

log : --is-rst--:py:class:`bool`

Determines whether this host should log its output to stdout and log files. Setting this field to False effectively sets log_stdout to False as well.

log_stdout : --is-rst--:py:class:`bool`

Determines whether this host should log its output to stdout. Commands and their output are still logged to log files if log is True.

toolchain : --is-rst--:py:class:`~otto.host.toolchain.Toolchain`

Toolchain associated with this host’s products. Used by the coverage pipeline to select the correct gcov and lcov binaries. Defaults to system-installed tools.

id : --is-rst--:py:class:`str`

Unique identifier for this host.

rebuild_connections()

Recreate the ConnectionManager and dependents.

Useful after changing hop or when the host must reconnect on a new event loop (e.g. after pytest.main() returns and coverage collection starts in a fresh asyncio.run()).

Return type:

None

set_term_type(term)
set_transfer_type(transfer)
async verify_connection()

Attempt to connect without running any commands. Used by dry-run mode.

Return type:

CommandStatus

async close()
Return type:

None

async oneshot(cmd, timeout=None)

Run a single command concurrent-safely, independent of the persistent shell.

Unlike run(), this method is concurrent-safe: multiple oneshot() calls can run simultaneously via asyncio.gather() or asyncio.create_task() without corrupting each other or the persistent shell session.

Key differences from run():

Property

run()

oneshot()

Shell state Concurrency Expect support Connection cost Best for

Persistent (cd, env persist) Sequential only Yes Reuses existing session Multi-step workflows, state

Stateless (fresh each call) Safe for asyncio.gather() No Reuses cached oneshot pool One-off / parallel cmds

Implementation details:

  • SSH: runs via SSHClientConnection.create_process() — a lightweight exec channel on the existing TCP connection. No new TCP handshake or authentication needed.

  • Telnet: telnet has no stateless exec primitive, so otto keeps a free-list pool of dedicated internal shell sessions. Serial callers reuse one session (one TCP+auth handshake amortized over all calls); concurrent callers each pull their own session off the free-list, opening a new one if none are free. This preserves the independence guarantee while avoiding the 1–2 s handshake on every call.

Parameters:
  • cmd – Shell command to run. Shell operators (<, >, |) work on SSH because asyncssh wraps the command in a shell; on telnet the command runs through the login shell of the new session.

  • timeout – Seconds before the command is considered hung. None (the default) disables the timeout — appropriate for long-running commands such as a netcat listener waiting for a connection.

Return type:

CommandStatus

Returns:

CommandStatus with the command, captured output, Status enum, and exit code.

See also

run(): stateful, sequential alternative with expect support.

async open_session(name)

Open a named persistent shell session.

Unlike run(), which uses a single default session, this method creates an additional named session that can run commands concurrently with the default session (or other named sessions).

The session is established eagerly — any connection errors surface here. Call HostSession.close() when done, or use the async context manager protocol:

async with (await host.open_session("monitor")) as mon:
    result = await mon.run("stat /tmp/file.bin")
Parameters:

name – Identifier for this session. Reusing an existing name returns the existing session if it is still alive, or replaces it if dead.

Return type:

HostSession

Returns:

A HostSession proxy exposing run, send, expect, and close.

See also

oneshot(): stateless one-shot alternative. run(): default persistent session.

async send(text)

Send raw text to the host’s persistent session.

Return type:

None

async expect(pattern, timeout=10.0)

Wait for a pattern in the host’s session output stream.

Return type:

str

async get(src_files, dest_dir, show_progress=True)

Transfer files from remote host to the local machine.

Return type:

tuple[Status, str]

async put(src_files, dest_dir, show_progress=True)

Transfer files from local machine to remote host.

Return type:

tuple[Status, str]