OneLab - Future Internet Testbeds

nepi-ng - D - testbed preping

Preparation

At this point, you should have a clear understanding of how to design your experiment using nepi-ng. In this tutorial section, we come back to the initialization and preparation stages, that we had done manually at first - i.e. using the shell tools - and show how to account for these various preparation tasks in a nepi-ng script.

To this end we will improve our script so that it takes care of initializations, and specifically we will add a command line option that, when enabled:

  • loads the ubuntu image on the nodes that we do use,
  • and makes sure that all the nodes that we do not use are actually turned off.

It is a rather common need for all experiments to take these aspects into account. We do recommend to make image loading an option though, since performing this for every run vey quickly gets in the way when fine-tuning your experiment.

Please note that the script will not try to get a lease automatically, instead we keep the simple policy of just checking that we have a valid lease.

Like always, we will improve the code by small incremental changes.

Important note on shell tools

Convenience tools are mostly just aliases

Before we dive in this area, we need to stress an important point. In the tutorial on the shell tools, we had seen sessions like this:

rleases
all-off
n 1-5 33,37 ~3
rload -i fedora

It is important to emphasize that the commands involved here are all volatile bash materials like aliases or functions. This means that, as of beginning of Feb. 2018 at least, if you try to run from your laptop something like this:

$ ssh inria_r2lab.tutorial@faraday.inria.fr rleases
bash: rleases: command not found

you get an error, that is to be compared this with:

$ ssh inria_r2lab.tutorial@faraday.inria.fr rhubarbe leases
----- <Leases from PLCAPIproxy@https://r2labapi.inria.fr:443/PLCAPI/ - 25 lease(s)>
  1  < from 02-22 @ 08:00 until 09:00 CET inria_oai
...

The rationale being that there is a need for very short commands in an interactive shell environment. But when invoking commands remotely through ssh, you don't run bash and so the bash-written convenience layer does not come into play.

How to find out long commands

For starters, as a rule of thumb, all convenience commands that are derived from rhubarbe are made up the same way. Just like rleases is an alias for rhubarbe leases, you will find that rbye is an alias for rhubarbe bye.

inria_r2lab.tutorial@faraday:~$ type rload
rload is aliased to `rhubarbe load'
inria_r2lab.tutorial@faraday:~$ type rwait
rwait is aliased to `rhubarbe wait'

As you can see, it is very easy to find out about a given command when logged on faraday, using bash's built-in type command; note that type is much more powerful and accurate than the old-school which thing, that is only able to locate a command along your path, while type knowns about aliases and functions as well.

inria_r2lab.tutorial@faraday:~$ which rwait
inria_r2lab.tutorial@faraday:~$

How to use short commands in scripts

Finally, note that you can expose short commands in your scripts by adding a line Like this in your shell script:

# this would define e.g. the 'rwait' command
source /etc/profile.d/faraday.sh

The same goes of course for convenience tools exposed from the nodes environment; as we have seen on a few occasions before, if you need to use any of these commands in code meant to run on nodes, you can insert this line in your bash script:

# this would define e.g. the `r2lab-id` command
source /etc/profile.d/nodes.sh

All this being said, let us now see in the next tab D1 how to extend the A5 script and turn it into D1 that knows how to load images.

Objective

When working on an experiment, you will find yourself making several reservations, as not everything works as planned the first time.

For this reason it is useful to design your experiment script so that it can be used both:

  • at the beginning of your reserved timeslot, and in this case you will need the script to load the image of your choice on the nodes,

  • or the rest of the time, when you just need to re-run everything, but not to necessarily to reload images, given that this is relatively time-consuming.

Starting point

It is the purpose of the present step, to show you how to simply add a command line option that, when provided, triggers image loading.

For this step, we start back from the last code in the A section - namely A5-ping.py, remember:

d1

The code

Every time we will see a piece of code, you can download the raw code with the right-most button.

#!/usr/bin/env python3

from argparse import ArgumentParser

from asynciojobs import Scheduler

from apssh import SshNode, SshJob
from apssh import Run, RunString

##########
gateway_hostname  = 'faraday.inria.fr'
gateway_username  = 'inria_r2lab.tutorial'
verbose_ssh = False

parser = ArgumentParser()
parser.add_argument("-s", "--slice", default=gateway_username,
                    help="specify an alternate slicename, default={}"
                         .format(gateway_username))
parser.add_argument("-l", "--load", default=False, action='store_true',
                    help="load the ubuntu image on nodes before starting")
parser.add_argument("-v", "--verbose-ssh", default=False, action='store_true',
                    help="run ssh in verbose mode")
args = parser.parse_args()

gateway_username = args.slice
verbose_ssh = args.verbose_ssh

##########
faraday = SshNode(hostname = gateway_hostname, username = gateway_username,
                  verbose = verbose_ssh)

node1 = SshNode(gateway = faraday, hostname = "fit01", username = "root",
                verbose = verbose_ssh)
node2 = SshNode(gateway = faraday, hostname = "fit02", username = "root",
                verbose = verbose_ssh)

##########
# create an orchestration scheduler
scheduler = Scheduler()

##########
check_lease = SshJob(
    # checking the lease is done on the gateway
    node = faraday,
    # this means that a failure in any of the commands
    # will cause the scheduler to bail out immediately
    critical = True,
    command = Run("rhubarbe leases --check"),
    scheduler = scheduler,
)

# the job to wait before proceeding
ready_requirement = check_lease
# has the user requested to load images ?
if args.load:
    ready_requirement = SshJob(
        node = faraday,
        commands = [
            Run('rhubarbe load -i ubuntu 1 2'),
            Run('rhubarbe wait 1 2'),
        ],
        required = check_lease,
        scheduler = scheduler,
    )

##########
# setting up the data interface on both fit01 and fit02
init_node_01 = SshJob(
    node = node1,
    command = Run("turn-on-data"),
    required = ready_requirement,
    scheduler = scheduler,
)
init_node_02 = SshJob(
    node = node2,
    command = Run("turn-on-data"),
    required = ready_requirement,
    scheduler = scheduler,
)

# the command we want to run in node1 is as simple as it gets
ping = SshJob(
    node = node1,
    required = (init_node_01, init_node_02),
    # let's be more specific about what to run
    # we will soon see other things we can do on an ssh connection
    command = Run('ping', '-c1', '-I', 'data', 'data02'),
    scheduler = scheduler,
)

##########
# run the scheduler
ok = scheduler.orchestrate()
# give details if it failed
ok or scheduler.debrief()

# we say this is a success if the ping command succeeded
# the result() of the SshJob is the value that the command
# returns to the OS
# so it's a success if this value is 0
success = ok and ping.result() == 0

# producing a dot file for illustration
scheduler.export_as_dotfile("D1.dot")

# return something useful to your OS
exit(0 if success else 1)

Sample output

Here's the output of the script when run with the -l option.


