xpflow 0.1b

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 (74) hide show
  1. data/bin/xpflow +96 -0
  2. data/lib/colorado.rb +198 -0
  3. data/lib/json/add/core.rb +243 -0
  4. data/lib/json/add/rails.rb +8 -0
  5. data/lib/json/common.rb +423 -0
  6. data/lib/json/editor.rb +1369 -0
  7. data/lib/json/ext.rb +28 -0
  8. data/lib/json/pure/generator.rb +442 -0
  9. data/lib/json/pure/parser.rb +320 -0
  10. data/lib/json/pure.rb +15 -0
  11. data/lib/json/version.rb +8 -0
  12. data/lib/json.rb +62 -0
  13. data/lib/mime/types.rb +881 -0
  14. data/lib/mime-types.rb +3 -0
  15. data/lib/restclient/abstract_response.rb +106 -0
  16. data/lib/restclient/exceptions.rb +193 -0
  17. data/lib/restclient/net_http_ext.rb +55 -0
  18. data/lib/restclient/payload.rb +235 -0
  19. data/lib/restclient/raw_response.rb +34 -0
  20. data/lib/restclient/request.rb +316 -0
  21. data/lib/restclient/resource.rb +169 -0
  22. data/lib/restclient/response.rb +24 -0
  23. data/lib/restclient.rb +174 -0
  24. data/lib/xpflow/bash.rb +341 -0
  25. data/lib/xpflow/bundle.rb +113 -0
  26. data/lib/xpflow/cmdline.rb +249 -0
  27. data/lib/xpflow/collection.rb +122 -0
  28. data/lib/xpflow/concurrency.rb +79 -0
  29. data/lib/xpflow/data.rb +393 -0
  30. data/lib/xpflow/dsl.rb +816 -0
  31. data/lib/xpflow/engine.rb +574 -0
  32. data/lib/xpflow/ensemble.rb +135 -0
  33. data/lib/xpflow/events.rb +56 -0
  34. data/lib/xpflow/experiment.rb +65 -0
  35. data/lib/xpflow/exts/facter.rb +30 -0
  36. data/lib/xpflow/exts/g5k.rb +931 -0
  37. data/lib/xpflow/exts/g5k_use.rb +50 -0
  38. data/lib/xpflow/exts/gui.rb +140 -0
  39. data/lib/xpflow/exts/model.rb +155 -0
  40. data/lib/xpflow/graph.rb +1603 -0
  41. data/lib/xpflow/graph_xpflow.rb +251 -0
  42. data/lib/xpflow/import.rb +196 -0
  43. data/lib/xpflow/library.rb +349 -0
  44. data/lib/xpflow/logging.rb +153 -0
  45. data/lib/xpflow/manager.rb +147 -0
  46. data/lib/xpflow/nodes.rb +1250 -0
  47. data/lib/xpflow/runs.rb +773 -0
  48. data/lib/xpflow/runtime.rb +125 -0
  49. data/lib/xpflow/scope.rb +168 -0
  50. data/lib/xpflow/ssh.rb +186 -0
  51. data/lib/xpflow/stat.rb +50 -0
  52. data/lib/xpflow/stdlib.rb +381 -0
  53. data/lib/xpflow/structs.rb +369 -0
  54. data/lib/xpflow/taktuk.rb +193 -0
  55. data/lib/xpflow/templates/ssh-config.basic +14 -0
  56. data/lib/xpflow/templates/ssh-config.inria +18 -0
  57. data/lib/xpflow/templates/ssh-config.proxy +13 -0
  58. data/lib/xpflow/templates/taktuk +6590 -0
  59. data/lib/xpflow/templates/utils/batch +4 -0
  60. data/lib/xpflow/templates/utils/bootstrap +12 -0
  61. data/lib/xpflow/templates/utils/hostname +3 -0
  62. data/lib/xpflow/templates/utils/ping +3 -0
  63. data/lib/xpflow/templates/utils/rsync +12 -0
  64. data/lib/xpflow/templates/utils/scp +17 -0
  65. data/lib/xpflow/templates/utils/scp_many +8 -0
  66. data/lib/xpflow/templates/utils/ssh +3 -0
  67. data/lib/xpflow/templates/utils/ssh-interactive +4 -0
  68. data/lib/xpflow/templates/utils/taktuk +19 -0
  69. data/lib/xpflow/threads.rb +187 -0
  70. data/lib/xpflow/utils.rb +569 -0
  71. data/lib/xpflow/visual.rb +230 -0
  72. data/lib/xpflow/with_g5k.rb +7 -0
  73. data/lib/xpflow.rb +349 -0
  74. metadata +135 -0
