Easily manage multiple Circus instances across multiple hosts.
Barnum currently relies on a very specific directory structure in order to discover Circus hosts:
tree /users/user1/circus
├── host1
│ ├── circus.ini
│ ├── circus.log
│ ├── watcher1.stderr.log
│ └── watcher1.stdout.log
└── init_circus -> /users/$USER/circus/init_circus
In other words, it expects that every user that is running a Circus instance will have a ~/circus
directory, and that this each child directory thereof will contain a circus.ini
folder. Each circus.ini
file it discovered will be parsed to determine its endpoint, and the host will be derived from the name its parent. Then, ssh
commands will be built from this information, and used to delegate commands across multiple users/hosts simultaneously (threaded).
You will also need a config file, so that barnum
knows what to search for.
Create circus_users.yaml
in the same directory as barnum.py
. Its contents should look something like this:
---
- user1
- user2
Perform Circus operations across multiple hosts
$ python barnum.py --verbose
barnum: Circus is configured on the following hosts: host1, host2
barnum: Processing host1
barnum: Processing host2
barnum: bailey cmd: ssh -q host1 bailey --verbose
barnum: bailey cmd: ssh -q host2 bailey --verbose
bailey: Derived circus user user1 from /etc/systemd/system/circus_user1_host2.service
bailey: circus cmd: circusctl --endpoint tcp://host2:8385 status
bailey: Derived circus user user2 from /etc/systemd/system/circus_user2_host1.service
bailey: circus cmd: circusctl --endpoint tcp://host1:5775 status
bailey: Derived circus user user3 from /etc/systemd/system/circus_user3_host2.service
bailey: circus cmd: circusctl --endpoint tcp://host2:5555 status
--- HOST1 ---
--------------------------------------------------------------------------------
circus_user2_host1.service enabled active (running)
watcher1: active
================================================================================
--- HOST2 ---
--------------------------------------------------------------------------------
circus_user1_host2.service enabled active (running)
watcher2: active
--------------------------------------------------------------------------------
circus_user3_host2.service enabled active (running)
watcher3: active
--------------------------------------------------------------------------------
circus_user4_host2.service disabled inactive (dead)
No circus expected
================================================================================
What's happening here:
- For each user in
circus_users.yaml
, derive the hosts it hascircus
instances on from the directory structure described above - For every host:
- SSH to
host_n
- Use
sysctl list-unit-files
to determine allcircus
unit files - Examine each unit file to determine the user it is for
- Call
bailey
for each user onhost_n
- SSH to
Get status of all Circus instances run on host1
:
$ python barnum.py host1 --verbose
Circus is configured on the following hosts: host1
Processing user1@host1
bailey cmd: ssh -q host1 /path/to/bailey user1 --verbose
circus cmd: circusctl --endpoint tcp://host1:5775 status
---
watcher1: active
What's happening here:
- SSH to
host1
- Use
sysctl list-unit-files
to determine allcircus
unit files - Examine each unit file to determine the user it is for
- For each user:
- Construct path to
circus
config file based on given user and host - Parse config file to determine
circus
endpoint - Call
bailey
for derived endpoint
- Construct path to
Get status of Circus instance run by user1@host1
.
$ python barnum.py user1@host1 --verbose
Circus is configured on the following hosts: host1
Processing user1@host1
bailey cmd: ssh -q host1 bailey user1 --verbose
circus cmd: circusctl --endpoint tcp://host1:5775 status
---
watcher1: active
What's happening here:
- SSH to
host1
- Construct path to
circus
config file based on given user and host - Parse config file to determine
circus
endpoint - Call
bailey
for derived endpoint
There are two advanced use cases here:
- Send commands to
bailey
- Send commands to
circus
- Send commands to both
bailey
andcircus
It is useful to experiment with these using --dry-run
, in order to prevent things from getting broken. For example,
$ python barnum.py user1@host1 --verbose --dry-run
barnum: Processing user1@host1
---
DRY RUN; would execute: ssh -q host1 bailey user1 --verbose
This would print the help message for every bailey
instance:
$ python barnum.py -- --help
To send specific circus
commands to each bailey
instance, you'll need to use something like the following:
$ python barnum.py user1@host1 --verbose -- -- stats
Everything following the --
will be sent directly to bailey
, without any changes. bailey
will then send everything after the second --
directly to circus
(more on that below).
Perform Circus operations on a single hosts (but possibly multiple users)
Get status of all Circus instances run on current host (host1
):
$ bailey --verbose
--- host1 ---
--------------------------------------------------------------------------------
circus_user1_host1.service disabled inactive (dead)
No circus expected
--------------------------------------------------------------------------------
bailey: Derived circus user user1 from /etc/systemd/system/circus_user1_host1.service
bailey: circus cmd: circusctl --endpoint tcp://host1:5755 status
circus_user1_host1.service enabled active (running)
watcher1: active
================================================================================
What's happening here:
- Use
sysctl list-unit-files
to determine allcircus
unit files - Examine each unit file to determine the user it is for
- For each user:
- Construct path to
circus
config file based on given user and host - Parse config file to determine
circus
endpoint - Call
bailey
for derived endpoint
- Construct path to
Get status of Circus instance run by user1@host1
(given user at current host).
$ bailey user1 --verbose
bailey: circus cmd: circusctl --endpoint tcp://host1:5555 status
watcher1: active
What's happening here:
- Construct path to
circus
config file based on given user and host - Parse config file to determine
circus
endpoint - Call
bailey
for derived endpoint
To send specific circus
commands, you'll need to use something like the following:
$ python barnum.py user1@host1 --verbose -- stats
Everything following the --
will be sent directly to circus
, without any changes