faraday.inria.fr:Checking current reservation for inria_r2lab.tutorial : OK
faraday.inria.fr:Found binary frisbeed as /usr/sbin/frisbeed
faraday.inria.fr:Found binary nc as /bin/nc
faraday.inria.fr:08:44:04 - +000s: Selection: fit01 fit02
faraday.inria.fr:08:44:04 - +000s: Loading image /var/lib/rhubarbe-images/ubuntu.ndz
faraday.inria.fr:08:44:04 - +000s: AUTH: checking for a valid lease
faraday.inria.fr:08:44:04 - +000s: AUTH: access granted
faraday.inria.fr:08:44:04 - +000s: fit02 reboot = Sending message 'reset' to CMC reboot02
faraday.inria.fr:08:44:04 - +000s: fit01 reboot = Sending message 'reset' to CMC reboot01
faraday.inria.fr:08:44:06 - +002s: fit02 reboot = idling for 15s
faraday.inria.fr:08:44:06 - +002s: fit01 reboot = idling for 15s
faraday.inria.fr:08:44:22 - +018s: started 
faraday.inria.fr:08:44:22 - +018s: fit02 frisbee_status = trying to telnet..
faraday.inria.fr:08:44:22 - +018s: fit01 frisbee_status = trying to telnet..
faraday.inria.fr:08:44:24 - +020s: fit02 frisbee_status = timed out..
faraday.inria.fr:08:44:24 - +020s: fit02 frisbee_status = backing off for 4.03s
faraday.inria.fr:08:44:24 - +020s: fit01 frisbee_status = timed out..
faraday.inria.fr:08:44:24 - +020s: fit01 frisbee_status = backing off for 3.94s
faraday.inria.fr:08:44:28 - +024s: fit01 frisbee_status = trying to telnet..
faraday.inria.fr:08:44:29 - +024s: fit02 frisbee_status = trying to telnet..
faraday.inria.fr:08:44:30 - +026s: fit01 frisbee_status = timed out..
faraday.inria.fr:08:44:30 - +026s: fit01 frisbee_status = backing off for 2.21s
faraday.inria.fr:08:44:31 - +026s: fit02 frisbee_status = timed out..
faraday.inria.fr:08:44:31 - +026s: fit02 frisbee_status = backing off for 4.4s
faraday.inria.fr:08:44:33 - +028s: fit01 frisbee_status = trying to telnet..
faraday.inria.fr:08:44:35 - +030s: fit01 frisbee_status = timed out..
faraday.inria.fr:08:44:35 - +030s: fit01 frisbee_status = backing off for 4.43s
faraday.inria.fr:08:44:35 - +030s: fit02 frisbee_status = trying to telnet..
faraday.inria.fr:08:44:37 - +032s: fit02 frisbee_status = timed out..
faraday.inria.fr:08:44:37 - +032s: fit02 frisbee_status = backing off for 1.78s
faraday.inria.fr:08:44:39 - +034s: fit02 frisbee_status = trying to telnet..
faraday.inria.fr:08:44:39 - +034s: fit02 frisbee_status = starting frisbee client
faraday.inria.fr:08:44:39 - +034s: fit01 frisbee_status = trying to telnet..
faraday.inria.fr:08:44:39 - +034s: fit01 frisbee_status = starting frisbee client
faraday.inria.fr:08:45:01 - +057s: fit02 Uploading successful
faraday.inria.fr:08:45:01 - +057s: fit02 reboot = Sending message 'reset' to CMC reboot02
faraday.inria.fr:|                                                   |  0% |0.00s|ETA:  --:--:--
|#                                                   |  3% |1.05s|ETA:  0:00:34
|###                                                 |  6% |1.27s|ETA:  0:00:19
|####                                                |  9% |1.85s|ETA:  0:00:18
|#####                                               | 11% |1.99s|ETA:  0:00:15
|#######                                             | 14% |3.40s|ETA:  0:00:20
|########                                            | 16% |3.57s|ETA:  0:00:18
|##########                                          | 19% |4.67s|ETA:  0:00:19
|###########                                         | 22% |5.11s|ETA:  0:00:17
|#############                                       | 26% |5.46s|ETA:  0:00:15
|###############                                     | 29% |6.19s|ETA:  0:00:15
|################                                    | 32% |7.00s|ETA:  0:00:14
|##################                                  | 36% |7.93s|ETA:  0:00:13
|####################                                | 39% |9.41s|ETA:  0:00:14
|#####################                               | 41% |9.67s|ETA:  0:00:13
|######################                             | 43% |10.40s|ETA:  0:00:13
|#######################                            | 46% |10.88s|ETA:  0:00:12
|#########################                          | 49% |11.28s|ETA:  0:00:11
|###########################                        | 53% |11.73s|ETA:  0:00:10
|#############################                      | 57% |12.29s|ETA:  0:00:09
|##############################                     | 60% |14.43s|ETA:  0:00:09
|################################                   | 63% |15.06s|ETA:  0:00:08
|#################################                  | 65% |15.46s|ETA:  0:00:08
|###################################                | 69% |15.63s|ETA:  0:00:06
|####################################               | 72% |15.77s|ETA:  0:00:06
|#####################################              | 73% |15.96s|ETA:  0:00:05
|#######################################            | 77% |16.60s|ETA:  0:00:04
|#########################################          | 80% |17.28s|ETA:  0:00:04
|###########################################        | 84% |17.57s|ETA:  0:00:03
|############################################       | 88% |19.98s|ETA:  0:00:02
|##############################################     | 91% |20.11s|ETA:  0:00:01
|################################################   | 95% |20.55s|ETA:  0:00:01
|################################################## | 99% |21.00s|ETA:  0:00:00
|################################################## | 99% |22.58s|ETA:  0:00:00
|###################################################|100% |23.05s|Time: 0:00:23
faraday.inria.fr:08:45:02 - +057s: fit01 Uploading successful
faraday.inria.fr:08:45:02 - +057s: fit01 reboot = Sending message 'reset' to CMC reboot01
faraday.inria.fr:08:45:04 - +059s: stopped 
faraday.inria.fr::ssh OK
faraday.inria.fr::ssh OK
fit01:turn-on-data: data network on interface data
fit02:turn-on-data: data network on interface data
fit02:data
fit01:data
fit01:PING data02 (192.168.2.2) from 192.168.2.1 data: 56(84) bytes of data.
fit01:64 bytes from data02 (192.168.2.2): icmp_seq=1 ttl=64 time=0.456 ms
fit01:
fit01:--- data02 ping statistics ---
fit01:1 packets transmitted, 1 received, 0% packet loss, time 0ms
fit01:rtt min/avg/max/mdev = 0.456/0.456/0.456/0.000 ms

          

Next

We will now see in tab D2 how to also make sure all the rest of the testbed is turned off.

Objectives

In this section we study a variant D2, that is naturally based on D1, and that also makes sure that the unused nodes in the testbed are properly turned off.

Selection in rhubarbe

For doing so, we take advantage of a feature in rhubarbe, that is designed to make node selection a smooth process; in particular we use:

  • the --all (or just -a) option that selects all nodes,
  • and the ~ operator for removing nodes from the selection.

So for example

inria_r2lab.tutorial@faraday:~$ rhubarbe nodes -a
fit01 fit02 fit03 fit04 fit05 fit06 fit07 fit08 fit09 fit10 fit11 fit12 fit13 fit14 fit15 fit16 fit17 fit18 fit19 fit20 fit21 fit22 fit23 fit24 fit25 fit26 fit27 fit28 fit29 fit30 fit31 fit32 fit33 fit34 fit35 fit36 fit37

selects all 37 nodes, while

inria_r2lab.tutorial@faraday:~$ rhubarbe nodes -a ~1 ~2
fit03 fit04 fit05 fit06 fit07 fit08 fit09 fit10 fit11 fit12 fit13 fit14 fit15 fit16 fit17 fit18 fit19 fit20 fit21 fit22 fit23 fit24 fit25 fit26 fit27 fit28 fit29 fit30 fit31 fit32 fit33 fit34 fit35 fit36 fit37

selects all nodes but nodes number 1 and 2. This is the basic mechanism that we use to invoke the rhubarbe bye (a.k.a. all-off) command to turn off all the nodes that are not involved in our experiment.

requirement(s)

Also you will notice in this code that the required value for a given job may be either a plain job object, or a collection of jobs; in the code above, the ready_requirement variable, that was a single job object in D1-prep.py, is made a list with 2 jobs, and this is how we simply achieve the layout for the new dependency graph.

