Global API

Classes

play_on(*, pattern_hosts, inventory_path, …) A context manager to manage a sequence of Ansible module calls.

Functions

discover_networks(roles, …) Checks the network interfaces on the nodes.
ensure_python2([make_default]) Make sure python is installed on the remote nodes and is the default.
ensure_python3([make_default]) Make sure python3 is installed on the remote nodes and is the default.
gather_facts(*[, pattern_hosts, …]) Gather facts about hosts.
generate_inventory(roles, networks, …[, …]) Generate an inventory file in the ini format.
get_hosts(roles, List[enoslib.host.Host]], …) Get all the hosts matching the pattern.
run(command, hosts[, extra_vars, …]) Run a shell command on some remote hosts.
run_ansible(playbooks[, inventory_path, …]) Run Ansible.
run_command(command, *, pattern_hosts, …) Run a shell command on some remote hosts.
run_play(play_source, *[, inventory_path, …]) Run a play.
wait_ssh(roles, List[enoslib.host.Host]], …) Wait for all the machines to be ssh-reachable
enoslib.api.discover_networks(roles: MutableMapping[str, List[enoslib.host.Host]], networks: List[Dict[Any, Any]], fake_interfaces: List[str] = None, fake_networks: List[str] = None) → MutableMapping[str, List[enoslib.host.Host]]

Checks the network interfaces on the nodes.

This enables to auto-discover the mapping interface name <-> network role.

Parameters:
  • roles (dict) – role->hosts mapping as returned by enoslib.infra.provider.Provider.init()
  • networks (list) – network list as returned by enoslib.infra.provider.Provider.init()
  • fake_interfaces (list) – names of optionnal dummy interfaces to create
  • fake_networks (list) – names of the roles to associate with the fake interfaces. Like regular network interfaces, the mapping will be added to the host vars. Internally this will be zipped with the fake_interfaces to produce the mapping.

If the command is successful each host will be added some variables. Assuming that one network whose role is mynetwork has been declared, the following variables will be available through the ansible hostvars:

  • mynetwork=eth1, eth1 has been discovered has the interface in the network mynetwork.
  • mynetwork_dev=eth1, same as above with a different accessor names
  • mynetwork_ip=192.168.42.42, this indicates the ip in the network mynetwork for this node

All of this variable can then be accessed by the other nodes through the hostvars: hostvars[remote_node]["mynetwork_ip"]

enoslib.api.ensure_python2(make_default=True, **kwargs)

Make sure python is installed on the remote nodes and is the default.

It inherits the arguments of enoslib.api.play_on.

enoslib.api.ensure_python3(make_default=True, **kwargs)

Make sure python3 is installed on the remote nodes and is the default.

It inherits the arguments of enoslib.api.play_on.

enoslib.api.gather_facts(*, pattern_hosts='all', gather_subset='all', inventory_path=None, roles=None, extra_vars=None, on_error_continue=False)

Gather facts about hosts.

This function can be used to check/save the information of the infrastructure where the experiment ran. It’ll give the information gathered by Ansible (see https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html )

Parameters:
Raises:
  • enoslib.errors.EnosFailedHostsError – if a task returns an error on a host and on_error_continue==False
  • enoslib.errors.EnosUnreachableHostsError – if a host is unreachable (through ssh) and on_error_continue==False
Returns:

Dict combining the ansible facts of ok and failed hosts and every results of tasks executed.

Example:

# Inventory
[control1]
enos-0
[control2]
enos-1

# Python
result = gather_facts(roles=roles)

