Skip to content
Advertisement

fabric 2 traffic generation with non-blocking commands

I need to run some tests with a traffic generator that has different client and server commands. I would like to roll this into a fabric2 script which executes the traffic generation commands while cd’d into /root.

I have public-key authentication on the iperf machines. How can I run this traffic generation test under fabric2?

Advertisement

Answer

This was a little interesting to get running because the fabric2 docs don’t include much information about run() arguments… you need to look at the invoke Runner.run() documentation to see all fabric run() keywords.

The key to making iperf work in this case was setting pty=True and asynchronous=True when I run the iperf server commands. If I did not run the iperf server as asynchronous, it would block execution of the iperf client command.

# Save this script as run_iperf.py and run with "python run_iperf.py"
from getpass import getuser
import os

#from fabric import Config, SerialGroup, ThreadingGroup, exceptions, runners
#from fabric.exceptions import GroupException
from fabric import Connection

server_vm = "10.1.0.1"
client_vm = "10.2.0.1"

# This matters because my user .ssh/id_rsa.pub is authorized on the remote sytems
assert getuser()=="mpenning"

hosts = list()
conn1 = Connection(host=client_vm, user="root",
    connect_kwargs={"key_filename": os.path.expanduser("~/.ssh/id_rsa")})
conn2 = Connection(host=server_vm, user="root",
    connect_kwargs={"key_filename": os.path.expanduser("~/.ssh/id_rsa")})
hosts.append(conn1)
hosts.append(conn2)

iperf_udp_client_cmd = "nice -19 iperf3 --plus-more-client-commands"
iperf_udp_server_cmd = "nice -19 iperf3 --plus-more-server-commands"

# ThreadingGroup is optional for this use case, but the iperf commands
#     definitely require pty and asynchronous (server-side)...
#     ThreadingGroup() is required for concurrent fabric commands.
#
# Uncomment below to use ThreadingGroup()...
# t_hosts = ThreadingGroup.from_connections(hosts)
#
# also ref invoke Runner.run() for more run() args:
#     -> https://github.com/pyinvoke/invoke/blob/master/invoke/runners.py
with conn2.cd("/root"):
    conn2.run(iperf_udp_server_cmd, pty=True, asynchronous=True, disown=False, echo=True)
    
with conn1.cd("/root"):
    conn1.run("sleep 1;%s" % iperf_udp_client_cmd, pty=True, asynchronous=False, echo=True)

This script was loosely based-on this answer: https://stackoverflow.com/a/53763786/667301

Advertisement