The code

#!/usr/bin/env python3

from argparse import ArgumentParser

from asynciojobs import Scheduler

from apssh import SshNode, SshJob
from apssh import Run, RunString

##########
gateway_hostname  = 'faraday.inria.fr'
gateway_username  = 'inria_r2lab.tutorial'
verbose_ssh = False

parser = ArgumentParser()
parser.add_argument("-s", "--slice", default=gateway_username,
                    help="specify an alternate slicename, default={}"
                         .format(gateway_username))
parser.add_argument("-l", "--load", default=False, action='store_true',
                    help="load the ubuntu image on nodes before starting")
parser.add_argument("-v", "--verbose-ssh", default=False, action='store_true',
                    help="run ssh in verbose mode")
args = parser.parse_args()

gateway_username = args.slice
verbose_ssh = args.verbose_ssh

##########
faraday = SshNode(hostname = gateway_hostname, username = gateway_username,
                  verbose = verbose_ssh)

node1 = SshNode(gateway = faraday, hostname = "fit01", username = "root",
                verbose = verbose_ssh)
node2 = SshNode(gateway = faraday, hostname = "fit02", username = "root",
                verbose = verbose_ssh)

##########
# create an orchestration scheduler
scheduler = Scheduler()

##########
check_lease = SshJob(
    # checking the lease is done on the gateway
    node = faraday,
    # this means that a failure in any of the commands
    # will cause the scheduler to bail out immediately
    critical = True,
    command = Run("rhubarbe leases --check"),
    scheduler = scheduler,
)

# the job to wait before proceeding
ready_requirement = check_lease
# has the user requested to load images ?
# if so, we just need to wait for 2 jobs to complete instead of 1
if args.load:
    ready_requirement = [
        SshJob(
            node = faraday,
            commands = [
                Run('rhubarbe load -i ubuntu 1 2'),
                Run('rhubarbe wait 1 2'),
                ],
            required = check_lease,
            scheduler = scheduler,
        ),
        SshJob(
            node = faraday,
            commands = [
                Run('rhubarbe bye -a ~1 ~2')
            ],
            required = check_lease,
            scheduler = scheduler,
        )
    ]

##########
# setting up the data interface on both fit01 and fit02
init_node_01 = SshJob(
    node = node1,
    command = Run("turn-on-data"),
    required = ready_requirement,
    scheduler = scheduler,
)
init_node_02 = SshJob(
    node = node2,
    command = Run("turn-on-data"),
    required = ready_requirement,
    scheduler = scheduler,
)

# the command we want to run in node1 is as simple as it gets
ping = SshJob(
    node = node1,
    required = (init_node_01, init_node_02),
    # let's be more specific about what to run
    # we will soon see other things we can do on an ssh connection
    command = Run('ping', '-c1', '-I', 'data', 'data02'),
    scheduler = scheduler,
)

##########
# run the scheduler
ok = scheduler.orchestrate()
# give details if it failed
ok or scheduler.debrief()

# we say this is a success if the ping command succeeded
# the result() of the SshJob is the value that the command
# returns to the OS
# so it's a success if this value is 0
success = ok and ping.result() == 0

# producing a dot file for illustration
scheduler.export_as_dotfile("D2.dot")

# return something useful to your OS
exit(0 if success else 1)

Sample output

No great news here, just observe how all the other nodes, and the phones, get turned off while the 2 target nodes are being imaged.


