omf_ec 6.0.0.pre.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +4 -0
  3. data/Rakefile +7 -0
  4. data/bin/omf_test +161 -0
  5. data/config/ec.yml +164 -0
  6. data/exp_repo/system/exp/eventlib.rb +96 -0
  7. data/exp_repo/system/exp/imageNode.rb +283 -0
  8. data/exp_repo/system/exp/reset.rb +21 -0
  9. data/exp_repo/system/exp/saveNode.rb +99 -0
  10. data/exp_repo/system/exp/stat.rb +49 -0
  11. data/exp_repo/system/exp/stdlib.rb +122 -0
  12. data/exp_repo/system/exp/tell.rb +53 -0
  13. data/exp_repo/system/exp/testlib.rb +12 -0
  14. data/exp_repo/system/exp/winlib.rb +154 -0
  15. data/exp_repo/system/topo/active.rb +9 -0
  16. data/exp_repo/system/topo/all.rb +10 -0
  17. data/exp_repo/system/topo/circle.rb +23 -0
  18. data/exp_repo/test/app/aodvd.rb +73 -0
  19. data/exp_repo/test/app/appDef1.rb +102 -0
  20. data/exp_repo/test/app/athstats.rb +76 -0
  21. data/exp_repo/test/app/echo.rb +36 -0
  22. data/exp_repo/test/app/gennyReceiverAppDef.rb +100 -0
  23. data/exp_repo/test/app/gennySenderAppDef.rb +106 -0
  24. data/exp_repo/test/app/itgdec.rb +79 -0
  25. data/exp_repo/test/app/itgr.rb +77 -0
  26. data/exp_repo/test/app/itgs.rb +105 -0
  27. data/exp_repo/test/app/nop.rb +36 -0
  28. data/exp_repo/test/app/otg2.rb +68 -0
  29. data/exp_repo/test/app/otg2_mp.rb +56 -0
  30. data/exp_repo/test/app/otr2.rb +56 -0
  31. data/exp_repo/test/app/otr2_mp.rb +51 -0
  32. data/exp_repo/test/app/trace_oml2.rb +62 -0
  33. data/exp_repo/test/app/wlanconfig_oml2.rb +42 -0
  34. data/exp_repo/test/exp/conf-room-demo.rb +118 -0
  35. data/exp_repo/test/exp/planetlab.rb +82 -0
  36. data/exp_repo/test/exp/test01.rb +42 -0
  37. data/exp_repo/test/exp/test02.rb +60 -0
  38. data/exp_repo/test/exp/test03.rb +95 -0
  39. data/exp_repo/test/exp/test04.rb +105 -0
  40. data/exp_repo/test/exp/test05.rb +87 -0
  41. data/exp_repo/test/exp/test06.rb +71 -0
  42. data/exp_repo/test/exp/tutorial/hello-world-wired.rb +79 -0
  43. data/exp_repo/test/exp/tutorial/hello-world-wireless.rb +87 -0
  44. data/exp_repo/test/exp/tutorial/using-filters.rb +69 -0
  45. data/exp_repo/test/exp/tutorial/using-groups.rb +64 -0
  46. data/exp_repo/test/exp/tutorial/using-properties.rb +93 -0
  47. data/exp_repo/test/exp/tutorial/using-prototypes.rb +111 -0
  48. data/exp_repo/test/proto/aodvrouter.rb +55 -0
  49. data/exp_repo/test/proto/driverqueryapp.rb +59 -0
  50. data/exp_repo/test/proto/forwarder.rb +73 -0
  51. data/exp_repo/test/proto/itgcbrsender.rb +70 -0
  52. data/exp_repo/test/proto/itgdecoder.rb +64 -0
  53. data/exp_repo/test/proto/itgreceiver.rb +55 -0
  54. data/exp_repo/test/proto/itgvoipsender.rb +64 -0
  55. data/exp_repo/test/proto/listener2.rb +62 -0
  56. data/exp_repo/test/proto/nop.rb +47 -0
  57. data/exp_repo/test/proto/probelink.rb +48 -0
  58. data/exp_repo/test/proto/raw_receiver.rb +64 -0
  59. data/exp_repo/test/proto/receiver2_mp.rb +48 -0
  60. data/exp_repo/test/proto/sender2_mp.rb +54 -0
  61. data/exp_repo/test/proto/udp_receiver.rb +55 -0
  62. data/exp_repo/test/proto/udp_sender.rb +61 -0
  63. data/lib/omf_ec/version.rb +3 -0
  64. data/lib/omf_ec.rb +5 -0
  65. data/omf_ec.gemspec +24 -0
  66. metadata +145 -0
