The apssh API

Most symbols can be imported directly from the apssh package, e.g.

from apssh import SshJob

No need to import module apssh.sshjob here.

The SshProxy class

The SshProxy class models an ssh connection, and is mainly in charge * lazily initializing connections on a need-by-need basis * and reasembling lines as they come back from the remote

class apssh.sshproxy.SshProxy(hostname, *, username=None, gateway=None, keys=None, known_hosts=None, port=22, formatter=None, verbose=None, debug=False, timeout=30)

A proxy essentially wraps an ssh connection. It can connect to a remote, and then can run several commands in the most general sense, i.e. including file transfers.

Parameters:
  • hostname – remote hostname
  • username – remote login name
  • gateway (SshProxy) – when set, this node is then used as a hop for creating a 2-leg ssh connection.
  • formatter – each SshProxy instance has an attached formatter that is in charge of rendering the output of the various commands. The default is to use an instance of ColonFormatter, that outputs lines of the form hostname:actual-output
  • verbose – allows to get some user-level feedback on ssh negociation. Permission denied messages and similar won’t show up unless verbose is set.
coroutine close()

Close everything open, i.e. ssh connection and SFTP subsystem

coroutine connect_lazy()

Connects if needed - uses a lock to make it safe for several coroutines to simultaneously try to run commands on the same SshProxy instance.

Returns:connection object
coroutine get_file_s(remotepaths, localpath, **kwds)

Retrieve a collection of remote files locally into the same directory. The ssh connection and SFTP subsystem are created and set up if needed.

Parameters:
Returns:

True if all went well, or raise exception

is_connected()
Returns:whether the connection is up
Return type:bool
is_sftp_connected()
Returns:whether the SFTP subsystem is up
Return type:bool
coroutine mkdir(remotedir)

Create a remote directory if needed.

Parameters:remotedir (str) – remote repository to create.
Returns:True if remote directory existed or could be created, False if SFTP subsystem could not be set up.
Raises:asyncssh.sftp.SFTPError
coroutine put_file_s(localpaths, remotepath, **kwds)

Copy a collection of local files remotely into the same directory. The ssh connection and SFTP subsystem are created and set up if needed.

Parameters:
Returns:

True if all went well, or raise exception

coroutine put_string_script(script_body, remotefile, **kwds)

A convenience for copying over a local script before remote execution. The ssh connection and SFTP subsystem are created and set up if needed. Resulting remote file has mode 755.

Parameters:
Returns:

True if all went well, or raise exception

coroutine run(command, **x11_kwds)

Run a command, and write its output on the fly according to instance’s formatter.

Parameters:
  • command – remote command to run
  • x11_kwds – optional keyword args that will be passed to create_session, like typically x11_forwarding=True
Returns:

remote command exit status - or None if nothing could be run at all

coroutine sftp_connect_lazy()

Initializes SFTP connection if needed

Returns:SFTP connection object

Commands classes

The commands module implements all the command classes, typically Run, RunScript, Pull, and similar classes.


Formatters classes

A formatter is a class that knows how to deal with the stdout/stderr lines as they come back from a ssh connection.

In its capture form, it allows to retain this output in memory instead of printing on the fly.

class apssh.formatters.CaptureFormatter(custom_format='@line@', verbose=True)

This class allows to capture remote output in memory. For now it just provides options to start and get a capture.

Examples

To do a rough equivalent of bash’s:

captured_output=$(ssh remote.foo.com cat /etc/release-notes)

You would do this:

s = Scheduler()
f = CaptureFormatter()
n = SshNode('remote.foo.com', formatter=f)
s.add(SshJob(node=n, command="cat /etc/release-notes"))

f.start_capture()
s.run()
captured = f.get_capture()
get_capture()
Returns:the lines captured since last start_capture()
Return type:str
start_capture()

Marks the current capture as void.

class apssh.formatters.ColonFormatter(format="@host@:@line@")
class apssh.formatters.Formatter(custom_format)

This class is an abstract class that allows to describe how to handle the incoming text from a remote command, as well as various events pertaining to an SshProxy.

This object is expected to be created manually outside of the SshProxy logic.

Examples of predefined formatters:

  • TerminalFormatter: prints out line based on a format (time, hostname, actual line…).
  • RawFormatter: shortcut for TerminalFormatter("@line@").
  • ColonFormatter: shortcut for TerminalFormatter("@host@:@line@").
  • SubdirFormatter: stores in <subdir>/<hostname> all outputs from that host.
  • CaptureFormatter: stores flow in-memory instead of printing on the fly.