faraday.inria.fr:Checking current reservation for inria_r2lab.tutorial : OK
faraday.inria.fr:Found binary frisbeed as /usr/sbin/frisbeed
faraday.inria.fr:Found binary nc as /bin/nc
faraday.inria.fr:08:46:44 - +000s: Selection: fit01 fit02
faraday.inria.fr:08:46:44 - +000s: Loading image /var/lib/rhubarbe-images/ubuntu.ndz
faraday.inria.fr:08:46:44 - +000s: AUTH: checking for a valid lease
faraday.inria.fr:08:46:44 - +000s: AUTH: access granted
faraday.inria.fr:reboot23:ok
faraday.inria.fr:reboot13:ok
faraday.inria.fr:reboot14:ok
faraday.inria.fr:reboot12:ok
faraday.inria.fr:08:46:44 - +000s: fit01 reboot = Sending message 'reset' to CMC reboot01
faraday.inria.fr:08:46:44 - +000s: fit02 reboot = Sending message 'reset' to CMC reboot02
faraday.inria.fr:reboot29:ok
faraday.inria.fr:reboot22:ok
faraday.inria.fr:reboot36:ok
faraday.inria.fr:reboot19:ok
faraday.inria.fr:reboot06:ok
faraday.inria.fr:reboot30:ok
faraday.inria.fr:reboot11:ok
faraday.inria.fr:reboot25:ok
faraday.inria.fr:reboot31:ok
faraday.inria.fr:reboot34:ok
faraday.inria.fr:reboot09:ok
faraday.inria.fr:reboot03:ok
faraday.inria.fr:reboot16:ok
faraday.inria.fr:reboot26:ok
faraday.inria.fr:reboot28:ok
faraday.inria.fr:reboot04:ok
faraday.inria.fr:reboot15:ok
faraday.inria.fr:reboot20:ok
faraday.inria.fr:reboot17:ok
faraday.inria.fr:reboot21:ok
faraday.inria.fr:reboot33:ok
faraday.inria.fr:reboot05:ok
faraday.inria.fr:reboot07:ok
faraday.inria.fr:reboot37:ok
faraday.inria.fr:reboot32:ok
faraday.inria.fr:reboot10:ok
faraday.inria.fr:reboot08:ok
faraday.inria.fr:reboot27:ok
faraday.inria.fr:reboot35:ok
faraday.inria.fr:reboot18:ok
faraday.inria.fr:reboot24:ok
faraday.inria.fr:reboot08:already off
faraday.inria.fr:reboot27:already off
faraday.inria.fr:reboot10:already off
faraday.inria.fr:reboot22:already off
faraday.inria.fr:reboot34:already off
faraday.inria.fr:reboot32:already off
faraday.inria.fr:reboot33:already off
faraday.inria.fr:reboot09:already off
faraday.inria.fr:reboot07:already off
faraday.inria.fr:reboot35:already off
faraday.inria.fr:reboot29:already off
faraday.inria.fr:reboot03:already off
faraday.inria.fr:reboot04:already off
faraday.inria.fr:reboot30:already off
faraday.inria.fr:reboot06:already off
faraday.inria.fr:reboot21:already off
faraday.inria.fr:reboot17:already off
faraday.inria.fr:reboot26:already off
faraday.inria.fr:reboot05:already off
faraday.inria.fr:reboot11:already off
faraday.inria.fr:reboot36:already off
faraday.inria.fr:reboot31:already off
faraday.inria.fr:reboot12:already off
faraday.inria.fr:reboot37:already off
faraday.inria.fr:reboot13:already off
faraday.inria.fr:reboot28:already off
faraday.inria.fr:reboot18:already off
faraday.inria.fr:reboot14:already off
faraday.inria.fr:reboot25:already off
faraday.inria.fr:reboot16:already off
faraday.inria.fr:reboot20:already off
faraday.inria.fr:reboot15:already off
faraday.inria.fr:reboot23:already off
faraday.inria.fr:reboot19:already off
faraday.inria.fr:reboot24:already off
faraday.inria.fr:ssh -i /home/faraday/r2lab-embedded/mac-ssh-keys/macphone tester@macphone1 phone-off
faraday.inria.fr:Turning OFF phone : turning on airplane mode
faraday.inria.fr:08:46:46 - +002s: fit01 reboot = idling for 15s
faraday.inria.fr:08:46:46 - +002s: fit02 reboot = idling for 15s
faraday.inria.fr:Broadcasting: Intent { act=android.intent.action.AIRPLANE_MODE (has extras) }
faraday.inria.fr:Broadcast completed: result=0
faraday.inria.fr:ssh -i /home/faraday/r2lab-embedded/mac-ssh-keys/macphone tester@macphone2 phone-off
faraday.inria.fr:Turning OFF phone : turning on airplane mode
faraday.inria.fr:Broadcasting: Intent { act=android.intent.action.AIRPLANE_MODE (has extras) }
faraday.inria.fr:Broadcast completed: result=0
faraday.inria.fr:08:47:02 - +018s: started 
faraday.inria.fr:08:47:02 - +018s: fit02 frisbee_status = trying to telnet..
faraday.inria.fr:08:47:02 - +018s: fit01 frisbee_status = trying to telnet..
faraday.inria.fr:08:47:04 - +020s: fit02 frisbee_status = timed out..
faraday.inria.fr:08:47:04 - +020s: fit02 frisbee_status = backing off for 4.33s
faraday.inria.fr:08:47:04 - +020s: fit01 frisbee_status = timed out..
faraday.inria.fr:08:47:04 - +020s: fit01 frisbee_status = backing off for 4.27s
faraday.inria.fr:08:47:08 - +024s: fit01 frisbee_status = trying to telnet..
faraday.inria.fr:08:47:08 - +024s: fit02 frisbee_status = trying to telnet..
faraday.inria.fr:08:47:10 - +026s: fit01 frisbee_status = timed out..
faraday.inria.fr:08:47:10 - +026s: fit01 frisbee_status = backing off for 2.94s
faraday.inria.fr:08:47:10 - +026s: fit02 frisbee_status = timed out..
faraday.inria.fr:08:47:10 - +026s: fit02 frisbee_status = backing off for 1.76s
faraday.inria.fr:08:47:12 - +028s: fit02 frisbee_status = trying to telnet..
faraday.inria.fr:08:47:13 - +029s: fit01 frisbee_status = trying to telnet..
faraday.inria.fr:08:47:14 - +030s: fit02 frisbee_status = timed out..
faraday.inria.fr:08:47:14 - +030s: fit02 frisbee_status = backing off for 3.21s
faraday.inria.fr:08:47:15 - +031s: fit01 frisbee_status = timed out..
faraday.inria.fr:08:47:15 - +031s: fit01 frisbee_status = backing off for 2.72s
faraday.inria.fr:08:47:17 - +033s: fit02 frisbee_status = trying to telnet..
faraday.inria.fr:08:47:18 - +034s: fit01 frisbee_status = trying to telnet..
faraday.inria.fr:08:47:18 - +034s: fit01 frisbee_status = starting frisbee client
faraday.inria.fr:08:47:18 - +034s: fit02 frisbee_status = starting frisbee client
faraday.inria.fr:08:47:42 - +058s: fit01 Uploading successful
faraday.inria.fr:08:47:42 - +058s: fit01 reboot = Sending message 'reset' to CMC reboot01
faraday.inria.fr:|                                                   |  0% |0.00s|ETA:  --:--:--
|#                                                   |  3% |1.13s|ETA:  0:00:31
|###                                                 |  6% |1.32s|ETA:  0:00:18
|#####                                               | 10% |2.15s|ETA:  0:00:19
|#######                                             | 14% |2.40s|ETA:  0:00:14
|#########                                           | 17% |3.27s|ETA:  0:00:15
|##########                                          | 21% |3.51s|ETA:  0:00:13
|############                                        | 24% |4.61s|ETA:  0:00:14
|##############                                      | 27% |5.02s|ETA:  0:00:13
|##############                                      | 28% |5.64s|ETA:  0:00:14
|###############                                     | 30% |6.00s|ETA:  0:00:14
|#################                                   | 33% |6.72s|ETA:  0:00:13
|###################                                 | 37% |6.87s|ETA:  0:00:11
|#####################                               | 41% |7.47s|ETA:  0:00:10
|#######################                             | 45% |7.59s|ETA:  0:00:09
|########################                           | 48% |10.62s|ETA:  0:00:11
|##########################                         | 51% |10.74s|ETA:  0:00:10
|###########################                        | 54% |11.23s|ETA:  0:00:09
|#############################                      | 58% |11.37s|ETA:  0:00:08
|###############################                    | 61% |12.10s|ETA:  0:00:07
|################################                   | 64% |12.30s|ETA:  0:00:06
|##################################                 | 67% |13.41s|ETA:  0:00:06
|###################################                | 70% |15.60s|ETA:  0:00:06
|####################################               | 72% |16.11s|ETA:  0:00:06
|######################################             | 75% |16.27s|ETA:  0:00:05
|#######################################            | 78% |16.97s|ETA:  0:00:04
|#########################################          | 81% |17.41s|ETA:  0:00:03
|###########################################        | 84% |18.40s|ETA:  0:00:03
|############################################       | 87% |18.55s|ETA:  0:00:02
|##############################################     | 91% |21.06s|ETA:  0:00:02
|################################################   | 94% |21.23s|ETA:  0:00:01
|#################################################  | 97% |21.81s|ETA:  0:00:00
|################################################## | 99% |22.03s|ETA:  0:00:00
|################################################## | 99% |23.94s|ETA:  0:00:00
|###################################################|100% |24.42s|Time: 0:00:24
faraday.inria.fr:08:47:42 - +058s: fit02 Uploading successful
faraday.inria.fr:08:47:42 - +058s: fit02 reboot = Sending message 'reset' to CMC reboot02
faraday.inria.fr:08:47:44 - +060s: stopped 
faraday.inria.fr::ssh OK
faraday.inria.fr::ssh OK
fit02:turn-on-data: data network on interface data
fit01:turn-on-data: data network on interface data
fit01:data
fit02:data
fit01:PING data02 (192.168.2.2) from 192.168.2.1 data: 56(84) bytes of data.
fit01:64 bytes from data02 (192.168.2.2): icmp_seq=1 ttl=64 time=0.473 ms
fit01:
fit01:--- data02 ping statistics ---
fit01:1 packets transmitted, 1 received, 0% packet loss, time 0ms
fit01:rtt min/avg/max/mdev = 0.473/0.473/0.473/0.000 ms

          

Next

We will now see in tab D3 how to pass target nodes on the command-line.

Objectives

In this section, we will change the D2 script so that the target nodes can be passed on the command line, instead of using the hardwired nodes 1 and 2.

The r2lab python library

We take this opportunity to introduce the r2lab python library, that you need of course to install separately:

pip3 install r2lab

This library is designed to be, and hopefully to stay, very small; in this example we just use convenience functions like r2lab_hostname that lets us compute the hostname for one of the nodes from a variety of inputs, that can be either int or bytes or str.

This mostly is convenient to avoid ending up with hostname like fit1 with a missing 0, so as you can see it is very basic.

A complete reference can be found on readthedocs.io.

The code

#!/usr/bin/env python3

from argparse import ArgumentParser

from asynciojobs import Scheduler

from apssh import SshNode, SshJob
from apssh import Run, RunString

from r2lab import r2lab_hostname, r2lab_data

##########
gateway_hostname  = 'faraday.inria.fr'
gateway_username  = 'inria_r2lab.tutorial'
verbose_ssh = False

parser = ArgumentParser()
parser.add_argument("-s", "--slice", default=gateway_username,
                    help="specify an alternate slicename, default={}"
                         .format(gateway_username))
parser.add_argument("-l", "--load", default=False, action='store_true',
                    help="load the ubuntu image on nodes before starting")
parser.add_argument("-v", "--verbose-ssh", default=False, action='store_true',
                    help="run ssh in verbose mode")