@@ -0,0 +1,381 @@
1
+ # encoding: UTF-8
2
+
3
+ #
4
+ # Implementation of core activities.
5
+ #
6
+
7
+ require 'erb'
8
+ require 'ostruct'
9
+
10
+ module XPFlow
11
+
12
+ class Erb < OpenStruct
13
+
14
+ def render(hash)
15
+ ERB.new(hash).result(binding)
16
+ end
17
+
18
+ def self.render(template, hash)
19
+ x = Erb.new(hash)
20
+ return x.render(template)
21
+ end
22
+
23
+ end
24
+
25
+ # SSH = Net::SSH
26
+
27
+ class CoreLibrary < HiddenActivityLibrary
28
+
29
+ activities :sleep, :value, :code, :log, :repr, :system, :range,
30
+ :render_file, :render, :render_inline, :assert, :debug,
31
+ :start, :set_scope, :get_scope, :fail, :new_experiment,
32
+ :arguments, :item_range, :shift,
33
+ :send => :send_method, :id => :value, :"λ" => :code
34
+
35
+ def render_inline(template, hash = {})
36
+ return Erb.render(template, hash)
37
+ end
38
+
39
+ def shift(array)
40
+ return [ array.first, array.tail ]
41
+ end
42
+
43
+ def render(name, hash = {})
44
+ tmpl = $files[name]
45
+ raise "Template does not exist!" if tmpl.nil?
46
+ template = IO.read(tmpl)
47
+ return render_inline(template, hash)
48
+ end
49
+
50
+ def arguments(shift = 0)
51
+ tab = Scope.current.parent_activity[:__name__].arguments
52
+ return tab[shift ... tab.length]
53
+ end
54
+
55
+ def new_experiment
56
+ # inserts a new experiment in the +1 scope
57
+ scope = Scope.current.parent_activity
58
+ parent_experiment = scope[:__experiment__]
59
+ name = scope[:__name__].activity_full_name
60
+ scope[:__experiment__] = parent_experiment.create_subexperiment(name)
61
+ end
62
+
63
+ def render_file(name, out, hash = {})
64
+ s = render(name, hash)
65
+ File.open(out, "wb") do |f|
66
+ f.write(s)
67
+ end
68
+ return nil
69
+ end
70
+
71
+ def sleep(time)
72
+ span = Timespan.to_secs(time)
73
+ if span.infinite?
74
+ loop do; Kernel.sleep(1) end
75
+ end
76
+ Kernel.sleep(span)
77
+ end
78
+
79
+ def system(cmd)
80
+ result = `#{cmd}`
81
+ status = $?
82
+ code = status.exitstatus
83
+ raise "'#{cmd}' returned with code = #{code}" if code != 0
84
+ return result
85
+ end
86
+
87
+ def value(v)
88
+ return v
89
+ end
90
+
91
+ def code(*args)
92
+ raise 'No code given.' unless block_given?
93
+ return yield(*args)
94
+ end
95
+
96
+ def flatten_msgs(msgs)
97
+ return msgs.map { |m| m.__repr__ }.join("")
98
+ end
99
+
100
+ def get_scope(name)
101
+ return Scope.current[name]
102
+ end
103
+
104
+ def process_name
105
+ return Scope.current.parent[:__name__].activity_full_name
106
+ end
107
+
108
+ def log(*msgs)
109
+ msg = "Process %s: %s" % [ process_name.green, flatten_msgs(msgs) ]
110
+ proxy.engine.log(msg)
111
+ return nil
112
+ end
113
+
114
+ def debug(*msgs)
115
+ proxy.engine.debug(
116
+ "Process %s: %s" % [ process_name.green, flatten_msgs(msgs) ])
117
+ return nil
118
+ end
119
+
120
+ def fail(msg = "?", prob = 1.0)
121
+ raise "Failure (reason: #{msg})" if (Kernel.rand <= prob)
122
+ end
123
+
124
+ def send_method(o, method, *args)
125
+ return o.send(method.to_sym, *args) if o.respond_to?(method)
126
+ return o[method] if (o.is_a?(Hash) and o.key?(method))
127
+ return o[method.to_s] if (o.is_a?(Hash) and o.key?(method.to_s))
128
+ raise "No '#{method}' method for #{o.class}"
129
+ end
130
+
131
+ def repr(v)
132
+ return v.__repr__
133
+ end
134
+
135
+ def range(*args)
136
+ f = args.first
137
+ if args.length == 1 and f.is_a?(Range)
138
+ return f.to_a
139
+ elsif args.length == 1 and f.is_a?(Fixnum)
140
+ return range(0 ... f)
141
+ elsif args.length == 2
142
+ return range(f ... args.last)
143
+ elsif args.length == 3
144
+ return (args[0] .. args[1]).step(args[2]).to_a
145
+ end
146
+ raise "Wrong arguments to range: #{args}"
147
+ end
148
+
149
+ def item_range(items, last)
150
+ return items[0 ... last]
151
+ end
152
+
153
+ def set_scope(key, value)
154
+ Scope.current.parent.parent[key] = value # TODO: that's kind of weird
155
+ end
156
+
157
+ def assert(condition)
158
+ raise "Assertion failed." unless condition
159
+ end
160
+
161
+ # mapped from runtime library
162
+
163
+ def start(*args)
164
+ return proxy.engine.runtime.invoke(:start, args)
165
+ end
166
+
167
+ def finish(*args)
168
+ return proxy.engine.runtime.invoke(:finish, args)
169
+ end
170
+
171
+ def event(*args)
172
+ return proxy.engine.runtime.invoke(:event, args)
173
+ end
174
+
175
+ end
176
+
177
+ class GetSetLibrary < SyncedActivityLibrary
178
+
179
+ activities :get, :set, :config, :config_full,
180
+ :entry_activity,
181
+ :conf => :config
182
+
183
+ attr_accessor :configuration
184
+
185
+ include SerializableLibrary
186
+
187
+ def setup
188
+ @storage = {}
189
+ @configuration = {}
190
+ end
191
+
192
+ def get(key)
193
+ raise "Unknown key: #{key}" unless @storage.key?(key)
194
+ return @storage[key]
195
+ end
196
+
197
+ def set(key, value)
198
+ @storage[key] = value
199
+ end
200
+
201
+ def config(key)
202
+ raise "Unknown config option: #{key}" unless @configuration.key?(key)
203
+ return @configuration[key]
204
+ end
205
+
206
+ def config_full
207
+ return @configuration
208
+ end
209
+
210
+ def update_config(hash)
211
+ h = {}
212
+ hash.each_pair do |k, v|
213
+ h[k.to_sym] = v
214
+ end
215
+ @configuration.merge!(h)
216
+ end
217
+
218
+ def set_entry_activity(name)
219
+ set(:__original_entry__, name)
220
+ end
221
+
222
+ def entry_activity
223
+ return get(:__original_entry__)
224
+ end
225
+
226
+ end
227
+
228
+ class RunLater
229
+ # runs an activity later
230
+
231
+ attr_reader :name
232
+ attr_reader :args
233
+
234
+ def initialize(name, args)
235
+ @name = name
236
+ @args = args
237
+ end
238
+
239
+ def to_s
240
+ return "RunLater of '#{@name}' with (#{@args.inspect})"
241
+ end
242
+
243
+ def extend(args)
244
+ return RunLater.new(@name, @args + args)
245
+ end
246
+
247
+ end
248
+
249
+ class DataLibrary < SyncedActivityLibrary
250
+
251
+ activities :store, :data, :avg, :sum, :stddev, :gauss,
252
+ :confidence_precision, :confidence_interval, :save_yaml,
253
+ :data_vector, :conf_precision, :data_append, :data_push,
254
+ :run_later, :get_of, :minimal_sample, :minimal_sample_enough
255
+
256
+ def data_vector(values = nil)
257
+ return ValueData.new(values)
258
+ end
259
+
260
+ def get_of(object, key, default = nil)
261
+ str = key.to_s
262
+ sym = key.to_sym
263
+ if object.is_a?(Hash)
264
+ return object[str] if object.key?(str)
265
+ return object[sym] if object.key?(sym)
266
+ return default unless default.nil?
267
+ raise "No such key as '#{key}' in #{object}"
268
+ end
269
+
270
+ if object.respond_to?(sym)
271
+ return object.__send__(sym)
272
+ end
273
+
274
+ return default unless default.nil?
275
+ raise "No such property as '#{key}' on #{object} of class #{object.class}"
276
+ end
277
+
278
+ def setup
279
+ @storage = {}
280
+ end
281
+
282
+ def store(name, value)
283
+ @storage[name] = ValueData.new unless @storage.key?(name)
284
+ @storage[name].push(value.to_f)
285
+ end
286
+
287
+ def data(name)
288
+ @storage[name] = ValueData.new unless @storage.key?(name)
289
+ return @storage[name]
290
+ end
291
+
292
+ def run_later(name, *args)
293
+ if name.is_a?(RunLater)
294
+ return name.extend(args)
295
+ end
296
+ return RunLater.new(name, args)
297
+ end
298
+
299
+ def _stddev(vector)
300
+ m = avg(vector)
301
+ disp = vector.map { |x| (x - m)**2 }.reduce(:+)
302
+ var = disp.to_f / (vector.length - 1)
303
+ return (var ** 0.5)
304
+ end
305
+
306
+ def _sum(vector)
307
+ return vector.reduce(:+)
308
+ end
309
+
310
+ def _avg(vector)
311
+ return sum(vector).to_f / (vector.length)
312
+ end
313
+
314
+ def gauss(m = 0.0, s = 1.0)
315
+ x = Kernel.rand
316
+ y = Kernel.rand
317
+ p = (-2 * Math.log(1 - y)) ** 0.5
318
+ return m + s * Math.cos(2*Math::PI*x) * p
319
+ end
320
+
321
+ def data_append(data, x)
322
+ return data.append(x)
323
+ end
324
+
325
+ def data_push(data, x)
326
+ data.push(x)
327
+ end
328
+
329
+ def confidence_precision(name)
330
+ return data(name).confidence_precision
331
+ end
332
+
333
+ def conf_precision(x)
334
+ return x.confidence_precision
335
+ end
336
+
337
+ def confidence_interval(name)
338
+ return data(name).confidence_interval
339
+ end
340
+
341
+ def stddev(name)
342
+ return data(name).stddev
343
+ end
344
+
345
+ def sum(name)
346
+ if name.is_a?(Array)
347
+ return name.reduce(:+)
348
+ else
349
+ return data(name).sum
350
+ end
351
+ end
352
+
353
+ def save_yaml(filename, obj)
354
+ IO.write(filename, obj.to_yaml)
355
+ end
356
+ def minimal_sample_enough(name,opts={})
357
+ minimal_sample(name,opts)<name.size
358
+ end
359
+ def minimal_sample(name,opts={})
360
+ opts.merge({:conf=>0.95,:abs=>1})
361
+ name.minimal_sample_both(opts[:rel],opts[:abs],opts[:conf])
362
+ end
363
+ end
364
+
365
+ class TestLibrary < SyncedActivityLibrary
366
+ # used for testing
367
+
368
+ attr_reader :values
369
+ activities :collect
370
+
371
+ def setup
372
+ @values = []
373
+ end
374
+
375
+ def collect(value)
376
+ @values.push(value)
377
+ end
378
+
379
+ end
380
+
381
+ end