class apssh.formatters.RawFormatter(format="@line@")
class apssh.formatters.SubdirFormatter(run_name, *, verbose=True)

This class allows to store remote outputs on the filesystem rather than on the terminal, using the remote hostname as the base for the local filename.

With this class, the remote stdout, stderr, as well as ssh events if requested, are all merged in a single output file, named after the hostname.

Parameters:
  • run_name – the name of a local directory where to store the resulting output; this directory is created if needed.
  • verbose – allows to see ssh events in the resulting file.

Examples

If run_name is set to probing, the session for host foo.com will end up in file probing/foo.com.

class apssh.formatters.TerminalFormatter(custom_format, verbose)

Use print() to render raw lines as they come. Remote stdout goes to stdout of course. Remote stderr goes to stderr. If the verbose attribute is set, additional ssh-related events, like connection open and similar, are also issued on stderr.

Parameters:
  • custom_format – a string that describes the format used to print out incoming lines, see below.
  • verbose – when set, additional information get issued as well, typically pertaining to the establishment of the ssh connection.

The custom_format attribute can contain the following keywords, that are expanded when actual traffic occurs.

  • @line@ the raw contents as sent over the wire
  • @host@@ the remote hostname
  • @user@ the remote username
  • %H and similar time-oriented formats, applied to the time of local reception; refer to strftime for a list of supported formats.
  • @time@ is a shortcut for "%H-%M-%S".
class apssh.formatters.TimeColonFormatter(format="%H-%M-%S:@host@:@line@")
class apssh.commands.AbstractCommand(*, label=None, allowed_exits=None)

Abstract base class for all command classes.

Parameters:
  • label – optional label used when representing a scheduler textually or graphically
  • allowed_exits – the default is to only allow the command to exit(0). Using allowed_exits, one can whitelist a set of exit codes or signals. If the command returns one of these codes, or receives one of these signals, it is deemed to have completed successfully. A retcod 0 is always allowed.

Examples

allowed_exits=["TERM", 4] would allow the command to either return exit code 4, or to end after receiving signal ‘TERM’. Refer to the POSIX documentation for signal names, like QUIT or ALRM.

Note

allowed_exits is typically useful when a command starts a process that is designed to be killed by another command later in the scheduler.

coroutine co_run_local(localnode)

Needs to be redefined on actual command classes that want to support running on a LocalNode as well.

Returns:Should return 0 if everything is fine.
coroutine co_run_remote(node)

Needs to be redefined on actual command classes.

Returns:Should return 0 if everything is fine.
label_line()

Used by SshJob to conveniently show the inside of a Job; intended to be redefined by daughter classes.

Returns:a one-line string
Return type:str
class apssh.commands.Pull(remotepaths, localpath, *args, label=None, verbose=False, **kwds)

Retrieve remote files and stores them locally

Parameters:
  • remotepaths – a collection of remote paths to be retrieved.
  • localpath – the local directory where to store resulting copies.
  • label – if set, is used to describe the command in scheduler graphs.
  • verbose (bool) – be verbose.
  • kwds – passed as-is to the SFTPClient get method.

See also: http://asyncssh.readthedocs.io/en/latest/api.html#asyncssh.SFTPClient.get

coroutine co_run_remote(node)

Needs to be redefined on actual command classes.

Returns:Should return 0 if everything is fine.
label_line()

Used by SshJob to conveniently show the inside of a Job; intended to be redefined by daughter classes.

Returns:a one-line string
Return type:str
class apssh.commands.Push(localpaths, remotepath, *args, label=None, verbose=False, **kwds)

Put local files onto target node

Parameters:
  • localpaths – a collection of local filenames to be copied over to the remote end.
  • remotepath – the directory where to store copied on the remote end.
  • label – if set, is used to describe the command in scheduler graphs.
  • verbose (bool) – be verbose.
  • kwds – passed as-is to the SFTPClient put method.

See also: http://asyncssh.readthedocs.io/en/latest/api.html#asyncssh.SFTPClient.put

coroutine co_run_remote(node)

Needs to be redefined on actual command classes.

Returns:Should return 0 if everything is fine.
label_line()

Used by SshJob to conveniently show the inside of a Job; intended to be redefined by daughter classes.

Returns:a one-line string
Return type:str
class apssh.commands.Run(*argv, label=None, allowed_exits=None, verbose=False, x11=False)

The most basic form of a command is to run a remote command