parser.add_argument("-a", "--node-a", default="fit01",
                    help="packets are sent from this node")
parser.add_argument("-b", "--node-b", default="fit02",
                    help="packets are sent to this node")
args = parser.parse_args()

gateway_username = args.slice
verbose_ssh = args.verbose_ssh

##########
faraday = SshNode(hostname = gateway_hostname, username = gateway_username,
                  verbose = verbose_ssh)

# r2lab_hostname will accept inputs like '1', '01', or 'fit01'
hostnamea = r2lab_hostname(args.node_a)
hostnameb = r2lab_hostname(args.node_b)

nodea = SshNode(gateway = faraday, hostname = hostnamea, username = "root",
                verbose = verbose_ssh)
nodeb = SshNode(gateway = faraday, hostname = hostnameb, username = "root",
                verbose = verbose_ssh)

##########
# create an orchestration scheduler
scheduler = Scheduler()

##########
check_lease = SshJob(
    # checking the lease is done on the gateway
    node = faraday,
    # this means that a failure in any of the commands
    # will cause the scheduler to bail out immediately
    critical = True,
    command = Run("rhubarbe leases --check"),
    scheduler = scheduler,
)

# the job to wait before proceeding
ready_requirement = check_lease
# has the user requested to load images ?
# if so, we just need to wait for 2 jobs to complete instead of 1
if args.load:
    ready_requirement = [
        SshJob(
            node = faraday,
            commands = [
                Run('rhubarbe load -i ubuntu', hostnamea, hostnameb),
                Run('rhubarbe wait', hostnamea, hostnameb),
                ],
            required = check_lease,
            scheduler = scheduler,
        ),
        SshJob(
            node = faraday,
            commands = [
                Run('rhubarbe bye -a', '~'+hostnamea, '~'+hostnameb)
            ],
            required = check_lease,
            scheduler = scheduler,
        )
    ]

##########
# setting up the data interface on both fit01 and fit02
init_node_a = SshJob(
    node = nodea,
    command = Run("turn-on-data"),
    required = ready_requirement,
    scheduler = scheduler,
)
init_node_b = SshJob(
    node = nodeb,
    command = Run("turn-on-data"),
    required = ready_requirement,
    scheduler = scheduler,
)

# the name of receiver nodeb, on the data network, is e.g. data02
data_b = r2lab_data(hostnameb)

ping = SshJob(
    node = nodea,
    required = (init_node_a, init_node_b),
    # let's be more specific about what to run
    # we will soon see other things we can do on an ssh connection
    command = Run('ping', '-c1', '-I', 'data', data_b),
    scheduler = scheduler,
)

##########
# run the scheduler
ok = scheduler.orchestrate()
# give details if it failed
ok or scheduler.debrief()

# we say this is a success if the ping command succeeded
# the result() of the SshJob is the value that the command
# returns to the OS
# so it's a success if this value is 0
success = ok and ping.result() == 0

# producing a dot file for illustration
scheduler.export_as_dotfile("D3.dot")

# return something useful to your OS
exit(0 if success else 1)

Sample output

It is easy to select other nodes with the -a and -b option.


