| 1 | = How to integrate your application with nodehandler = |
| 2 | |
| 3 | This tutorial is for users who want to use [wiki:NodeHandler nodeHandler] to launch their applications on the nodes. For example, we assume that you want to launch |
| 4 | {{{ |
| 5 | tcpdump -i eth1 |
| 6 | }}} |
| 7 | on all the nodes in the experiment. |
| 8 | |
| 9 | Three steps are needed |
| 10 | |
| 11 | == Step 1: Create application definition file == |
| 12 | This definition tells the nodehandler about your new application that you want to launch. It mainly includes details such as what are the command line options it takes and what are the statistics it returns. Here is a sample application definition for our above application |
| 13 | |
| 14 | '''Think about this as a class definition for your application''' |
| 15 | * '''Put this file in your home directory as test_app_tcpdump.rb''' |
| 16 | |
| 17 | {{{ |
| 18 | # |
| 19 | # Create an application representation from scratch |
| 20 | # |
| 21 | require 'handler/appDefinition' |
| 22 | |
| 23 | a = AppDefinition.create('test:app:tcpdump') |
| 24 | a.name = "tcpdump" |
| 25 | a.version(0, 0, 1) |
| 26 | a.shortDescription = "Tcpdump application" |
| 27 | a.description = <<TEXT |
| 28 | TCPDump application |
| 29 | TEXT |
| 30 | |
| 31 | # addProperty(name, description, mnemonic, type, isDynamic = false, constraints = nil) |
| 32 | |
| 33 | #Here ?i means tcpdump will be launched with -i <interface> option |
| 34 | a.addProperty('interface', 'Interface to run on', ?i, String, false) |
| 35 | |
| 36 | a.path = "/usr/sbin/tcpdump" |
| 37 | |
| 38 | if $0 == __FILE__ |
| 39 | require 'stringio' |
| 40 | require 'rexml/document' |
| 41 | include REXML |
| 42 | |
| 43 | sio = StringIO.new() |
| 44 | a.to_xml.write(sio, 2) |
| 45 | sio.rewind |
| 46 | puts sio.read |
| 47 | |
| 48 | sio.rewind |
| 49 | doc = Document.new(sio) |
| 50 | t = AppDefinition.from_xml(doc.root) |
| 51 | |
| 52 | puts |
| 53 | puts "-------------------------" |
| 54 | puts |
| 55 | t.to_xml.write($stdout, 2) |
| 56 | |
| 57 | end |
| 58 | |
| 59 | }}} |
| 60 | |
| 61 | |
| 62 | == Step 2: Prototype definition == |
| 63 | After informing nodeHandler about our new application, we then need to create a prototype using our application definition. |
| 64 | |
| 65 | '''Think about this as an instance of your above class''' |
| 66 | * '''Put this file in your home directory as test_proto_tcpdumper.rb''' |
| 67 | {{{ |
| 68 | # |
| 69 | # Define a prototype |
| 70 | # |
| 71 | |
| 72 | require 'handler/prototype' |
| 73 | require 'handler/filter' |
| 74 | require 'handler/appDefinition' |
| 75 | |
| 76 | p = Prototype.create("test:proto:tcpdumper") |
| 77 | p.name = "TCPdump proto" |
| 78 | p.description = "TCPdump" |
| 79 | p.defProperty('interface', 'Interface to listen on') |
| 80 | |
| 81 | |
| 82 | tcpd = p.addApplication('aodvd', "test:app:tcpdump") |
| 83 | tcpd.bindProperty('interface') |
| 84 | |
| 85 | |
| 86 | |
| 87 | if $0 == __FILE__ |
| 88 | p.to_xml.write($stdout, 2) |
| 89 | puts |
| 90 | end |
| 91 | |
| 92 | }}} |
| 93 | |
| 94 | == Step 3: Using this prototype in an actual script == |
| 95 | |
| 96 | The following example script uses our newly defined application definition. |
| 97 | {{{ |
| 98 | ################################################## |
| 99 | # TCPDump using nodeHandler |
| 100 | ################################################## |
| 101 | |
| 102 | Experiment.name = "tutorial-tcpdump" |
| 103 | Experiment.project = "orbit:tutorial" |
| 104 | |
| 105 | # |
| 106 | # Define nodes used in experiment |
| 107 | # |
| 108 | defNodes('nodes', [[1,1],[1,2]]) {|node| |
| 109 | node.image = nil # assume the right image to be on disk |
| 110 | |
| 111 | node.prototype("test:proto:tcpdumper", { |
| 112 | 'interface' => 'eth1' #This is where we assign the interface for this specific instance |
| 113 | }) |
| 114 | node.net.w0.mode = "master" |
| 115 | } |
| 116 | |
| 117 | |
| 118 | allNodes.net.w0 { |w| |
| 119 | w.type = 'b' |
| 120 | w.essid = "helloworld" |
| 121 | w.ip = "%192.168.%x.%y" |
| 122 | } |
| 123 | |
| 124 | # |
| 125 | # Now, start the application |
| 126 | # |
| 127 | whenAllInstalled() {|node| |
| 128 | # Launch TCPdump on all nodes |
| 129 | |
| 130 | #startApplications will launch all the applications defined for the group "nodes" |
| 131 | NodeSet['nodes'].startApplications |
| 132 | |
| 133 | |
| 134 | |
| 135 | wait 180 |
| 136 | |
| 137 | Experiment.done |
| 138 | } |
| 139 | |
| 140 | }}} |