Parameters:
  • argv – the parts of the remote command. The actual command run remotely is obtained by concatenating the string representation of each argv and separating them with a space.
  • label – if set, is used to describe the command in scheduler graphs.
  • verbose (bool) – if set, the actual command being run is printed out.
  • x11 (bool) – if set, will enable X11 forwarding, so that a X11 program running remotely ends on the local DISPLAY.

Examples

Remotely run tail -n 1 /etc/lsb-release

Run("tail -n 1 /etc/lsb-release")

The following forms are exactly equivalent:

Run("tail", "-n", 1, "/etc/lsb-release")
Run("tail -n", 1, "/etc/lsb-release")
coroutine co_run_local(localnode)

The semantics of running on a local node.

coroutine co_run_remote(node)

The semantics of running on a remote node.

label_line()

One-line rendering is to use the label attribute if set, by default it is the full remote command.

class apssh.commands.RunLocalStuff(args, *, label=None, allowed_exits=None, includes=None, remote_basename=None, x11=False, verbose=False)

The base class for RunScript and RunString. This class implements the common logic for a local script that needs to be copied over before being executed.

Parameters:
  • args – the argument list for the remote command
  • label – if set, is used to describe the command in scheduler graphs.
  • includes – a collection of local files that need to be copied over as well; get copied in the same directory as the remote script.
  • verbose – print out more information if set; this additionnally causes the remote script to be invoked through bash -x, which admittedly is totally hacky. xxx we need to remove this.
  • remote_basename – an optional name for the remote copy of the script.

Local commands are copied in a remote directory - typically in ~/.apssh-remote.

Also, all copies are done under a name that contains a random string to avoid collisions. This is because two parallel runs of the same command would otherwise be at risk of one overwriting the remote command file, while the second tries to run it, which causes errors like this:

fit26: .apssh-remote/B3.sh: /bin/bash: bad interpreter: Text file busy
coroutine co_install(node, remote_path)

Abstract method to explain how to remotely install a local script before we can invoke it

coroutine co_run_remote(node)

Implemented to satisfy the requirement of AbstractCommand. The common behaviour for both classes is to first invoke co_install() to push the local material over; it should raise an exception in case of failure.

class apssh.commands.RunScript(local_script, *args, label=None, allowed_exits=None, includes=None, x11=False, verbose=False)

A class to run a local script file on the remote system, but with arguments passed exactly like with Run

Parameters:
  • local_script – the local filename for the script to run remotely
  • args – the arguments for the remote script; like with Run, these are joined with a space character
  • label – if set, is used to describe the command in scheduler graphs.
  • includes – a collection of local files to be copied over in the same location as the remote script, i.e. typically in ~/.apssh-remote
  • x11 (bool) – allows to enable X11 x11_forwarding
  • verbose – more output

Examples

Run a local script located in ../foo.sh with specified args:

RunScript("../foo.sh", "arg1", 2, "arg3")

or equivalently:

RunScript("../foo.sh", "arg1 2", "arg3")
coroutine co_install(node, remote_path)

Abstract method to explain how to remotely install a local script before we can invoke it

label_line()

Used by SshJob to conveniently show the inside of a Job; intended to be redefined by daughter classes.

Returns:a one-line string
Return type:str
class apssh.commands.RunString(script_body, *args, label=None, allowed_exits=None, includes=None, x11=False, remote_name=None, verbose=False)

Much like RunScript, but the script to run remotely is expected to be passed in the first argument as a python string this time.

Parameters:
  • script_body (str) – the contents of the script to run remotely.
  • args – the arguments for the remote script; like with Run, these are joined with a space character
  • label – if set, is used to describe the command in scheduler graphs.
  • includes – a collection of local files to be copied over in the same location as the remote script, i.e. typically in ~/.apssh-remote
  • x11 (bool) – allows to enable X11 x11_forwarding
  • remote_name – if provided, will tell how the created script should be named on the remote node; it is randomly generated if not specified by caller.
  • verbose – more output

Examples

Here’s how to call a simple bash wrapper remotely:

myscript = "#!/bin/bash\nfor arg in "$@"; do echo arg=$arg; done"
scheduler.add(
  RunString(myscript, "foo", "bar", 2, "arg3",
            remote_name = "echo-args.sh"))
coroutine co_install(node, remote_path)

Abstract method to explain how to remotely install a local script before we can invoke it

label_line()

Used by SshJob to conveniently show the inside of a Job; intended to be redefined by daughter classes.

