= Example to Plot LabWiki Graph from a CSV File = == 1. On InstaGENI, use the following image which has the latest GIMI and other Tools installed: == {{{ Image URN: urn:publicid:IDN+instageni.illinois.edu+image+ch-geni-net:gimidev2 Image URL: https://www.instageni.illinois.edu/image_metadata.php?uuid=df9ce62b-ec1a-11e3-bc1a-000000000000 }}} For more details on what is installed in these images, go to [http://groups.geni.net/geni/wiki/GIMIv3/Documentation#Images GIMI Images] == 2. Identify Measurement Points in CSV file == For this example, the CSV File used is attached here (wimaxss.csv) Each of the fields has been taken as a separate measurement point for this example. {{{ "1401394008","6C:F3:73:99:FA:1E","samsung","SPH-D710","Android","EVDO Rev 0","Sprint","99.207.13.249",-96,,"-82.8344","34.676","23.517" "1401393251","f8:a9:d0:66:7d:78","LGE","LG-D801","Android","Wifi",,"198.21.252.5",-81,"eduroam","-82.8344","34.676","25.854" "1401392753","6C:F3:73:99:FA:1E","samsung","SPH-D710","Android","EVDO Rev 0","Sprint","99.207.13.249",-96,,"-82.8344","34.676","17.06" "1401392748","6C:F3:73:99:FA:1E","samsung","SPH-D710","Android","EVDO Rev 0","Sprint","99.207.13.249",-96,,"-82.8344","34.676","24.803" "1401392619","6C:F3:73:99:FA:1E","samsung","SPH-D710","Android","EVDO Rev 0","Sprint","99.207.13.249",-101,,"-82.8344","34.676","20" "1401392598","6C:F3:73:99:FA:1E","samsung","SPH-D710","Android","EVDO Rev 0","Sprint","99.207.13.249",-96,,"-82.8344","34.676","21.088" }}} The fields in order: {{{ a) testTime: Timestamp of when the test was initiated in unix timestamp : We use this to uniquely identify the devices. It is the MAC address of the Wifi interface of a device. b) make: Device manufacturer c) model: Device model d) platform: Operating system e) networkType: Radio access technology f) networkOperator: Cell network operator (null for Wifi tests) g) ipAddress: IP that the server saw during the test h) signalDbm: signal dBm as reported by the device's radio i) ssid: SSID of the wifi network used (null for cell tests) j) longitude: longitude of current location k) latitude: latitude of current location l) geolocationAccuracy: precision of location data in meters m) methodName: whether a hardware GPS fix was used, or network-based geolocation (nearby wifi networks, cell triangulation) }}} == 3. Write OML4R application Script and save it on VM == === 3.1 Define a class of measurement point variables === This is based on the number and type of the fields in the CSV file {{{ class MPThroughput < OML4R::MPBase name :wimaxss param :unixts, :type => :string param :ifacemac, :type => :string param :make, :type => :string param :model, :type => :string param :platform, :type => :string param :nettype, :type => :string param :netoper, :type => :string param :ipaddr, :type => :string param :ssid, :type => :int64 param :longi, :type => :string param :lat, :type => :string param :geoLoc, :type => :string param :metName, :type => :string end }}} === 3.2 Parse measurement fields === {{{ def processOutput(output) column = output.split(",") puts "Each line process" # Inject the measurements into OML puts Integer(column[8]) MPThroughput.inject("#{column[0]}", "#{column[1]}", "#{column[2]}", "#{column[3]}", "#{column[4]}", "#{column[5]}", "#{column[6]}", "#{column[7]}", "#{column[8]}".to_i, "#{column[9]}", "#{column[10]}", "#{column[11]}", "#{column[12]}") end end }}} === Specify number of lines to read === The log.backward() function specifies the number of lines to read while doing a file tail. In this example, it reads only 1 line from the file's history. {{{ def start() log = MyFile.new("#{@addr}") log.interval = @if_num log.backward(1) puts "#{@if_num}" log.tail { |line| print line processOutput(line) } end }}} === 3.4 The complete script is given below === {{{ #!/usr/local/bin/ruby # # This file was generated by RubyGems. # # The application 'oml4r' is installed as part of a gem, and # this file is here to facilitate running it. # require 'rubygems' require 'oml4r' require 'file-tail' APPNAME = "ofstats" class MPThroughput < OML4R::MPBase name :wimaxss param :unixts, :type => :string param :ifacemac, :type => :string param :make, :type => :string param :model, :type => :string param :platform, :type => :string param :nettype, :type => :string param :netoper, :type => :string param :ipaddr, :type => :string param :ssid, :type => :int64 param :longi, :type => :string param :lat, :type => :string param :geoLoc, :type => :string param :metName, :type => :string end class OFStatsWrapper def initialize(args) @addr = nil @if_num = ' ' @trema_port = ' ' @trema_path = ' ' @verbose = true @numeric = ' ' OML4R::init(args, :appName => "#{APPNAME}_wrapper", :domain => 'foo', :collect => 'file:-') { |argParser| argParser.banner = "Reports OpenFlow stat measurements via OML\n\n" argParser.on("-f" , "--file_path ADDRESS", "Path where output is saved"){ |address| @addr = address } argParser.on("-i","--interface IFNUM","Interface number"){ |if_num| @if_num ="#{if_num.to_i()}" } argParser.on("-q", "--no-quiet ","Don't show of stats output on console"){ @verbose = false } argParser.on("-n", "--[no]-numeric ", "No attempt twill be made to look up symbolic names for host addresses"){ @numeric ='-n' } } unless @addr !=nil raise "You did not specify path of file (-p option)" end end class MyFile < File include File::Tail end def start() log = MyFile.new("#{@addr}") log.interval = @if_num log.backward(1) puts "#{@if_num}" log.tail { |line| print line processOutput(line) } end def processOutput(output) column = output.split(",") puts "Each line process" # Inject the measurements into OML puts Integer(column[8]) MPThroughput.inject("#{column[0]}", "#{column[1]}", "#{column[2]}", "#{column[3]}", "#{column[4]}", "#{column[5]}", "#{column[6]}", "#{column[7]}", "#{column[8]}".to_i, "#{column[9]}", "#{column[10]}", "#{column[11]}", "#{column[12]}") end end begin app = OFStatsWrapper.new(ARGV) app.start() rescue SystemExit rescue SignalException puts "OFWrapper stopped." rescue Exception => ex puts "Error - When executing the wrapper application!" puts "Error - Type: #{ex.class}" puts "Error - Message: #{ex}\n\n" # Uncomment the next line to get more info on errors # puts "Trace - #{ex.backtrace.join("\n\t")}" end OML4R::close() # Local Variables: # mode:ruby # End: # vim: ft=ruby:sw=2 }}} == 4. Write OEDL Script to Run application == === 4.1 Specify location of CSV file on VM === {{{ defProperty('pathfile', "/root/wimaxtest.txt", "Path to file") }}} === 4.2 Define OML Application with path on VM === {{{ defApplication('ofstats') do |app| app.description = 'Simple Definition for the of-collect application' # Define the path to the binary executable for this application app.binary_path = '/usr/local/bin/ofcollect.rb' app.defProperty('target', 'Address to output file', '-f', {:type => :string}) app.defProperty("interval","Interval",'-i', {:type => :string}) app.defMeasurement('wrapper_wimaxss') do |m| m.defMetric(':pathtype', :string) m.defMetric('throughput',:int64) m.defMetric('instput',:int64) end end }}} === 4.3 Create Node Group with Application === {{{ defGroup('Source1', property.source1) do |node| node.addApplication("ofstats") do |app| app.setProperty('target', property.pathfile) app.setProperty('interval', property.intervalcol) app.measure('wrapper_wimaxss', :samples => 1) end end }}} === 4.4 Define parameters for Graph === Line Graph {{{ defGraph 'SSID' do |g| g.ms('wrapper_wimaxss').select(:oml_ts_client, :ssid, :ifacemac) g.caption "SSID" g.type 'line_chart3' g.mapping :x_axis => :oml_ts_client, :y_axis => :ssid, :group_by => :ifacemac g.xaxis :legend => 'unix_ts' g.yaxis :legend => 'SSID', :ticks => {:format => 's'} end }}} HistoGram {{{ defGraph 'SSID' do |g| g.ms('wrapper_wimaxss').select(:oml_ts_client, :ssid, :netoper) g.caption "SSID of Carriers" g.type 'histogram2' g.mapping :value => :ssid, :group_by => :netoper g.xaxis :legend => 'Unix TS' g.yaxis :legend => 'SSID' end }}} === 4.5 Full Script is given below === {{{ defProperty('source1', "nodec-gimidev1", "ID of a resource") defProperty('intervalcol',"1", "Interval to Tail") defProperty('pathfile', "/root/wimaxtest.txt", "Path to file") defApplication('ofstats') do |app| app.description = 'Simple Definition for the of-collect application' # Define the path to the binary executable for this application app.binary_path = '/usr/local/bin/ofcollect.rb' app.defProperty('target', 'Address to output file', '-f', {:type => :string}) app.defProperty("interval","Interval",'-i', {:type => :string}) app.defMeasurement('wrapper_wimaxss') do |m| m.defMetric(':pathtype', :string) m.defMetric('throughput',:int64) m.defMetric('instput',:int64) end end defGroup('Source1', property.source1) do |node| node.addApplication("ofstats") do |app| app.setProperty('target', property.pathfile) app.setProperty('interval', property.intervalcol) app.measure('wrapper_wimaxss', :samples => 1) end end onEvent(:ALL_UP_AND_INSTALLED) do |event| info "Starting the collect" after 2 do group('Source1').startApplications end after 800 do info "Stopping the collect" allGroups.stopApplications Experiment.done end end defGraph 'SSID' do |g| g.ms('wrapper_wimaxss').select(:oml_ts_client, :ssid, :ifacemac) g.caption "SSID" g.type 'line_chart3' g.mapping :x_axis => :oml_ts_client, :y_axis => :ssid, :group_by => :ifacemac g.xaxis :legend => 'unix_ts' g.yaxis :legend => 'SSID', :ticks => {:format => 's'} end defGraph 'SSID' do |g| g.ms('wrapper_wimaxss').select(:oml_ts_client, :ssid, :netoper) g.caption "SSID of Carriers" g.type 'histogram2' g.mapping :value => :ssid, :group_by => :netoper g.xaxis :legend => 'Unix TS' g.yaxis :legend => 'SSID' end }}}