omf_ec 6.0.0.pre.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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