Returns:a one-line string
Return type:str

The Service class

The service module defines the Service helper class.

class apssh.service.Service(command, *, service_id=None, tty=False, systemd_type='simple', environ=None, verbose=False)

The Service class is a helper class, that allows to deal with services that an experiment scheduler needs to start and stop over the course of its execution. It leverages systemd-run, which thus needs to be available on the remote box.

Typical examples include starting and stopping a netcat server, or a tcpdump session.

A Service instance is then able to generate a Command instance for starting or stopping the service, that should be inserted in an SshJob, just like e.g. a usual Run instance.

Parameters:
  • command (str) – the command to start the service
  • service_id (str) – a unique id used to refer to that particular service; the class always add a randomly generated salt to the (optional) user-provided id.
  • tty (bool) – some services require a pseudo-tty to work properly
  • systemd_type (str) – a systemd service unit can have several values for its type setting, depending on the forking strategy implemented in the main command. The default used in Service is simple, which is correct for a command that hangs (does not fork or go in the background). If on the contrary the command already handles forking, then it may be appropriate to use the forking systemd type instead. Refer to systemd documentation for more details, at https://www.freedesktop.org/software/systemd/man/systemd.service.html#Type=
  • environ – a dictionary that defines additional environment variables to be made visible to the running service. In contrast with what happens with regular Run commands, processes forked by systemd have a very limited set of environment variables defined - typically only LANG and PATH. If your program rely on, for example, the USER variable to be defined as well, you may specify it here, for example environ={'USER': 'root'}.
start_command(*, label=None, **kwds)
Returns:a Run instance suitable to be inserted in a SshJob object
status_command(*, output=None, label=None, **kwds)
Returns:a Run instance suitable to be inserted in a SshJob object
stop_command(*, label=None, **kwds)
Returns:a Run instance suitable to be inserted in a SshJob object

Utilities

apssh.topology.close_ssh_in_scheduler(scheduler, manage_gateways=True)

Convenience: synchroneous version of co_close_ssh_in_scheduler().

Parameters:manage_gateways (bool) – passed as-is
coroutine apssh.topology.co_close_ssh_in_scheduler(scheduler, manage_gateways=True)

This utility function allows to close all ssh connections involved in a scheduler.

Its logic is to find all SshNode instances referred in the jobs contained in the scheduler, nested schedulers included. All the attached ssh connections are then closed, starting with the remotest ones.

Parameters:manage_gateways (bool) – when this parameter is False, all the nodes that appear in at least one job are considered. If it is True, then in addition to that, all the nodes that appear as a gateway of a node in that first set are considered as well.
apssh.topology.topology_graph(scheduler)

Much like Scheduler.graph() in asynciojobs, this convenience function creates a graphviz graph object, that can be used to visualize the various nodes and gateways present in a scheduler, through the relationship: x is used as a gateway to reach y

Returns:a graph
Return type:graphviz.Digraph

This method is typically useful in a Jupyter notebook, so as to visualize a topology in graph format - see http://graphviz.readthedocs.io/en/stable/manual.html#jupyter-notebooks for how this works.

The dependency from apssh to graphviz is limited to this function, and topology_as_pngfile as these are the only places that need that library, and as installing graphviz can be cumbersome.

For example, on MacOS I had to do both:

brew install graphviz     # for the C/C++ binary stuff
pip3 install graphviz     # for the python bindings
apssh.topology.topology_dot(scheduler)

Computes the relationship between nodes and gateways, for a given scheduler.

Returns:a string in DOT format.
Return type:str
apssh.topology.topology_as_dotfile(scheduler, filename)

Convenience function to store a dot file from a schedulerself.

Parameters:
  • scheduler
  • filename – output filename
apssh.topology.topology_as_pngfile(scheduler, filename)

Convenience wrapper that creates a png file.

Parameters:
  • scheduler
  • filename – output filename, without the .png extension
Returns:

created file name

Notes

  • This actually uses the binary dot program.
  • A file named as the output but with a .dot extension is created as an artefact by this method.

nepi-ng node classes

The SshNode and LocalNode classes are designed as companions to the SshJob class, that need a node attribute to describe on which node to run commands.

class apssh.nodes.LocalNode(formatter=None, verbose=None)

For convenience and consistency, this class can be used as the node attribute of a SshJob object, so as to define a set of commands to run locally.

Parameters:
  • formatter – a formatter instance, default to an instance of ColonFormatter;
  • verbose – if provided, passed to the formatter instance