faraday.inria.fr:Checking current reservation for inria_r2lab.tutorial : OK
faraday.inria.fr:Found binary frisbeed as /usr/sbin/frisbeed
faraday.inria.fr:Found binary nc as /bin/nc
faraday.inria.fr:08:54:39 - +000s: Selection: fit10 fit20
faraday.inria.fr:08:54:39 - +000s: Loading image /var/lib/rhubarbe-images/ubuntu.ndz
faraday.inria.fr:08:54:39 - +000s: AUTH: checking for a valid lease
faraday.inria.fr:08:54:39 - +000s: AUTH: access granted
faraday.inria.fr:08:54:39 - +000s: fit10 reboot = Sending message 'reset' to CMC reboot10
faraday.inria.fr:reboot11:ok
faraday.inria.fr:08:54:39 - +000s: fit20 reboot = Sending message 'reset' to CMC reboot20
faraday.inria.fr:reboot12:ok
faraday.inria.fr:reboot23:ok
faraday.inria.fr:reboot24:ok
faraday.inria.fr:reboot13:ok
faraday.inria.fr:reboot15:ok
faraday.inria.fr:reboot27:ok
faraday.inria.fr:reboot18:ok
faraday.inria.fr:reboot14:ok
faraday.inria.fr:reboot34:ok
faraday.inria.fr:reboot17:ok
faraday.inria.fr:reboot25:ok
faraday.inria.fr:reboot19:ok
faraday.inria.fr:reboot31:ok
faraday.inria.fr:reboot21:ok
faraday.inria.fr:reboot22:ok
faraday.inria.fr:reboot16:ok
faraday.inria.fr:reboot36:ok
faraday.inria.fr:reboot01:ok
faraday.inria.fr:reboot30:ok
faraday.inria.fr:reboot37:ok
faraday.inria.fr:reboot29:ok
faraday.inria.fr:reboot28:ok
faraday.inria.fr:reboot33:ok
faraday.inria.fr:reboot26:ok
faraday.inria.fr:reboot32:ok
faraday.inria.fr:reboot35:ok
faraday.inria.fr:reboot05:ok
faraday.inria.fr:reboot04:ok
faraday.inria.fr:reboot03:ok
faraday.inria.fr:reboot08:ok
faraday.inria.fr:reboot06:ok
faraday.inria.fr:reboot09:ok
faraday.inria.fr:reboot07:ok
faraday.inria.fr:reboot02:ok
faraday.inria.fr:reboot09:already off
faraday.inria.fr:reboot15:already off
faraday.inria.fr:reboot37:already off
faraday.inria.fr:reboot35:already off
faraday.inria.fr:reboot21:already off
faraday.inria.fr:reboot05:already off
faraday.inria.fr:reboot16:already off
faraday.inria.fr:reboot07:already off
faraday.inria.fr:reboot29:already off
faraday.inria.fr:reboot12:already off
faraday.inria.fr:reboot03:already off
faraday.inria.fr:reboot30:already off
faraday.inria.fr:reboot11:already off
faraday.inria.fr:reboot28:already off
faraday.inria.fr:reboot33:already off
faraday.inria.fr:reboot36:already off
faraday.inria.fr:reboot32:already off
faraday.inria.fr:reboot14:already off
faraday.inria.fr:reboot17:already off
faraday.inria.fr:reboot24:already off
faraday.inria.fr:reboot02:ok
faraday.inria.fr:reboot01:ok
faraday.inria.fr:reboot19:already off
faraday.inria.fr:reboot06:already off
faraday.inria.fr:reboot27:already off
faraday.inria.fr:reboot13:already off
faraday.inria.fr:reboot25:already off
faraday.inria.fr:reboot26:already off
faraday.inria.fr:reboot31:already off
faraday.inria.fr:reboot04:already off
faraday.inria.fr:reboot08:already off
faraday.inria.fr:reboot34:already off
faraday.inria.fr:reboot22:already off
faraday.inria.fr:reboot18:already off
faraday.inria.fr:reboot23:already off
faraday.inria.fr:ssh -i /home/faraday/r2lab-embedded/mac-ssh-keys/macphone tester@macphone1 phone-off
faraday.inria.fr:Turning OFF phone : turning on airplane mode
faraday.inria.fr:08:54:41 - +002s: fit10 reboot = idling for 15s
faraday.inria.fr:08:54:41 - +002s: fit20 reboot = idling for 15s
faraday.inria.fr:Broadcasting: Intent { act=android.intent.action.AIRPLANE_MODE (has extras) }
faraday.inria.fr:Broadcast completed: result=0
faraday.inria.fr:ssh -i /home/faraday/r2lab-embedded/mac-ssh-keys/macphone tester@macphone2 phone-off
faraday.inria.fr:Turning OFF phone : turning on airplane mode
faraday.inria.fr:Broadcasting: Intent { act=android.intent.action.AIRPLANE_MODE (has extras) }
faraday.inria.fr:Broadcast completed: result=0
faraday.inria.fr:08:54:57 - +018s: started 
faraday.inria.fr:08:54:57 - +018s: fit20 frisbee_status = trying to telnet..
faraday.inria.fr:08:54:57 - +018s: fit10 frisbee_status = trying to telnet..
faraday.inria.fr:08:54:59 - +020s: fit20 frisbee_status = timed out..
faraday.inria.fr:08:54:59 - +020s: fit20 frisbee_status = backing off for 3.13s
faraday.inria.fr:08:54:59 - +020s: fit10 frisbee_status = timed out..
faraday.inria.fr:08:54:59 - +020s: fit10 frisbee_status = backing off for 4.39s
faraday.inria.fr:08:55:02 - +023s: fit20 frisbee_status = trying to telnet..
faraday.inria.fr:08:55:04 - +024s: fit10 frisbee_status = trying to telnet..
faraday.inria.fr:08:55:04 - +025s: fit20 frisbee_status = timed out..
faraday.inria.fr:08:55:04 - +025s: fit20 frisbee_status = backing off for 1.84s
faraday.inria.fr:08:55:06 - +026s: fit10 frisbee_status = timed out..
faraday.inria.fr:08:55:06 - +026s: fit10 frisbee_status = backing off for 2.82s
faraday.inria.fr:08:55:06 - +027s: fit20 frisbee_status = trying to telnet..
faraday.inria.fr:08:55:08 - +029s: fit20 frisbee_status = timed out..
faraday.inria.fr:08:55:08 - +029s: fit20 frisbee_status = backing off for 1.84s
faraday.inria.fr:08:55:08 - +029s: fit10 frisbee_status = trying to telnet..
faraday.inria.fr:08:55:10 - +030s: fit20 frisbee_status = trying to telnet..
faraday.inria.fr:08:55:10 - +031s: fit10 frisbee_status = timed out..
faraday.inria.fr:08:55:10 - +031s: fit10 frisbee_status = backing off for 2.96s
faraday.inria.fr:08:55:11 - +031s: fit20 frisbee_status = starting frisbee client
faraday.inria.fr:08:55:13 - +034s: fit10 frisbee_status = trying to telnet..
faraday.inria.fr:08:55:14 - +035s: fit10 frisbee_status = starting frisbee client
faraday.inria.fr:08:55:36 - +057s: fit20 Uploading successful
faraday.inria.fr:08:55:36 - +057s: fit20 reboot = Sending message 'reset' to CMC reboot20
faraday.inria.fr:|                                                   |  0% |0.00s|ETA:  --:--:--
|#                                                   |  3% |0.98s|ETA:  0:00:31
|###                                                 |  6% |1.94s|ETA:  0:00:30
|####                                                |  9% |3.31s|ETA:  0:00:31
|######                                              | 12% |4.33s|ETA:  0:00:31
|#######                                             | 14% |5.22s|ETA:  0:00:32
|########                                            | 16% |5.26s|ETA:  0:00:26
|##########                                          | 19% |6.60s|ETA:  0:00:27
|###########                                         | 21% |7.33s|ETA:  0:00:26
|############                                        | 24% |7.99s|ETA:  0:00:24
|##############                                      | 27% |9.25s|ETA:  0:00:24
|################                                    | 31% |9.93s|ETA:  0:00:22
|#################                                  | 34% |10.10s|ETA:  0:00:19
|##################                                 | 37% |10.56s|ETA:  0:00:17
|####################                               | 41% |11.23s|ETA:  0:00:16
|######################                             | 44% |12.39s|ETA:  0:00:15
|########################                           | 48% |12.85s|ETA:  0:00:13
|##########################                         | 51% |13.50s|ETA:  0:00:12
|############################                       | 55% |14.44s|ETA:  0:00:11
|#############################                      | 57% |15.19s|ETA:  0:00:11
|###############################                    | 61% |15.32s|ETA:  0:00:09
|################################                   | 64% |16.10s|ETA:  0:00:08
|##################################                 | 68% |17.01s|ETA:  0:00:07
|####################################               | 72% |17.95s|ETA:  0:00:06
|######################################             | 76% |18.25s|ETA:  0:00:05
|########################################           | 79% |18.58s|ETA:  0:00:04
|#########################################          | 82% |19.87s|ETA:  0:00:04
|##########################################         | 84% |21.20s|ETA:  0:00:04
|############################################       | 87% |21.73s|ETA:  0:00:03
|#############################################      | 90% |22.69s|ETA:  0:00:02
|###############################################    | 93% |23.45s|ETA:  0:00:01
|#################################################  | 96% |24.09s|ETA:  0:00:00
|################################################## | 99% |25.21s|ETA:  0:00:00
|###################################################|100% |27.60s|ETA:  0:00:00
|###################################################|100% |27.60s|Time: 0:00:27
faraday.inria.fr:08:55:39 - +059s: fit10 Uploading successful
faraday.inria.fr:08:55:39 - +059s: fit10 reboot = Sending message 'reset' to CMC reboot10
faraday.inria.fr:08:55:41 - +061s: stopped 
faraday.inria.fr::ssh OK
faraday.inria.fr::ssh OK
fit20:turn-on-data: data network on interface data
fit10:turn-on-data: data network on interface data
fit20:data
fit10:data
fit10:PING data20 (192.168.2.20) from 192.168.2.10 data: 56(84) bytes of data.
fit10:64 bytes from data20 (192.168.2.20): icmp_seq=1 ttl=64 time=0.460 ms
fit10:
fit10:--- data20 ping statistics ---
fit10:1 packets transmitted, 1 received, 0% packet loss, time 0ms
fit10:rtt min/avg/max/mdev = 0.460/0.460/0.460/0.000 ms

          

Next

In the next example, we will see how to rewrite this example to use nested schedulers, for better modularity.

Objectives

In this section, we will change the D3 script and illustrate a very convenient feature, that allows to create so-called nested schedulers; the idea is to be able to insert a scheduler as a job in a higher-level scheduler. This feature aims in particular at allowing a modular design of schedulers.

In a nutshell, all you need to know is that a Scheduler object can be inserted inside another scheduler, like e.g.:

s_high = Scheduler()
s_high.append(
    Sequence(
        SshJob(...),
        Scheduler(...),  # low-level scheduler
        SshJob()))

Of course in practice, the low-level scheduler is often built separately; for example it could be built by a regular python function.

The other way around, it is also possible to implement a python function that accepts a scheduler in argument, an returns a decorated scheduler that would, for example, check for the lease before running the incoming scheduler.

A more detailed introduction to nested schedulers can be found in the asynciojobs documentation.

So in this example we create a script that behaves exactly like in D3, but using a nested scheduler to provide for more modularity.

The code

Notice:

  • how nested schedulers are rendered graphically, and
  • how the reusable check_lease function decorates experiment_scheduler so as to first check for the lease.
#!/usr/bin/env python3

from argparse import ArgumentParser

from asynciojobs import Scheduler, Sequence

from apssh import SshNode, SshJob
from apssh import Run, RunString

from r2lab import r2lab_hostname, r2lab_data

##########
gateway_hostname  = 'faraday.inria.fr'
gateway_username  = 'inria_r2lab.tutorial'
verbose_ssh = False

parser = ArgumentParser()
parser.add_argument("-s", "--slice", default=gateway_username,
                    help="specify an alternate slicename, default={}"
                         .format(gateway_username))