@@ -0,0 +1,283 @@
1
+ #
2
+ # Copyright (c) 2006-2008 National ICT Australia (NICTA), Australia
3
+ #
4
+ # Copyright (c) 2004-2008 WINLAB, Rutgers University, USA
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #
24
+ #
25
+ # = imageNode.rb
26
+ #
27
+ # == Description
28
+ #
29
+ # This file describes the Experiment that is used to image the nodes within OMF.
30
+ # (In OMF, loading a disk image on a node is treated as an 'experiment' itself)
31
+ #
32
+
33
+ # Define the experiment properties
34
+ Experiment.name = "imageNode"
35
+ Experiment.project = "Orbit::Admin"
36
+ defProperty('nodes', 'system:topo:all', "Nodes to image")
37
+ defProperty('image', 'baseline.ndz', "Image to load on nodes")
38
+ defProperty('domain', "#{OConfig.domain}", "Domain of the nodes to image")
39
+ defProperty('outpath', "/tmp", "Path where to place the topology files resulting from this image")
40
+ defProperty('outprefix', "#{Experiment.ID}", "Prefix to use for the topology files resulting from this image")
41
+ # The following value of 1200sec for timeout is based on trial imaging experiments
42
+ defProperty('timeout', 1200, "Stop the imaging process <timeout> sec after the last node has powered up")
43
+
44
+ # Define some constants
45
+ MSG_CHECKINFAILED = <<TEXT
46
+ # This creates a Topology with the resources which did not check in to the load experiment.
47
+ # These nodes may have failed to boot into the PXE image or start the RC from within.
48
+ #
49
+ TEXT
50
+ MSG_IMAGEFAILED = <<TEXT
51
+ # This creates a Topology with the resources for which the image loading failed.
52
+ # On these resources, the 'frisbee' client may have raised an error during its execution.
53
+ # Please check the EC log file for the 'frisbee' client error message.
54
+ #
55
+ TEXT
56
+ MSG_TIMEOUT = <<TEXT
57
+ # This creates a Topology with the resources for which the image loading timed out.
58
+ # These nodes did not finish imaging before the timeout limit.
59
+ # Most of the time this is caused by some disk or network problems.
60
+ #
61
+ TEXT
62
+ MSG_SUCCESS = <<TEXT
63
+ # This creates a Topology with the resources which have successfully been imaged.
64
+ #
65
+ TEXT
66
+ MESSAGES = {:checkinfailed => MSG_CHECKINFAILED, :imagefailed => MSG_IMAGEFAILED, :timeout => MSG_TIMEOUT, :success => MSG_SUCCESS}
67
+
68
+
69
+ #
70
+ # First of all, do some checks...
71
+ # - check if the requested image really exists on the Repository
72
+ #
73
+ #url = "#{OConfig[:ec_config][:frisbee][:url]}/checkImage?img=#{prop.image.value}&domain=#{prop.domain.value}"
74
+ #response = NodeHandler.service_call(url, "Image does not exist")
75
+ response = OMF::Services.frisbee.checkImage(:img => "#{prop.image.value}", :domain => "#{prop.domain.value}")
76
+ if response.elements[1].name != "OK"
77
+ MObject.error("Frisbee Service Call", response.root.text)
78
+ Experiment.done
79
+ exit
80
+ end
81
+ # - check if timeout value from command line is really an integer
82
+ if (prop.timeout.value.to_i == 0)
83
+ MObject.error("The timeout value '#{prop.timeout.value}' is not an integer!")
84
+ MObject.error("Check command line syntax.")
85
+ Experiment.done
86
+ exit -1
87
+ end
88
+
89
+ @allNodes = []
90
+
91
+ #
92
+ # Define the group of node to image and set them into PXE boot
93
+ #
94
+ defGroup('image', prop.nodes) {|ns|
95
+ ns.image = "pxe-5.4"
96
+ ns.each { |n| @allNodes << n }
97
+ }
98
+
99
+ OMF::Services.pxe.setBootImageNS(:ns => "#{@allNodes.map{|n| n.to_s }.join(',')}", :domain => "#{prop.domain.value}")
100
+
101
+ def clearPXE
102
+ OMF::Services.pxe.clearBootImageNS(:ns => "#{@allNodes.map{|n| n.to_s }.join(',')}", :domain => "#{prop.domain.value}")
103
+ end
104
+
105
+ def outputTopologyFile(type, nset)
106
+ begin
107
+ filename = "#{prop.outpath.value}/#{prop.outprefix.value}-topo-#{type}.rb"
108
+ toponame = "#{prop.outprefix.value}-topo-#{type}"
109
+
110
+ # we need to put the array back into the original order
111
+ # since nodes were added in the order they signed in
112
+ sortedNodes = Array.new(@allNodes)
113
+ sortedNodes.delete_if {|n| !nset.include?(n) }
114
+ sortedNodes.map!{|n| n.to_s }
115
+ File.open(filename, "w") do |f|
116
+ f.puts("# Topology name: #{toponame}", "# ")
117
+ f.puts(MESSAGES[type])
118
+ f.print("defTopology('#{toponame}', '")
119
+ f.print(sortedNodes.join(","))
120
+ f.puts "')"
121
+ end
122
+ return filename
123
+ rescue Exception => err
124
+ MObject.warn("exp", "Could not write result topology file: '#{filename}' (#{err})")
125
+ MObject.warn("exp", "(Most probably imaging was OK, but result file could not be created)")
126
+ end
127
+ return nil
128
+ end
129
+
130
+ #
131
+ # Every 10s check the state of the imaging process and report accordingly
132
+ #
133
+ everyNS('image', 10) { |ns|
134
+ nodesUp = 0
135
+ nodesDone = 0
136
+ nodesWithError = 0
137
+ nodesWithErrorList = []
138
+ nodesWithSuccessList = []
139
+ nodesPendingList = []
140
+ nodeCnt = 0
141
+ progMax = 0
142
+ progMin = 100
143
+ nodeMin = nil
144
+ progSum = 0
145
+ startupDelayMax = 0
146
+ report = true
147
+ notDone = true
148
+ lastUpTime = 0
149
+
150
+ ns.each { |n|
151
+ nodeCnt += 1
152
+ if n.isUp
153
+ # nodesUp += 1
154
+ prog = n.match('apps/*/*/progress/text()')[-1].to_s.to_i
155
+ #puts n
156
+ #puts n.match('apps/*/*/progress')
157
+ progSum += prog
158
+ progMax = prog if prog > progMax
159
+ if prog < progMin
160
+ progMin = prog
161
+ nodeMin = n
162
+ end
163
+ startupDelay = n.checkedInAt.to_i - n.poweredAt.to_i
164
+ startupDelayMax = startupDelay if startupDelay > startupDelayMax
165
+ if n.poweredAt.to_i > lastUpTime
166
+ lastUpTime = n.poweredAt.to_i
167
+ end
168
+
169
+ status = n.match('apps/*/status/')[0].to_s
170
+ nodesDone += 1 if status =~ /DONE/
171
+ if status =~ /DONE.ERR/
172
+ nodesWithError += 1
173
+ nodesWithErrorList << n
174
+ elsif status =~ /DONE.OK/
175
+ nodesWithSuccessList << n
176
+ else
177
+ nodesPendingList << n
178
+ end
179
+ else
180
+ # wait with reporting until everybody is up
181
+ report = false
182
+ end
183
+ }
184
+ if report
185
+ progAvg = nodeCnt > 0 ? progSum / nodeCnt : 0
186
+ stats = "#{progMin}/#{progAvg}/#{progMax}"
187
+ prog = "#{nodesDone}/#{nodesWithError}/#{nodeCnt}"
188
+ timeLeft = lastUpTime+prop.timeout.value-Time.now.to_i
189
+ info "Progress(#{prog}): #{stats} min(#{nodeMin})/avg/max (#{startupDelayMax}) - Timeout: #{timeLeft} sec."
190
+
191
+ if (nodesDone >= nodeCnt) || ((lastUpTime+prop.timeout.value) < Time.now.to_i)
192
+ # we are done
193
+ info " ----------------------------- "
194
+ info " Imaging Process Done "
195
+ nodesWhichNeverCheckedIn = @allNodes - nodesWithErrorList - nodesPendingList - nodesWithSuccessList
196
+ if (l = nodesWhichNeverCheckedIn.length) > 0
197
+ f = outputTopologyFile(:checkinfailed, nodesWhichNeverCheckedIn)
198
+ info " #{l} node#{"s" if l>1} failed to check in - Topology saved in '#{f}'"
199
+ end
200
+ if (l = nodesWithErrorList.length) > 0
201
+ f = outputTopologyFile(:imagefailed, nodesWithErrorList)
202
+ info " #{l} node#{"s" if l>1} failed to image the disk - Topology saved in '#{f}'"
203
+ end
204
+ if (l = nodesPendingList.length) > 0
205
+ f = outputTopologyFile(:timeout, nodesPendingList)
206
+ info " #{l} node#{"s" if l>1} timed out - Topology saved in '#{f}'"
207
+ end
208
+ if (l = nodesWithSuccessList.length) > 0
209
+ f = outputTopologyFile(:success, nodesWithSuccessList)
210
+ info " #{l} node#{"s" if l>1} successfully imaged - Topology saved in '#{f}'"
211
+ end
212
+ info " ----------------------------- "
213
+ ns.stopImageServer("#{prop.image.value}", "#{prop.domain.value}")
214
+ Experiment.done
215
+ notDone = false
216
+ end
217
+ end
218
+ notDone
219
+ }
220
+
221
+ onEvent(:INTERRUPT) {
222
+ clearPXE
223
+ }
224
+
225
+ #
226
+ # When all the nodes in the above group are Up, then start loading the image on them
227
+ #
228
+ onEvent(:ALL_UP) {
229
+ clearPXE
230
+ # Only execute imaging if node set is not empty!
231
+ # (e.g. in rare occasions no node managed to come up and register to EC, when this
232
+ # happens, we need to exit quietly from this 'onEvent(:ALL_UP)')
233
+ nodeCount = 0
234
+ group('image').each { |n|
235
+ nodeCount += 1
236
+ }
237
+ if (nodeCount != 0)
238
+ group('image').loadImage(Experiment.property('image'), "#{prop.domain.value}")
239
+ end
240
+ }
241
+
242
+
243
+ ##defURL('/progress') {|req, res|
244
+ #OMF::Common::Web.mapProc('/progress') {|req, res|
245
+ # body = []
246
+ # body << %q{
247
+ #<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
248
+ #<html>
249
+ # <head>
250
+ # <meta http-equiv="refresh" content="10">
251
+ # <title>Imaging Progress :: Orbit</title>
252
+ # <link href="resource/stylesheet/grid.css" type="text/css" rel="stylesheet"/>
253
+ # </head>
254
+ #
255
+ # <body>
256
+ # <h1>Imaging Progress</h1>
257
+ # <table class="grid">
258
+ #}
259
+ # # TODO: port this to OMF 5.4
260
+ # # (1 .. OConfig[:tb_config][:default][:y_max]).each { |y|
261
+ # # body << "<tr class='row'>"
262
+ # # (1 .. OConfig[:tb_config][:default][:x_max]).each { |x|
263
+ # # n = Node[x,y]
264
+ # # if (n == nil)
265
+ # # body << "<td class='cell'></td>"
266
+ # # elsif (n.isUp)
267
+ # # body << "<td class='cell cell-up'>"
268
+ # # progress = n.match('apps/builtin[1]/properties/progress/text()').to_s
269
+ # # if (progress != nil)
270
+ # # body << "<div class='cell-progress' style='width: #{progress}%'></div>"
271
+ # # end
272
+ # # body << "</td>"
273
+ # # else
274
+ # # body << "<td class='cell cell-down'></td>"
275
+ # # end
276
+ # # }
277
+ # # body << "</tr>"
278
+ # # }
279
+ # body << "</table></body></html>"
280
+ # res.body = body.to_s
281
+ # res['Content-Type'] = "text/html"
282
+ #}
283
+ #
@@ -0,0 +1,21 @@
1
+ #
2
+ # This experiment sends a reset to all the resources which are associated to it
3
+ # Typically, one would run this experiment with a specific Experiment ID, with
4
+ # the following command:
5
+ # omf-5.4 exec -e your_experiment_id system:exp:reset
6
+ #
7
+ property.resetDelay = 1
8
+ property.resetTries = 0
9
+ info "---------------"
10
+ info " "
11
+ info " This management experiment will send a RESET to all resources"
12
+ info " in the experiment with the ID: #{Experiment.ID}"
13
+ info " (Typically one would run this experiment with the following"
14
+ info " command: omf-5.4 exec -e your_experiment_id system:exp:reset)"
15
+ info " "
16
+ info " Please wait a few second now..."
17
+ info " "
18
+ info "---------------"
19
+ defGroup("reset", "")
20
+ ECCommunicator.instance.send_reset
21
+ Experiment.done
@@ -0,0 +1,99 @@
1
+ #
2
+ # Copyright (c) 2006-2009 National ICT Australia (NICTA), Australia
3
+ #
4
+ # Copyright (c) 2004-2009 WINLAB, Rutgers University, USA
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #
24
+ #
25
+ # = saveNode.rb
26
+ #
27
+ # == Description
28
+ #
29
+ # This file describes the Experiment that is used to save the disk image of a node within OMF.
30
+ # (In OMF, saving the disk image of a node is treated as an 'experiment' itself)
31
+ #
32
+ #
33
+
34
+ Experiment.name = "imageNode"
35
+ Experiment.project = "Orbit::Admin"
36
+
37
+ defProperty('node', 'omf.nicta.node1', "Node to save image of")
38
+ defProperty('pxe', '1.1.6', "PXE version to use")
39
+ defProperty('domain', "#{OConfig.domain}", "Domain of the node to save")
40
+ defProperty('started', 'false', "internal flag")
41
+
42
+ OMF::Services.pxe.setBootImageNS(:ns => "#{prop.node.value}", :domain => "#{prop.domain.value}")
43
+
44
+ def clearPXE
45
+ OMF::Services.pxe.clearBootImageNS(:ns => "#{prop.node.value}", :domain => "#{prop.domain.value}")
46
+ end
47
+
48
+ #
49
+ # Define nodes used in experiment
50
+ #
51
+ defGroup('save', Experiment.property('node')) {|n|
52
+ #n.pxeImage("#{prop.domain.value}", setPXE=true)
53
+ n.image = "pxe-5.4"
54
+ }
55
+
56
+ everyNS('save', 10) { |ns|
57
+ notDone = true
58
+ ns.each { |n|
59
+ status = n.match('apps/*/status/')[0].to_s
60
+ if status =~ /DONE/
61
+ notDone = false
62
+ if status =~ /DONE.ERR/
63
+ info("- Saving disk image of '#{n}' finished with ERRORS!")
64
+ info(" Check the log file (probably disk read error on the node)")
65
+ else
66
+ info("- Saving disk image of '#{n}' finished with success.")
67
+ end
68
+ info("- Saving process completed at: #{Time.now}")
69
+ info " "
70
+ end
71
+ }
72
+ Experiment.done if notDone == false
73
+ notDone
74
+ }
75
+
76
+ everyNS('save', 10) { |ns|
77
+ ns.each { |n|
78
+ status = n.match('apps/*/status/')[0].to_s
79
+ if status =~ /STARTED/
80
+ if prop.started.value == "false"
81
+ prop.started = "true"
82
+ info " "
83
+ info "- Saving process started at: #{Time.now}"
84
+ info " (this may take a while depending on the size of your image)"
85
+ end
86
+ end
87
+ }
88
+ }
89
+
90
+ onEvent(:INTERRUPT) {
91
+ clearPXE
92
+ }
93
+
94
+ onEvent(:ALL_UP) {
95
+ clearPXE
96
+ group('save').each { |n|
97
+ n.saveImage
98
+ }
99
+ }
@@ -0,0 +1,49 @@
1
+ # This experiment prints the CMC power state of each node in the given topology
2
+
3
+ # empty group to stop OMF from complaining
4
+ # & prevent it from powering on nodes
5
+ defGroup("stat","")
6
+
7
+ defProperty('nodes', 'system:topo:all', 'Nodes to query')
8
+ defProperty('summary', false, 'Show a summary instead of details')
9
+
10
+ topo = nil
11
+ begin
12
+ # if 'nodes' is a topology file, try to load it
13
+ topo = Topology["#{prop.nodes}"]
14
+ rescue
15
+ # if not create a new topology here
16
+ topo = Topology.create(nil, "#{prop.nodes}")
17
+ end
18
+
19
+ tuples = []
20
+
21
+ $stderr.print " Talking to the CMC service, please wait"
22
+
23
+ topo.eachNode {|n|
24
+ tuples << ["#{n.to_s}", "#{OMF::Services.cmc.status(n.to_s, OConfig.domain).
25
+ first_element("NODE_STATUS/detail/node").attributes['state']}"]
26
+ $stderr.print "."
27
+ }
28
+
29
+ puts
30
+ puts "-----------------------------------------------"
31
+ puts " Domain: #{OConfig.domain}"
32
+ if property.summary.value
33
+ on = off = unknown = 0
34
+ tuples.each {|t|
35
+ on += 1 if t[1] == "POWERON"
36
+ off += 1 if t[1] == "POWEROFF"
37
+ unknown += 1 if t[1] == "UNKNOWN"
38
+ }
39
+ puts " Number of nodes in 'Power ON' state:\t#{on}"
40
+ puts " Number of nodes in 'Power OFF' state:\t#{off}"
41
+ puts " Number of nodes in 'Unknown' state:\t#{unknown}"
42
+ else
43
+ tuples.each {|t|
44
+ puts " Node: #{t[0]} \t State: #{t[1]}"
45
+ }
46
+ end
47
+ puts "-----------------------------------------------"
48
+
49
+ Experiment.done
@@ -0,0 +1,122 @@
1
+ #
2
+ # Copyright (c) 2006-2009 National ICT Australia (NICTA), Australia
3
+ # Copyright (c) 2004-2009 WINLAB, Rutgers University, USA
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+ #
23
+ #
24
+ # = stdlib.rb
25
+ #
26
+ # == Description
27
+ #
28
+ # This Ruby file contains various general declarations, which the EC will load
29
+ # before the user's experiment file
30
+ #
31
+ # These declarations implement the process that loop, check and wait that all
32
+ # the required nodes are UP, before proceeding with the remaining of the
33
+ # experiment
34
+ #
35
+
36
+ # Define some properties that we will use in this
37
+ defProperty('resetDelay', 210,
38
+ "Time to wait before assuming that node didn't boot")
39
+ defProperty('resetTries', 1,
40
+ "Number of reset tries before declaring node dead")
41
+ # keeps track of how many times a node has been reset
42
+ ResetCount = {}
43
+
44
+ #
45
+ # This declaration calls the 'everyNS' loop defined in handlerCommand.rb
46
+ # This declared bloc will be executed for all the existing node sets ('*')
47
+ # every 10sec. This loop will stop when the bloc returns 'false', which will
48
+ # happen when all the nodes are UP
49
+ #
50
+ everyNS('*', 10) { |ns|
51
+
52
+ # First check if the experiment has not been interrupted
53
+ #exp_status = Experiment.state("status/text()")
54
+ #return true if allEqual(exp_status, "INTERRUPTED")
55
+
56
+
57
+ # Now check if we are done with adding node in that experiment
58
+ # If not, we skip the checks and loop again in 10sec
59
+ if NodeSet.frozen?
60
+ # Yes, we are done adding nodes...
61
+ nodesDown = []
62
+ nodeCnt = 0
63
+ # For each node in this Node Set, check if it is UP
64
+ # Check that for 'resetDelay' time, if no sucess, reset the node
65
+ # Do only 'resetTries' number of resets before giving up on a node
66
+ ns.eachNode { |n|
67
+ nodeCnt += 1
68
+ if ! n.isUp
69
+ nodesDown << n
70
+ poweredAt = n.poweredAt
71
+ if (poweredAt.kind_of?(Time))
72
+ startupDelay = Time.now - poweredAt
73
+ if (startupDelay > Experiment.property('resetDelay').value)
74
+ count = ResetCount[n] = (ResetCount[n] || 0) + 1
75
+ if (count <= prop.resetTries.value)
76
+ MObject.info('stdlib', "Resetting node ", n)
77
+ n.reset()
78
+ else
79
+ MObject.warn('stdlib', "Giving up on node ", n)
80
+ if NodeHandler.ALLOWMISSING
81
+ Topology.removeNode(n)
82
+ if Topology.empty?
83
+ MObject.info("stdlib", " ")
84
+ MObject.info("stdlib", "No resources available for this "+
85
+ "experiment. Closing the experiment now!" )
86
+ MObject.info("stdlib", "Please wait and ignore remaining "+
87
+ "messages...")
88
+ MObject.info("stdlib", " ")
89
+ Experiment.close
90
+ end
91
+ else
92
+ MObject.error('stdlib', "One or more nodes failed to check in " +
93
+ "to your experiment. To ignore and continue, use the '-a'"+
94
+ " flag. Exiting now.")
95
+ Experiment.close
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ }
102
+ # Check the number of nodes still not UP...
103
+ nodesDownCnt = nodesDown.length
104
+ if nodesDownCnt > 0
105
+ MObject.info('stdlib', "Waiting for nodes (Up/Down/Total): "+
106
+ "#{nodeCnt-nodesDownCnt}/#{nodesDownCnt}/#{nodeCnt}",
107
+ " - (still down: ", nodesDown[0..2].join(','),")")
108
+ end
109
+ # Check if the experiment is not interrupted
110
+ exp_status = Experiment.state("status/text()")
111
+ if allEqual(exp_status, "INTERRUPTED")
112
+ false
113
+ else
114
+ # The experiment is running, stop looping if all the nodes are UP!
115
+ nodesDownCnt > 0
116
+ end
117
+ else
118
+ # We have not finished adding nodes to this experiment,
119
+ # loop and check again in 10sec
120
+ true
121
+ end
122
+ }
@@ -0,0 +1,53 @@
1
+ # This experiment can be used to power on, off, reset or reboot nodes using the CMC
2
+
3
+ # empty group to stop OMF from complaining
4
+ # & prevent it from powering on nodes
5
+ defGroup("tell","")
6
+
7
+ defProperty('nodes', 'system:topo:all', 'Nodes to act on')
8
+ defProperty('command', false, 'Command as in on, offh, offs, reboot, reset')
9
+
10
+ topo = nil
11
+ begin
12
+ # if 'nodes' is a topology file, try to load it
13
+ topo = Topology["#{prop.nodes}"]
14
+ rescue
15
+ # if not create a new topology here
16
+ topo = Topology.create(nil, "#{prop.nodes}")
17
+ end
18
+
19
+ tuples = []
20
+ call = nil
21
+
22
+ case "#{prop.command}"
23
+ when "on"
24
+ call = "on"
25
+ when "offh"
26
+ call = "offHard"
27
+ when "offs"
28
+ call = "offSoft"
29
+ when "reboot"
30
+ call = "reboot"
31
+ when "reset"
32
+ call = "reset"
33
+ else
34
+ raise "Unknown command: '#{prop.command}'. Use 'help' to see usage information."
35
+ end
36
+
37
+ $stderr.print " Talking to the CMC service, please wait"
38
+
39
+ topo.eachNode {|n|
40
+ tuples << ["#{n.to_s}", eval("OMF::Services.cmc.#{call}"+
41
+ "(n.to_s, OConfig.domain).elements[1].name")]
42
+ $stderr.print "."
43
+ }
44
+
45
+ puts
46
+ puts "-----------------------------------------------"
47
+ puts " Domain: #{OConfig.domain} - Command: #{call}"
48
+ tuples.each {|t|
49
+ puts " Node: #{t[0]} \t Reply: #{t[1]}"
50
+ }
51
+ puts "-----------------------------------------------"
52
+
53
+ Experiment.done
@@ -0,0 +1,12 @@
1
+ defProperty('logpath', "unconfigured-logpath", "Path to experiment log")
2
+ defProperty('outpath', "unconfigured-outpath", "Path to experiment output")
3
+
4
+ onEvent(:EXPERIMENT_DONE) do |event|
5
+ begin
6
+ f = File.open("#{property.outpath}", 'w')
7
+ check_outcome ? f.puts("OK") : f.puts("FAILED")
8
+ f.close
9
+ rescue Exception => ex
10
+ puts "TEST - Failed to check the outcome of a test (Error: '#{ex}'"
11
+ end
12
+ end