Examples

To create a job that runs 2 commands locally:

SshJob(node=LocalNode(),
       commands = [
           Run("cat /etc/motd"),
           Run("sleep 10"),
       ])

Note

Not all command classes support running on a local node, essentially
this is only available for usual Run commands as of this writing.
coroutine read_and_display(stream, datatype)

read (process stdout or stderr) stream line by line until EOF and dispatch lines in formatter - using self.lines(… datatype)

class apssh.nodes.SshNode(hostname, *, username=None, keys=None, **kwds)

An instance of SshNode typically is needed to create a apssh.sshjob.SshJob instance, that defines a batch of commands or file transfers to run in sequence on that node.

Examples

A typical usage to create a job that runs 2 commands remotely:

remote_node = SshNode('remote.foo.com', username='tutu')

SshJob(node=remote_node,
       commands = [
           Run("cat /etc/motd"),
           Run("sleep 10"),
       ])

This class is a very close specialization of the SshProxy class. The only difference are in the handling of default values at build time.

Parameters:
  • hostname – remote node’s hostname
  • username – defaults to root if unspecified, note that SshProxy’s default is to use the local username instead
  • keys – filenames for the private keys to use when authenticating; the default policy implemented in this class is to first use the keys currently loaded in the ssh agent. If none can be found this way, SshNode will attempt to import the default ssh keys located in ~/.ssh/id_rsa and ~/.ssh/id_dsa.
  • kwds – passed along to the SshProxy class.
distance()
Returns:number of hops from the local node. An instance without a gateway has a distance of 1. Otherwise, it is deemed one hop further than its gateway.
Return type:int

nepi-ng job classes

The SshJob class is a specialization of asynciojobsAbstractJob class. It allows to group operations (commands & file transfers) made in sequence on a given remote (and even local for convenience) node.

exception apssh.sshjob.CommandFailedError

The exception class raised when a command that is part of a critical SshJob instance fails.

This is turn is designed to cause the abortion of the surrounding scheduler.

class apssh.sshjob.SshJob(node, *, command=None, commands=None, keep_connection=False, verbose=None, forever=None, critical=None, **kwds)

A subclass of asynciojobs’s AbstractJob object that is set to run a command, or list of commands, on a remote node specified by a SshNode object.

Parameters:
  • node – an SshNode instance that describes the node where the attached commands will run, or the host used for file transfers for commands like e.g. Pull. It is possible to use a LocalNode instance too, for running commands locally, although some types of commands, like precisely file transfers, do not support this.
  • command – an alias for commands
  • commands

    An ordered collection of commands to run sequentially on the reference node. for convenience, you can set either commands or command, both forms are equivalent, but you need to make sure to give exactly one of both. commands can be set as either in a variety of ways:

    • (1) a list/tuple of AbstractCommand objects, e.g.:
      commands = [ Run(..), RunScript(...), ..]
      
    • (2) a single instance of AbstractCommand, e.g.:
      commands = RunScript(...)
      
    • (3) a list/tuple of strings, in which case a single Run object is created, e.g.:
      commands = [ "uname", "-a" ]
      
    • (4) a single string, here again a single Run object is created, e.g.:
      commands = "uname -a"
      

    Regardless, the commands attached internally to a SshJob objects are always represented as a list of AbstractCommand instances.

  • verbose – if set to a non-None value, it is used to set - and possibly override - the verbose value in all the command instances in the job.
  • keep_connection – if set, this flag prevents co_shutdown, when sent to this job instance by the scheduler upon completion, from closing the connection to the attached node.
  • forever – passed to AbstractJob; default is False, which may differ from the one adopted in asynciojobs.
  • critical – passed to AbstractJob; default is True, which may differ from the one adopted in asynciojobs.
  • kwds – passed as-is to AbstractJob; typically useful for setting required and scheduler at build-time.
coroutine close()

Implemented as part of the AbstractJob protocol.

Default behaviour is to close the underlying ssh connection, that is to say the attached node object, unless keep_connection was set, in which case no action is taken.

Returns:None
coroutine co_run()

This method is triggered by a running scheduler as part of the AbstractJob protocol. It simply runs all commands sequentially.

If any of the commands fail, then the behavious depends on the job’s critical flag:

  • if the job is not critical, then all the commands are triggered no matter what, and the return code reflects that something went wrong by reporting the last failing code;
  • if the job is critical on the other hand, then the first failing command causes co_run to stop abruptly and to throw an exception, that in turn will cause the surrounding scheduler execution to abort immediately.