parser.add_argument("-l", "--load", default=False, action='store_true',
                    help="load the ubuntu image on nodes before starting")
parser.add_argument("-v", "--verbose-ssh", default=False, action='store_true',
                    help="run ssh in verbose mode")
parser.add_argument("-a", "--node-a", default="fit01",
                    help="packets are sent from this node")
parser.add_argument("-b", "--node-b", default="fit02",
                    help="packets are sent to this node")
args = parser.parse_args()

gateway_username = args.slice
verbose_ssh = args.verbose_ssh

##########
faraday = SshNode(hostname = gateway_hostname, username = gateway_username,
                  verbose = verbose_ssh)

# r2lab_hostname will accept inputs like '1', '01', or 'fit01'
hostnamea = r2lab_hostname(args.node_a)
hostnameb = r2lab_hostname(args.node_b)

nodea = SshNode(gateway = faraday, hostname = hostnamea, username = "root",
                verbose = verbose_ssh)
nodeb = SshNode(gateway = faraday, hostname = hostnameb, username = "root",
                verbose = verbose_ssh)

def check_lease(experiment_scheduler, sshnode):

    """
    re-usable function that acts a bit like a python
    decorator on schedulers.

    Given an experiment described as a scheduler, this function
    returns a higher-level scheduler that first checks for the
    lease, and then proceeds with the experiment.
    """

    check_lease_job = SshJob(
        # checking the lease is done on the gateway
        node = faraday,
        # this means that a failure in any of the commands
        # will cause the scheduler to bail out immediately
        critical = True,
        command = Run("rhubarbe leases --check"),
    )

    return Scheduler(
        Sequence(
            check_lease_job,
            # here we create a nested scheduler
            # by inserting the experiment_scheduler
            # as a regular job in the main scheduler
            experiment_scheduler,
        )
    )


##########
# create an orchestration scheduler
scheduler = Scheduler()


# the job to wait before proceeding
ready_requirement = None
# has the user requested to load images ?
# if so, we just need to wait for 2 jobs to complete instead of 1
if args.load:
    ready_requirement = [
        SshJob(
            node = faraday,
            commands = [
                Run('rhubarbe load -i ubuntu', hostnamea, hostnameb),
                Run('rhubarbe wait', hostnamea, hostnameb),
                ],
            scheduler = scheduler,
        ),
        SshJob(
            node = faraday,
            commands = [
                Run('rhubarbe bye -a', '~'+hostnamea, '~'+hostnameb)
            ],
            scheduler = scheduler,
        )
    ]

##########
# setting up the data interface on both fit01 and fit02
init_node_a = SshJob(
    node = nodea,
    command = Run("turn-on-data"),
    required = ready_requirement,
    scheduler = scheduler,
)
init_node_b = SshJob(
    node = nodeb,
    command = Run("turn-on-data"),
    required = ready_requirement,
    scheduler = scheduler,
)

# the name of receiver nodeb, on the data network, is e.g. data02
data_b = r2lab_data(hostnameb)

ping = SshJob(
    node = nodea,
    required = (init_node_a, init_node_b),
    # let's be more specific about what to run
    # we will soon see other things we can do on an ssh connection
    command = Run('ping', '-c1', '-I', 'data', data_b),
    scheduler = scheduler,
)

scheduler = check_lease(scheduler, faraday)

##########
# run the scheduler
ok = scheduler.orchestrate()
# give details if it failed
ok or scheduler.debrief()

# we say this is a success if the ping command succeeded
# the result() of the SshJob is the value that the command
# returns to the OS
# so it's a success if this value is 0
success = ok and ping.result() == 0

# producing a dot file for illustration
scheduler.export_as_dotfile("D4.dot")

# return something useful to your OS
exit(0 if success else 1)

Sample output