# Result
{
    'failed': {},
    'ok':
    {
      'enos-0':
      {
        'ansible_product_serial': 'NA',
        'ansible_form_factor': 'Other',
        'ansible_user_gecos': 'root',
        ...
      },
      'enos-1':
      {...}
    'results': [...]
}
enoslib.api.generate_inventory(roles, networks, inventory_path, check_networks=False, fake_interfaces=None, fake_networks=None)

Generate an inventory file in the ini format.

The inventory is generated using the roles in the ini format. If check_network == True, the function will try to discover which networks interfaces are available and map them to one network of the networks parameters. Note that this auto-discovery feature requires the servers to have their IP set.

Parameters:
  • roles (dict) – role->hosts mapping as returned by enoslib.infra.provider.Provider.init()
  • networks (list) – network list as returned by enoslib.infra.provider.Provider.init()
  • inventory_path (str) – path to the inventory to generate
  • check_networks (bool) – True to enable the auto-discovery of the mapping interface name <-> network role
  • fake_interfaces (list) – names of optionnal dummy interfaces to create on the nodes
  • fake_networks (list) – names of the roles to associate with the fake interfaces. Like reguilar network interfaces, the mapping will be added to the host vars. Internally this will be zipped with the fake_interfaces to produce the mapping.
enoslib.api.get_hosts(roles: MutableMapping[str, List[enoslib.host.Host]], pattern_hosts: str = 'all') → List[enoslib.host.Host]

Get all the hosts matching the pattern.

Parameters:
Returns:

The list of hosts matching the pattern

class enoslib.api.play_on(*, pattern_hosts: str = 'all', inventory_path: Optional[str] = None, roles: Optional[MutableMapping[str, List[enoslib.host.Host]]] = None, extra_vars: Optional[MutableMapping[Any, Any]] = None, on_error_continue: bool = False, gather_facts: Union[str, bool] = True, priors: Optional[List[play_on]] = None, run_as: Optional[str] = None)

A context manager to manage a sequence of Ansible module calls.

Constructor.

Parameters:
  • pattern_hosts – pattern to describe ansible hosts to target. see https://docs.ansible.com/ansible/latest/intro_patterns.html
  • inventory_path – inventory to use
  • roles – roles as returned by enoslib.infra.provider.Provider.init()
  • extra_vars – extra_vars to use
  • on_error_continue – don’t throw any exception in case a host is unreachable or the playbooks run with errors
  • gather_facts – controls how the facts will be gathered. - True -> Gathers facts of pattern_hosts hosts. - False -> Does not gather facts. - pattern -> Gathers facts of pattern hosts.
  • priors – tasks in each prior will be prepended in the playbook
  • run_as – A shortcut that injects become and become_user to each task. become* at the task level has the precedence over this parameter

Examples

  • Minimal snippet:

    with play_on(roles=roles) as t:
        t.apt(name=["curl", "git"], state="present")
        t.shell("which docker || (curl get.docker.com | sh)")
        t.docker_container(name="nginx", state="started")
    
  • Complete example with fact_gathering

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    from enoslib.api import play_on
    from enoslib.errors import EnosFailedHostsError
    from enoslib.infra.enos_vagrant.provider import Enos_vagrant
    from enoslib.infra.enos_vagrant.configuration import Configuration
    
    import logging
    
    logging.basicConfig(level=logging.DEBUG)
    
    provider_conf = {
        "resources": {
            "machines": [{
                "roles": ["control"],
                "flavour": "tiny",
                "number": 1,
            },{
                "roles": ["client"],
                "flavour": "tiny",
                "number": 1,
            }],
            "networks": [{"roles": ["rn1"], "cidr": "172.16.0.1/16"}]
        }
    }
    
    conf = Configuration.from_dictionnary(provider_conf)
    provider = Enos_vagrant(conf)
    roles, networks = provider.init()
    
    with play_on(roles=roles) as p:
        p.debug(msg="{{ inventory_hostname  }}")
    
    with play_on(pattern_hosts="client", roles=roles) as p:
        p.debug(msg="{{ inventory_hostname  }}")
        # this fails
        # p.debug(msg="{{ hostvars[groups['control'][0]].ansible_fqdn }}")
    
    with play_on(pattern_hosts="control", roles=roles) as p:
        p.debug(msg="{{ inventory_hostname  }}")
    
    with play_on(pattern_hosts="client", roles=roles, gather_facts="control") as p:
        p.debug(msg="{{ inventory_hostname  }}")
        # This doesn't fail because we gather facts on the control host
        p.debug(msg="{{ hostvars[groups['control'][0]].ansible_fqdn }}")
    
    with play_on(pattern_hosts="client", roles=roles, gather_facts="all") as p:
        p.debug(msg="{{ inventory_hostname  }}")
        # This doesn't fail because we gather facts on all hosts
        p.debug(msg="{{ hostvars[groups['control'][0]].ansible_fqdn }}")
    
Hint
  • Module can be run asynchronously using the corresponding Ansible options Note that not all the modules support asynchronous execution.
  • Note that the actual result isn’t available in the result file but will be available through a file specified in the result object.
  • Any ansible module can be called using the above way. You’ll need to refer to the module reference documentation to find the corresponding kwargs to use.
enoslib.api.run(command, hosts, extra_vars=None, on_error_continue=False, **kwargs)

Run a shell command on some remote hosts.

This is a wrapper of enoslib.api.run_command().

enoslib.api.run_ansible(playbooks, inventory_path=None, roles=None, extra_vars=None, tags=None, on_error_continue=False, basedir='.')

Run Ansible.

Parameters:
  • playbooks (list) – list of paths to the playbooks to run
  • inventory_path (str) – path to the hosts file (inventory)
  • extra_var (dict) – extra vars to pass
  • tags (list) – list of tags to run
  • on_error_continue (bool) – Don’t throw any exception in case a host is unreachable or the playbooks run with errors
Raises:
  • enoslib.errors.EnosFailedHostsError – if a task returns an error on a host and on_error_continue==False
  • enoslib.errors.EnosUnreachableHostsError – if a host is unreachable (through ssh) and on_error_continue==False
enoslib.api.run_command(command: str, *, pattern_hosts: str = 'all', inventory_path: Optional[str] = None, roles: Optional[MutableMapping[str, List[enoslib.host.Host]]] = None, extra_vars: Optional[Mapping[KT, VT_co]] = None, on_error_continue: bool = False, run_as: Optional[str] = None, **kwargs)

Run a shell command on some remote hosts.

Parameters:
  • command (str) – the command to run
  • pattern_hosts (str) – pattern to describe ansible hosts to target. see https://docs.ansible.com/ansible/latest/intro_patterns.html
  • inventory_path (str) – inventory to use
  • roles (dict) – the roles to use (replacement for inventory_path).
  • extra_vars (dict) – extra_vars to use
  • on_error_continue (bool) – Don’t throw any exception in case a host is unreachable or the playbooks run with errors
  • run_as (str) – run the command as this user. This is equivalent to passing become=yes and become_user=user but become_method can be passed to modify the priviledge escalation method. (default to sudo).
  • kwargs – keywords argument to pass to the shell module or as top level args.
Raises:
  • enoslib.errors.EnosFailedHostsError – if a task returns an error on a host and on_error_continue==False
  • enoslib.errors.EnosUnreachableHostsError – if a host is unreachable (through ssh) and on_error_continue==False
Returns:

Dict combining the stdout and stderr of ok and failed hosts and every results of tasks executed (this may include the fact gathering tasks)

Example:

# Inventory
[control1]
enos-0
[control2]
enos-1

# Python
result = run_command("date", inventory)

# Result
{
    'failed': {},
    'ok':
    {
        u'enos-0':
        {
            'stderr': u'',
            'stdout': u'Tue Oct 31 04:53:04 GMT 2017'
        },
        u'enos-1':
        {
            'stderr': u'',
            'stdout': u'Tue Oct 31 04:53:05 GMT 2017'}
        },
    'results': [...]
}

If facts are gathered it is possible to use ansible templating

result = run_command("control*", "ping -c 1
{{hostvars['enos-1']['ansible_' + n1].ipv4.address}}", inventory)

Command can be run asynchronously using the corresponding Ansible options (see https://docs.ansible.com/ansible/latest/user_guide/playbooks_async.html)

result = run_command("date", roles=roles, async=20, poll=0)

Note that the actual result isn’t available in the result file but will be available through a file specified in the result object.

enoslib.api.run_play(play_source, *, inventory_path=None, roles=None, extra_vars=None, on_error_continue=False)

Run a play.

Parameters:
  • play_source (dict) – ansible task
  • inventory_path (str) – inventory to use
  • extra_vars (dict) – extra_vars to use
  • on_error_continue (bool) – Don’t throw any exception in case a host is unreachable or the playbooks run with errors
Raises:
  • enoslib.errors.EnosFailedHostsError – if a task returns an error on a host and on_error_continue==False
  • enoslib.errors.EnosUnreachableHostsError – if a host is unreachable (through ssh) and on_error_continue==False
Returns:

List of all the results

enoslib.api.wait_ssh(roles: MutableMapping[str, List[enoslib.host.Host]], retries: int = 100, interval: int = 30) → None

Wait for all the machines to be ssh-reachable

Let ansible initiates a communication and retries if needed.

Parameters:
  • roles – Roles to wait for
  • retries – Number of time we’ll be retrying an SSH connection
  • interval – Interval to wait in seconds between two retries