Returns:0 if everything runs fine, the faulty return code otherwise.
Return type:int
Raises:CommandFailedError – in the case where the object instance is defined as critical, and if one of the commands fails, an exception is raised, which leads the running scheduler to aborting abruptly.
coroutine co_shutdown()

Implemented as part of the AbstractJob protocol.

Default behaviour is to close the underlying ssh connection, that is to say the attached node object, unless keep_connection was set, in which case no action is taken.

Returns:None
details()

Used by Scheduler when running list(details=True)

graph_label()

This method customizes rendering of this job instance for calls to its Scheduler’s graph() or export_as_dotfile() methods.

Relies on each command’s label_line() method

repr_result()

Returns: str: standardized repr’s part that shows

the result or exception of the job.
text_label()

This method customizes rendering of this job instance for calls to its Scheduler’s list() or debrief() methods.

Relies on the first command’s label_line() method.


Tools to deal with keys

Basic tools for loading ssh keys from the user space or the agent

apssh.keys.import_private_key(filename)

This functions attempts to import a private key from its filename. It will prompt for a password if needed.

Parameters:filename – the local path to the private key
Returns:a (asyncssh) SSHKey object if successful, or None
apssh.keys.load_agent_keys(agent_path=None, *, loop=None)

The ssh-agent is a convenience tool that aims at easying the use of private keys protected with a password. In a nutshell, the agent runs on your local computer, and you trust it enough to load one or several keys into the agent once and for good - and you provide the password at that time.

Later on, each time an ssh connection needs to access a key, the agent can act as a proxy for you and pass the key along to the ssh client without the need for you to enter the password.

The load_agent_keys function allows your python code to access the keys currently knwns to the agent. It is automatically called by the SshNode class if you do not explicit the set of keys that you plan to use.

Parameters:
  • agent_path – how to locate the agent; defaults to env. variable $SSH_AUTH_SOCK
  • loop – an asyncio event loop, probably safer to ignore this.
Returns:

a list of SSHKey keys from the agent

Note

Use the command ssh-add -l to inspect the set of keys currently present in your agent.

apssh.keys.load_private_keys(command_line_keys=None, verbose=False)

A utility that implements a default policy for locating private keys.

Parameters:
  • command_line_keys – a collection of local filenames that should contain private keys; this should correspond to keys that a user has explicitly decided to use through a command-line option or similar;
  • verbose – gives more details on what is going on.

This function is used both by the apssh binary, and by the SshNode class. Here’s for example how apssh locates private keys:

    1. If no keys are given as the command_line_keys parameter (typically through the apssh -k command line option), then:
    • 1.a if an ssh agent can be reached using the SSH_AUTH_SOCK
      environment variable, and offers a non-empty list of keys, apssh will use the keys loaded in the agent
    • 1.b otherwise, apssh will use
      ~/.ssh/id_rsa and ~/.ssh/id_dsa if they exist
    1. If keys are specified on the command line
    • 2.c That exact list is used for loading private keys

Note

Use ssh-add for managing the keys known to the agent.


The apssh binary implementation

The apssh binary makes a rather straightforward use of the library, except maybe for the way it handles the fuzzy notion of targets, that can be defined as either hostnames directly, or from files that contain hostnames, or from directories that contain files named after hostnames.

class apssh.apssh.Apssh

Main class for apssh utility

analyze_target(target)

This function is used to guess the meaning of all the targets passed to the apssh command through its -t/--target option.

Parameters:target – a string passed to --target
Returns:a tuple, whose meaning is described below.
Return type:(bool, list)

A target can be specified as either

  • a filename. If it is a relative filename it is also searched in ~/.apssh. If an existing file can be located this way, and it can be parsed, then the returned object will be of the form:

    True, [ hostname1, ...]
    
  • a directory name. Here again the search is also done in ~/.apssh. If an existing directory can be found, all the simple files that are found immediately under the specified directory are taken as hostnames, and in this case analyze_target returns:

    True, [ hostname1, ...]
    

    This is notably for use together with the --mark option, so that one can easily select reachable nodes only, or just as easily exclude failing nodes.

  • otherwise, the incoming target is then expected to be a string that directly contains the hostnames, and so it is simply split along white spaces, and the return code is then:

    True, [ hostname1, ...]
    
  • If anything goes wrong, return code is:

    False, []
    

    for example, this is the case when the file exists but cannot be parsed - in which case it is probably not a hostname.