faraday.inria.fr:Checking current reservation for inria_r2lab.tutorial : OK
faraday.inria.fr:reboot24:ok
faraday.inria.fr:reboot23:ok
faraday.inria.fr:reboot13:ok
faraday.inria.fr:reboot12:ok
faraday.inria.fr:reboot26:ok
faraday.inria.fr:reboot21:ok
faraday.inria.fr:reboot25:ok
faraday.inria.fr:reboot29:ok
faraday.inria.fr:reboot19:ok
faraday.inria.fr:reboot22:ok
faraday.inria.fr:reboot14:ok
faraday.inria.fr:reboot11:ok
faraday.inria.fr:reboot33:ok
faraday.inria.fr:reboot04:ok
faraday.inria.fr:reboot15:ok
faraday.inria.fr:reboot07:ok
faraday.inria.fr:reboot35:ok
faraday.inria.fr:reboot27:ok
faraday.inria.fr:reboot28:ok
faraday.inria.fr:reboot32:ok
faraday.inria.fr:reboot01:ok
faraday.inria.fr:reboot30:ok
faraday.inria.fr:reboot06:ok
faraday.inria.fr:reboot02:ok
faraday.inria.fr:reboot05:ok
faraday.inria.fr:reboot18:ok
faraday.inria.fr:reboot36:ok
faraday.inria.fr:reboot17:ok
faraday.inria.fr:reboot34:ok
faraday.inria.fr:reboot31:ok
faraday.inria.fr:Found binary frisbeed as /usr/sbin/frisbeed
faraday.inria.fr:reboot16:ok
faraday.inria.fr:Found binary nc as /bin/nc
faraday.inria.fr:reboot03:ok
faraday.inria.fr:reboot37:ok
faraday.inria.fr:reboot08:ok
faraday.inria.fr:reboot09:ok
faraday.inria.fr:12:22:58 - +000s: Selection: fit10 fit20
faraday.inria.fr:12:22:58 - +000s: Loading image /var/lib/rhubarbe-images/ubuntu.ndz
faraday.inria.fr:12:22:58 - +000s: AUTH: checking for a valid lease
faraday.inria.fr:12:22:58 - +000s: AUTH: access granted
faraday.inria.fr:12:22:58 - +000s: fit10 reboot = Sending message 'on' to CMC reboot10
faraday.inria.fr:12:22:58 - +000s: fit20 reboot = Sending message 'on' to CMC reboot20
faraday.inria.fr:reboot33:ok
faraday.inria.fr:reboot32:already off
faraday.inria.fr:reboot27:already off
faraday.inria.fr:reboot19:already off
faraday.inria.fr:reboot31:already off
faraday.inria.fr:reboot04:already off
faraday.inria.fr:reboot37:already off
faraday.inria.fr:reboot26:already off
faraday.inria.fr:reboot06:already off
faraday.inria.fr:reboot25:already off
faraday.inria.fr:reboot21:already off
faraday.inria.fr:reboot18:already off
faraday.inria.fr:reboot22:already off
faraday.inria.fr:reboot36:already off
faraday.inria.fr:reboot11:already off
faraday.inria.fr:reboot12:already off
faraday.inria.fr:reboot03:already off
faraday.inria.fr:reboot34:already off
faraday.inria.fr:reboot29:already off
faraday.inria.fr:reboot02:already off
faraday.inria.fr:reboot16:already off
faraday.inria.fr:reboot24:already off
faraday.inria.fr:reboot15:already off
faraday.inria.fr:reboot28:already off
faraday.inria.fr:reboot14:already off
faraday.inria.fr:reboot35:already off
faraday.inria.fr:reboot05:already off
faraday.inria.fr:reboot08:already off
faraday.inria.fr:reboot09:already off
faraday.inria.fr:reboot13:already off
faraday.inria.fr:reboot17:already off
faraday.inria.fr:12:22:59 - +001s: fit10 reboot = idling for 15s
faraday.inria.fr:12:22:59 - +001s: fit20 reboot = idling for 15s
faraday.inria.fr:reboot01:already off
faraday.inria.fr:reboot30:already off
faraday.inria.fr:reboot07:already off
faraday.inria.fr:reboot23:already off
faraday.inria.fr:ssh -i /home/faraday/r2lab-embedded/mac-ssh-keys/macphone tester@macphone1 phone-off
faraday.inria.fr:Turning OFF phone : turning on airplane mode
faraday.inria.fr:Broadcasting: Intent { act=android.intent.action.AIRPLANE_MODE (has extras) }
faraday.inria.fr:Broadcast completed: result=0
faraday.inria.fr:ssh -i /home/faraday/r2lab-embedded/mac-ssh-keys/macphone tester@macphone2 phone-off
faraday.inria.fr:Turning OFF phone : turning on airplane mode
faraday.inria.fr:Broadcasting: Intent { act=android.intent.action.AIRPLANE_MODE (has extras) }
faraday.inria.fr:Broadcast completed: result=0
faraday.inria.fr:12:23:15 - +017s: started 
faraday.inria.fr:12:23:15 - +017s: fit20 frisbee_status = trying to telnet..
faraday.inria.fr:12:23:15 - +017s: fit10 frisbee_status = trying to telnet..
faraday.inria.fr:12:23:17 - +019s: fit20 frisbee_status = timed out..
faraday.inria.fr:12:23:17 - +019s: fit20 frisbee_status = backing off for 1.7s
faraday.inria.fr:12:23:17 - +019s: fit10 frisbee_status = timed out..
faraday.inria.fr:12:23:17 - +019s: fit10 frisbee_status = backing off for 3.97s
faraday.inria.fr:12:23:19 - +020s: fit20 frisbee_status = trying to telnet..
faraday.inria.fr:12:23:21 - +022s: fit20 frisbee_status = timed out..
faraday.inria.fr:12:23:21 - +022s: fit20 frisbee_status = backing off for 3.93s
faraday.inria.fr:12:23:21 - +023s: fit10 frisbee_status = trying to telnet..
faraday.inria.fr:12:23:23 - +025s: fit10 frisbee_status = timed out..
faraday.inria.fr:12:23:23 - +025s: fit10 frisbee_status = backing off for 3.38s
faraday.inria.fr:12:23:24 - +026s: fit20 frisbee_status = trying to telnet..
faraday.inria.fr:12:23:26 - +028s: fit10 frisbee_status = trying to telnet..
faraday.inria.fr:12:23:26 - +028s: fit20 frisbee_status = timed out..
faraday.inria.fr:12:23:26 - +028s: fit20 frisbee_status = backing off for 1.61s
faraday.inria.fr:12:23:28 - +030s: fit20 frisbee_status = trying to telnet..
faraday.inria.fr:12:23:28 - +030s: fit10 frisbee_status = timed out..
faraday.inria.fr:12:23:28 - +030s: fit10 frisbee_status = backing off for 1.73s
faraday.inria.fr:12:23:30 - +032s: fit10 frisbee_status = trying to telnet..
faraday.inria.fr:12:23:30 - +032s: fit20 frisbee_status = timed out..
faraday.inria.fr:12:23:30 - +032s: fit20 frisbee_status = backing off for 3.07s
faraday.inria.fr:12:23:32 - +034s: fit10 frisbee_status = timed out..
faraday.inria.fr:12:23:32 - +034s: fit10 frisbee_status = backing off for 3.29s
faraday.inria.fr:12:23:33 - +035s: fit20 frisbee_status = trying to telnet..
faraday.inria.fr:12:23:33 - +035s: fit20 frisbee_status = starting frisbee client
faraday.inria.fr:12:23:35 - +037s: fit10 frisbee_status = trying to telnet..
faraday.inria.fr:12:23:35 - +037s: fit10 frisbee_status = starting frisbee client
faraday.inria.fr:12:23:57 - +059s: fit20 Uploading successful
faraday.inria.fr:12:23:57 - +059s: fit20 reboot = Sending message 'reset' to CMC reboot20
faraday.inria.fr:|                                                   |  0% |0.00s|ETA:  --:--:--
|                                                    |  1% |0.59s|ETA:  0:00:38
|##                                                  |  5% |1.65s|ETA:  0:00:28
|####                                                |  8% |2.68s|ETA:  0:00:28
|#####                                               | 11% |2.96s|ETA:  0:00:23
|#######                                             | 14% |3.90s|ETA:  0:00:22
|#########                                           | 17% |4.08s|ETA:  0:00:19
|###########                                         | 21% |4.94s|ETA:  0:00:18
|#############                                       | 25% |5.05s|ETA:  0:00:14
|###############                                     | 29% |6.03s|ETA:  0:00:14
|################                                    | 32% |6.32s|ETA:  0:00:13
|#################                                   | 34% |8.02s|ETA:  0:00:15
|###################                                 | 37% |8.20s|ETA:  0:00:13
|#####################                               | 41% |8.92s|ETA:  0:00:12
|######################                             | 44% |10.65s|ETA:  0:00:13
|########################                           | 48% |11.27s|ETA:  0:00:12
|##########################                         | 51% |11.48s|ETA:  0:00:10
|############################                       | 55% |12.19s|ETA:  0:00:09
|#############################                      | 57% |12.35s|ETA:  0:00:09
|##############################                     | 60% |12.98s|ETA:  0:00:08
|################################                   | 63% |14.32s|ETA:  0:00:08
|#################################                  | 66% |15.41s|ETA:  0:00:07
|###################################                | 69% |16.07s|ETA:  0:00:07
|####################################               | 72% |16.85s|ETA:  0:00:06
|######################################             | 75% |17.23s|ETA:  0:00:05
|#######################################            | 78% |17.44s|ETA:  0:00:04
|#########################################          | 81% |18.30s|ETA:  0:00:04
|###########################################        | 85% |19.05s|ETA:  0:00:03
|############################################       | 87% |21.10s|ETA:  0:00:03
|##############################################     | 91% |21.54s|ETA:  0:00:02
|################################################   | 95% |21.67s|ETA:  0:00:01
|#################################################  | 97% |22.32s|ETA:  0:00:00
|################################################## | 99% |23.10s|ETA:  0:00:00
|###################################################|100% |25.80s|ETA:  0:00:00
|###################################################|100% |25.80s|Time: 0:00:25
faraday.inria.fr:12:23:59 - +061s: fit10 Uploading successful
faraday.inria.fr:12:23:59 - +061s: fit10 reboot = Sending message 'reset' to CMC reboot10
faraday.inria.fr:12:24:01 - +063s: stopped 
faraday.inria.fr::ssh OK
faraday.inria.fr::ssh OK
fit10:turn-on-data: data network on interface data
fit20:turn-on-data: data network on interface data
fit10:data
fit20:data
fit10:PING data20 (192.168.2.20) from 192.168.2.10 data: 56(84) bytes of data.
fit10:64 bytes from data20 (192.168.2.20): icmp_seq=1 ttl=64 time=0.446 ms
fit10:
fit10:--- data20 ping statistics ---
fit10:1 packets transmitted, 1 received, 0% packet loss, time 0ms
fit10:rtt min/avg/max/mdev = 0.446/0.446/0.446/0.000 ms

          

Next

We can now wrap up this D-series.

Summary

You now have a complete toolset at your disposal, and should be able to create nepi-ng scripts for writing a real scale experiment, including features like:

  • setting up nodes from scratch,
  • accounting for any node that the previous experimenter may have forgotten to switch off,
  • passing node numbers on the command-line,
  • and, last but not least, using nested schedulers to write more modular experiments.

Next

Let us move to the next tutorial for some guidelines and troubleshooting tips.