Version 24 (modified by, 6 years ago) (diff)


Get to Know the GENI Experiment Engine

Hello GENI index Hello GENI index Hello GENI index


Your goal in this tutorial is to fetch a parameterized URL on each node of your slicelet:<slice name>&name=<container name>&ip=<IP of host>&local=<IP of container>&lat=<latitude of host>&lng=<longitude of container>

This page will log each of your queries, and you can check that all your nodes were successfully able to run the query.

We will work up to this goal through hands-on learning with Ansible.

1. Experiment with various Ansible modules: ping, shell, setup

We will first get familiar with some basic Ansible tasks using the command-line interface.

(a) The ping module

The ping module simply tries to do a SSH login to a node and reports success or failure. Run the following command on your controller:

$ ansible nodes -i ansible-hosts -m ping

If you don’t see success everywhere then there is something wrong with your setup. Ask one of the tutorial leaders for help. Note that you will be prompted to accept each node as you log into it; this happens only once per node, the first time you log in.

(b) The shell module

The shell module lets you run arbitrary SSH commands in parallel across a set of hosts. It’s useful for poking around, or if there is no Ansible module with the functionality you need. Try it out:

$ ansible nodes -i ansible-hosts -m shell -a "hostname"

You can replace hostname above with any other Linux command.

(c) The setup module

The setup module gathers a bunch of information about each node and saves it in variables that you can reference in your Ansible playbooks. This will be really useful to do the tutorial! Try it out on a node to see what it collects (replace <your-slicelet> with your slicelet’s name):

$ ansible <your-slicelet> -i ansible-hosts -m setup

2. Create an Ansible playbook to download a parameterized URL from each node

(a) Create a starter Ansible playbook

A playbook is a YAML file containing a list of Ansible tasks. To get started creating your Ansible playbook, copy the following into a file called test.yaml:

- hosts: nodes
  remote_user: root
  - name: An example of a debug statement
    debug: var=ansible_hostname

Run the playbook as:

$ ansible-playbook -i ansible-hosts test.yaml

The setup module is run automatically at the beginning of a playbook to populate variables for each node. The above playbook will dump the value of each node’s ansible_hostname variable. To run the playbook on a single node, replace nodes with the name of one of your slice nodes (e.g.,

Now, think about how you are going to solve the problems of this tutorial. You need to collect several pieces of information on each node: the container name, the IP of the host (i.e., the VM hosting the container), the IP of the container, and the latitude and longitude of the host. You then need to fetch a custom URL containing this information from each host.

Pro Tip: Solve the problem on one node in your slice first, then deploy your solution to the remaining nodes. One thing at a time.
Pro Tip: Build your solution a piece at a time. Each step is, basically: (1) run a command, (2) possibly extract the information from the output and register it in an Ansible variable
Pro Tip: Starting an task in an Ansible playbook with "- name:", as in the example above, prints out the string following name at the beginning of the task. This is useful for keeping track of where you are in a playbook run.

Here is an Ansible playbook skeleton that you can use to complete the tutorial.

- hosts: nodes
  remote_user: root
  - name: Update apt cache
    shell: apt-get update

  - name: Install python-apt (to work around an Ansible bug)
    shell: apt-get -y install python-apt

  - name: 2(a): Dump container FQDN

  - name: 2(b): Dump container IP address

  - name: 2(c): Dump control host name

  - name: 2(d): Install dnsutils (for dig)

  - name: 2(d): Get my public IP using 'dig +short'
    register: public_ip

  - name: 2(d): Dump public_ip variable
    debug: var=public_ip

  - name: 2(e): Install geoip-bin (for geoiplookup)

  - name: 2(e): Download GeoLiteCity DB

  - name: 2(e): Unzip GeoLiteCity.dat.gz
    shell: gunzip -f GeoLiteCity.dat.gz

  - name: 2(e): Run geoiplookup to get latitude
    register: lat

  - name: 2(e): Dump lat variable
    debug: var=lat

  - name: 2(e): Run geoiplookup to get longitude
    register: long

  - name: 2(e): Dump long variable
    debug: var=long

  - name: Dump the full URL 
  - debug: msg=" INSERT ARGUMENTS HERE"

  - shell: curl " INSERT ARGUMENTS HERE"

(b) Get the container's FQDN

Look at the variables collected by Ansible's setup module (step 1(c) above). Find one that holds the container's fully-qualified domain name (e.g.,

(c) Get the container IP address

Look at the variables collected by Ansible's setup module (step 1(c) above). Find one that holds the container IP address. Add a debug task to your playbook, like the one in the starter playbook, to print out its value. Complete the following task and add it to your playbook

   - name: Print container IP address
     debug: var=

(d) Get the host's public IP address

This is a bit trickier: how to get the host's IP address? The IP address visible inside the slicelet (as reported in the variable ansible_eth0.ipv4.address) is a private address -- it is not the control address of the host. There are a number of ways that you could discover the control address, including running dig +short on the host’s name (see if you can find a variable that contains the host's name; HINT: you need it to SSH into the slicelet) or by running curl against a webserver that reports the client’s externally visible address.

Pro Tip: The ansible command-line tool is a good way to try out Ansible tasks before putting them in your playbook. Look at the examples in part 1 above.
Pro Tip: Usually in an Ansible playbook you reference a variable by surrounding it in double curly brackets: {{ ansible_eth0.ipv4.address }}. You can see examples of how variables are referenced in tasks in this playbook.
Pro Tip: When you run an Ansible command in a playbook, you can save the output into a new variable using register: varname Then you can retrieve the value later in the playbook using {{ varname }} or, for shell command output, {{ varname.stdout }}. You can see an example of how to register a variable in this playbook.

(e) Get the latitude and longitude for each node

Another requirement of the lab is to map the host's control IP address obtained in the previous step to the latitude and longitude for each node. One way to do this is to use the geoiplookup tool, provided by package geoip-bin.

$ geoiplookup -f <data file> <ip address>

where <data file> is the database of IP addresses and locations. You can find a good one at:, which you’ll have to download to each node and unzip.

A different approach would be to run curl against a webserver that maps IP address to latitude and longitude, such as, and parse the output. NOTE: this particular website rate-limits the number of requests per node per day, so if you use it, make only a single request per node and save the result in a file… keep in mind that everyone in the tutorial may be hitting this server from the same set of hosts!

Pro Tip: The Ansible script module can be used to run arbitrary scripts in your slicelet. See:
Pro Tip: Not all the resources you may need are installed on the nodes! The apt Ansible module is useful for installing packages; see:

At this point, you should have enough information to flesh out the base Ansible playbook. No need to hurry. Do each step, one at a time, and use the debug module to print out variable values after each step. This will help you get something working very quickly.

3. Run the playbook

Once you have finished your playbook, run it against all the nodes!

As a data point, our Ansible playbook contained six commands (not including debug commands) and used the apt, shell, and get_url modules.

4. Verify that your playbook worked as expected

Once you have completed the tutorial, you can check where you’ve said hello from at:<your slice>

You should see an entry for each node in your slicelet.

Next: Teardown Experiment

Attachments (2)

Download all attachments as: .zip