= [wiki:GENIExperimenter/Tutorials/GENI-SAVI Get to Know GENI and SAVI] = {{{ #!html
Hello GENI index Hello GENI index Hello GENI index
}}} ---- = STEPS FOR EXECUTING EXERCISE = ---- '''Your goal in this tutorial is to fetch a parameterized URL on each node in your experiment:''' '''!http://www.lively-web.org/nodejs/GEETutorial/helloWorld?slice=&name=&ip=&lat=&lng=''' '''This page will log each of your queries, and you can check that all your nodes were successfully able to run the query.''' You will use Ansible to do this. == 1. Create an Ansible playbook to download a parameterized URL from each node == To determine the parameters in the above url, 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. Three of these (the slice name, container name, and local IP) can be found from Ansible variables. Running a {{{setup}}} command, as on the previous page, will show you the Ansible variables. Note that {{{setup}}} is run automatically by Ansible, so when executing a playbook on a node that information is available. Look through the output from {{{setup}}}, and you can identify the variables you'll need. You then need to fetch a custom URL containing this information from each host. {{{ #!div style="background: #E6D8F0; border: 3px ridge; width: 800px;" The [attachment:gee-tutorial.yaml Ansible playbook] that you will need is: {{{ --- - hosts: nodes sudo: yes remote_user: "{{ ansible_ssh_user }}" tasks: ### (a): Get the container's FQDN ### - name: Dump container name debug: var=ansible_fqdn ### (b): Get the container IP address ### - name: Dump container IP address debug: var=ansible_eth0.ipv4.address ### (c): Get the control host name ### - name: Dump control host name debug: var=ansible_ssh_host ### (d): Get the host's public IP address ### - name: Get my public IP ###shell: dig +short {{ ansible_hostname }} shell: curl ipecho.net/plain register: public_ip - name: Dump public_ip variable debug: var=public_ip - name: Run geoiplookup to get latitude #shell: geoiplookup -f GeoLiteCity.dat {{ public_ip.stdout }} | awk -F ', ' '{print $7}' shell: curl -s ipinfo.io | grep loc | sed "s/^.*loc..// " | sed "s/..$//" | sed "s/^.*\"//" | sed "s/,.*$//" register: lat - name: Dump lat variable debug: var=lat - name: Run geoiplookup to get longitude # shell: geoiplookup -f GeoLiteCity.dat {{ public_ip.stdout }} | awk -F ', ' '{print $8}' shell: curl -s ipinfo.io | grep loc | sed "s/^.*loc..// " | sed "s/..$//" | sed "s/^.*,//" register: long - name: Dump long variable debug: var=long ### (f): Fetch the parameterized URL ### - shell: curl "http://www.lively-web.org/nodejs/GEETutorial/helloWorld?slice=&name={{ansible_fqdn}}&ip={{public_ip.stdout }}&local={{ansible_eth0.ipv4.address}}&lat={{lat.stdout}}&lng={{long.stdout}}" register: hello - debug: var=hello }}} }}} {{{ #!div style="background: #ffd; border: 3px ridge; width: 800px;" To download this playbook to your client machine: {{{ wget http://groups.geni.net/geni/raw-attachment/wiki/GENIExperimenter/Tutorials/GENI-SAVI/Execute/gee-tutorial-solution.yaml }}} '''Before you run this playbook, replace at the end of the script (the last curl command) with your GENI username''' }}} {{{ #!comment The following subsections provide further guidance on how to complete each step. === (a) Get the control host name === Look at the variables collected by Ansible's '''setup''' module. Find one that holds the control host's FQDN (HINT: it begins with ''pcvm'') and dump it using a '''debug''' task. You'll need this for the next step. === (b) Get the host's public IP address === The IP address visible inside the node (as reported in the variable ''ansible_eth0.ipv4.address'') is a private address -- it is not the control address of the host. To discover the ''public'' IP address of the node, run '''dig +short '''. || [[Image(wiki:GENIExperimenter/Tutorials/Graphics:tip.png, nolink, 50px, bottom)]] || '''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. || || [[Image(wiki:GENIExperimenter/Tutorials/Graphics:tip.png, nolink, 50px, bottom)]] || '''Pro Tip:''' Running a playbook on all the nodes can take a fair amount of time, and this can lengthen the debug cycle. Pick one or two nodes to be {{{debug_nodes}}}, then go to the {{{ansible-hosts}}} inventory file and add the lines {{{ #!python [debug_nodes] .pcvm3-1.geni.case.edu ansible_ssh_host=pcvm3-1.geni.case.edu ansible_ssh_port=49153 .pcvm2-2.instageni.rnoc.gatech.edu ansible_ssh_host=pcvm2-2.instageni.rnoc.gatech.edu ansible_ssh_port=49153 }}} to the top. Then, first run every playbook on {{{debug_nodes}}} for your tests. || || [[Image(wiki:GENIExperimenter/Tutorials/Graphics:tip.png, nolink, 50px, bottom)]] || '''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 [https://github.com/ansible/ansible-examples/blob/master/language_features/get_url.yml this playbook]. || || [[Image(wiki:GENIExperimenter/Tutorials/Graphics:tip.png, nolink, 50px, bottom)]] || '''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 [https://github.com/ansible/ansible-examples/blob/master/language_features/register_logic.yml this playbook]. || === (c) Get the latitude and longitude for each node === To map the host's control IP address obtained in the previous step to the latitude and longitude for each node, use the '''geoiplookup''' tool, provided by package '''geoip-bin'''. {{{ $ geoiplookup -f }}} where '''' is the database of IP addresses and locations. You can find a good one at: http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz, which you’ll have to download to each node and unzip. Note that '''geoiolookup''' returns a bunch of comma-separated fields. The latitude and longitude are in fields 7 and 8. You'll need to extract these -- perhaps by piping the output of '''geoiplookup''' into '''awk'''. || [[Image(wiki:GENIExperimenter/Tutorials/Graphics:tip.png, nolink, 50px, bottom)]] || '''Pro Tip:''' You can also use the Ansible '''script''' module to run arbitrary scripts in your slicelet, if that helps. See: http://docs.ansible.com/script_module.html || === (d) Fetch the parameterized URL === At this point, you should have enough information to fetch the parameterized URL in the playbook. You should first use a '''debug''' task to print out the URL to make sure that it's formatted correctly. || [[Image(wiki:GENIExperimenter/Tutorials/Graphics:tip.png, nolink, 50px, bottom)]] || '''Pro Tip:''' Solve the problem on one node in your slice first, then deploy your solution to the remaining nodes. || || [[Image(wiki:GENIExperimenter/Tutorials/Graphics:tip.png, nolink, 50px, bottom)]] || '''Pro Tip:''' Build your solution a piece at a time. Get each step working before continuing to the next step. || ---- }}} == 2. Run the playbook == Once you have finished with Step 1, run your playbook against all the nodes in your slice! {{{ #!div style="background: #ffd; border: 3px ridge; width: 800px;" {{{ ansible-playbook -i ansible-hosts gee-tutorial-solution.yaml }}} }}} ---- == 3. Verify that your playbook worked as expected == Once you have completed the tutorial, you can check where you’ve said hello from at: http://lively-web.org/users/rick/GEETutorialMap.html Choose your slice name from the drop-down and you should see pins in the map at the coordinates reported by the nodes! ---- = [wiki:GENIExperimenter/Tutorials/GENI-SAVI/Finish Next: Teardown Experiment] =