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,251 @@
1
+
2
+ require 'xpflow'
3
+
4
+ module Graphing
5
+
6
+ class XPFlowConverter
7
+
8
+ def self.from_process(process, ns, opts = {})
9
+ c = XPFlowConverter.new(opts, ns)
10
+ return c.do_process(process)
11
+ end
12
+
13
+ def initialize(opts, ns = nil)
14
+ @opts = { :builtin => false, :checkpoints => false,
15
+ :engine => nil, :subprocess => true }
16
+ @opts.merge!(opts)
17
+ if ns.nil?
18
+ @ns = []
19
+ else
20
+ @ns = ns
21
+ end
22
+ end
23
+
24
+ def engine
25
+ return @opts[:engine]
26
+ end
27
+
28
+ def do_process(process)
29
+ raise "Not a process!" if !process.is_a?(XPFlow::ProcessActivity)
30
+ body = xpflow_recurse(process.body)
31
+ return ProcessFlow.new(body)
32
+ end
33
+
34
+ def do_subprocess(process, name)
35
+ libs, name = engine.into_parts(name)
36
+ @ns.push(libs)
37
+ list = xpflow_map(process.body.body)
38
+ @ns.pop()
39
+ return SubprocessFlow.new(list, process.doc_name)
40
+ end
41
+
42
+ def xpflow_recurse(x)
43
+ klass = x.class.name.split('::').last
44
+ return self.send(('do_' + klass).to_sym, x)
45
+ end
46
+
47
+ def xpflow_map(array)
48
+ raise "Not an array (#{array})!" unless array.is_a?(Array)
49
+ array = array.map { |it| xpflow_recurse(it) }
50
+ array = array.compact # remove nils = hidden elements
51
+ return array
52
+ end
53
+
54
+ def do_SequenceRun(x)
55
+ list = xpflow_map(x.body)
56
+ return SequenceFlow.new(list)
57
+ end
58
+
59
+ def do_ActivityRun(x)
60
+ # TODO
61
+
62
+ if !x.opts[:process].nil?
63
+ name = x.opts[:process]
64
+ else
65
+ name = x.get_name.evaluate_offline()
66
+ end
67
+
68
+ unless x.opts[:text].nil?
69
+ return Block.new(x.opts[:text], x.opts)
70
+ end
71
+
72
+ if name.nil?
73
+ return Block.new("Dynamic activity")
74
+ end
75
+
76
+ original_name = name = name.to_s
77
+
78
+ library = @ns.flatten.join(".")
79
+ if library != ""
80
+ name = "#{library}.#{name}"
81
+ end
82
+
83
+ if activity_visibility(name) == false
84
+ return nil
85
+ end
86
+
87
+ activity = engine.get_activity_object(name)
88
+
89
+ return Block.new("#{name} *") if activity.nil?
90
+
91
+ activity = engine.get_activity_object(name)
92
+ desc = activity.doc
93
+ if desc.nil?
94
+ desc = original_name
95
+ end
96
+
97
+ if !x.builtin? or @opts[:builtin] or activity.doc
98
+ return do_subprocess(activity, original_name) if \
99
+ activity.is_a?(XPFlow::ProcessActivity) and \
100
+ @opts[:subprocess]
101
+ # must be an activity
102
+ return Block.new(desc, x.opts)
103
+ end
104
+
105
+ return nil
106
+ end
107
+
108
+ def do_ExperimentRun(x)
109
+ exp = x.get_name
110
+ if exp.nil?
111
+ return Block.new("Exp run") # TODO
112
+ else
113
+ name = "#{exp}.__standard__"
114
+ activity = engine.get_activity_object(name)
115
+ return do_subprocess(activity, "__standard__")
116
+ end
117
+ end
118
+
119
+ def do_ResultRun(x)
120
+ # TODO
121
+ return xpflow_recurse(x.body)
122
+ end
123
+
124
+ def do_TimesRun(x)
125
+ # TODO
126
+ return xpflow_recurse(x.body)
127
+ end
128
+
129
+ def do_InfoRun(x)
130
+ # TODO
131
+ return xpflow_recurse(x.body)
132
+ end
133
+
134
+ def do_ReturnLoopRun(x)
135
+ # TODO
136
+ return Block.new("Loop return")
137
+ end
138
+
139
+ def do_LoopRun(x)
140
+ # TODO
141
+ list = xpflow_map(x.body)
142
+ return SubprocessFlow.new(list, "Loop")
143
+ end
144
+
145
+ def do_ParallelRun(x)
146
+ list = xpflow_map(x.body)
147
+ return ParallelFlow.new(list)
148
+ end
149
+
150
+ def do_CheckpointRun(x)
151
+ # TODO
152
+ return nil if !@opts[:checkpoints]
153
+ return Block.new("Checkpoint :#{x.name}")
154
+ end
155
+
156
+ def do_CacheRun(x)
157
+ # TODO: this should add something more
158
+ return do_SequenceRun(x.body)
159
+ end
160
+
161
+ def do_TryRun(x)
162
+ # TODO
163
+ return xpflow_recurse(x.body)
164
+ end
165
+
166
+ def do_PeriodRun(x)
167
+ # TODO
168
+ return xpflow_recurse(x.body)
169
+ end
170
+
171
+ def do_ForAllRun(x)
172
+ # TODO
173
+ body = xpflow_recurse(x.body)
174
+ return ForallFlow.new([ body ], {})
175
+ end
176
+
177
+ def do_ForEachRun(x)
178
+ # TODO
179
+ body = xpflow_recurse(x.body)
180
+ return ForallFlow.new([ body ])
181
+ end
182
+
183
+ def do_ForManyRun(x)
184
+ # TODO
185
+ return xpflow_recurse(x.body)
186
+ end
187
+
188
+ def do_IfRun(x)
189
+ # TODO
190
+ on_true = xpflow_recurse(x.on_true)
191
+ on_false = xpflow_recurse(x.on_false)
192
+ return ParallelFlow.new([ on_true, on_false ])
193
+ end
194
+
195
+ end
196
+
197
+ end
198
+
199
+ if $0 == __FILE__
200
+ require('xpflow/graph')
201
+
202
+ # use :g5k
203
+
204
+ p = $engine.process :main do |site, sname|
205
+ switch = run 'g5k.switch', site, sname
206
+ log 'Experimenting with switch: ', switch
207
+ nodes = run 'g5k.nodes', switch
208
+ r = run 'g5k.reserve_nodes',
209
+ :nodes => nodes, :time => '02:00:00', :site => site, :keep => false,
210
+ :type => :deploy, :ignore_dead => true
211
+ nodes = (run 'g5k.nodes', r)
212
+ nodes = code(nodes) { |ns| (ns.length % 2 == 0) ? ns : ns[0...-1] } # we need an even number of nodes
213
+ master, slaves = (first_of nodes), (tail_of nodes)
214
+ checkpoint :reserved
215
+ rerun 'g5k.deploy', r, :env => 'squeeze-x64-nfs'
216
+ checkpoint :deployed
217
+ parallel :retry => 100 do
218
+ period :install_pkgs do
219
+ forall slaves do |slave|
220
+ run({ :gantt => false }, :install_pkgs, slave)
221
+ end
222
+ end
223
+ sequence do
224
+ run :install_pkgs, master
225
+ run :build_netgauge, master
226
+ run :distribute_netgauge, master, slaves
227
+ end
228
+ end
229
+ checkpoint :run_experiment
230
+ output = run :netgauge, master, nodes
231
+ checkpoint :interpret_results
232
+ run :analysis, output, switch
233
+ log "DONE."
234
+ end
235
+
236
+ x = Graphing::XPFlowConverter.from_process(p, :builtin => false)
237
+ s = Graphing::TikzGrapher.new(x).draw()
238
+
239
+ $engine.activity :cze do
240
+ log "cze"
241
+ end
242
+
243
+ q = $engine.process :bah do
244
+ run :cze
245
+ run 'whatever'
246
+ run :main
247
+ end
248
+ x = Graphing::XPFlowConverter.from_process(q,
249
+ :builtin => false, :engine => $engine)
250
+ puts Graphing.to_pdf(x, "cze.pdf", :debug => false)
251
+ end
@@ -0,0 +1,196 @@
1
+
2
+ module XPFlow
3
+
4
+ class GitRepo
5
+
6
+ def initialize(address)
7
+ @address = address
8
+ end
9
+
10
+ def versions
11
+ version_exp = Regexp.new("refs/tags/xpflow/(.+)")
12
+ cmd = "git ls-remote --tags #{@address}"
13
+ # puts cmd
14
+ tags = %x(#{cmd})
15
+ tags = tags.strip.lines.map(&:split)
16
+ vs = {}
17
+ tags.each do |hash, tag|
18
+ m = version_exp.match(tag)
19
+ if !m.nil?
20
+ vs[m.captures.first] = hash
21
+ end
22
+ end
23
+ return vs
24
+ end
25
+
26
+ def comparable_versions
27
+ vs = versions()
28
+ h = [ ]
29
+ vs.each_pair do |version, hash|
30
+ v = Repo.parse_version(version, hash)
31
+ h.push(v) unless v.nil?
32
+ end
33
+ return h.sort { |x, y| y <=> x } # from the newest downwards
34
+ end
35
+
36
+ def filter_versions(&block)
37
+ vs = comparable_versions()
38
+ return vs.select(&block)
39
+ end
40
+
41
+ def get_latest
42
+ return comparable_versions().max
43
+ end
44
+
45
+ def get_version(v)
46
+ v = Version.flatten(v)
47
+ v = v.to_dots if v.is_a?(Version)
48
+ vs = versions()
49
+ raise "No version #{v}" unless vs.key?(v)
50
+ return AnyVersion.new(vs[v], v)
51
+ end
52
+
53
+ def get_less_than(v)
54
+ v = Version.flatten(v)
55
+ r = filter_versions { |x| (x <=> v) < 0 }
56
+ raise "No version < #{v}" if r.length == 0
57
+ return r.max
58
+ end
59
+
60
+ def get_less_equal(v)
61
+ v = Version.flatten(v)
62
+ r = filter_versions { |x| (x <=> v) <= 0 }
63
+ raise "No version <= #{v}" if r.length == 0
64
+ return r.max
65
+ end
66
+
67
+ def checkout_version(v)
68
+ hash = v.hash
69
+ tmpdir = %x(mktemp -d).strip
70
+ Kernel.system("git clone #{@address} #{tmpdir}")
71
+ Kernel.system("cd #{tmpdir} && git checkout #{hash} -b __xpflow__")
72
+
73
+ end
74
+
75
+ end
76
+
77
+ class Modules
78
+
79
+ # contains information about installed modules
80
+
81
+ def initialize(directory)
82
+ @directory = directory
83
+ @versions = load_versions()
84
+ end
85
+
86
+ def load_versions
87
+ dirs = Dir.entries(@directory) - [ ".", ".." ]
88
+
89
+ end
90
+
91
+ end
92
+
93
+ class Version
94
+
95
+ attr_reader :major
96
+ attr_reader :minor
97
+ attr_reader :manor
98
+
99
+ def initialize(major, manor = 0, minor = 0)
100
+ @major = major
101
+ @manor = manor
102
+ @minor = minor
103
+ end
104
+
105
+ def self.flatten(x)
106
+ return x if x.is_a?(Version)
107
+ parts = x.split(".").map(&:to_i)
108
+ if (parts.length == 0 or parts.length > 3)
109
+ raise "Wrong version '#{x}'"
110
+ end
111
+ return Version.new(*parts)
112
+ end
113
+
114
+ def middle
115
+ return @manor
116
+ end
117
+
118
+ def <=>(x)
119
+ return (self.major <=> x.major) if self.major != x.major
120
+ return (self.manor <=> x.manor) if self.manor != x.manor
121
+ return (self.minor <=> x.minor)
122
+ end
123
+
124
+ def to_dots
125
+ return "#{@major}.#{@manor}.#{@minor}"
126
+ end
127
+
128
+ def to_s
129
+ return "{Version #{to_dots}}"
130
+ end
131
+
132
+ end
133
+
134
+ class AnyVersion
135
+
136
+ attr_reader :hash
137
+ attr_reader :name
138
+
139
+ def initialize(hash, name)
140
+ @hash = hash
141
+ @name = name
142
+ end
143
+
144
+ def to_s
145
+ return "{Version #{@name} #{@hash}}"
146
+ end
147
+
148
+ end
149
+
150
+ class RepoVersion < Version
151
+
152
+ attr_reader :hash
153
+
154
+ def initialize(hash, major, manor = 0, minor = 0)
155
+ super(major, manor, minor)
156
+ @hash = hash
157
+ end
158
+
159
+ def to_s
160
+ return "{Version #{to_dots} #{@hash}}"
161
+ end
162
+
163
+ end
164
+
165
+ class Repo
166
+
167
+ def self.parse_version(version, hash)
168
+ exp = Regexp.new('^(\d+|\d+\.\d+|\d+\.\d+\.\d+)$')
169
+ m = exp.match(version)
170
+ return nil if m.nil?
171
+ parts = version.split(".").map(&:to_i)
172
+ return RepoVersion.new(hash, *parts)
173
+ end
174
+
175
+ def self.create(url)
176
+ scheme, address = url.split("://", 2)
177
+ repo = case scheme
178
+ when 'github' then GitRepo.new("https://github.com/#{address}")
179
+ when 'local' then GitRepo.new("file://#{address}")
180
+ else
181
+ raise "Unknown scheme: #{scheme}"
182
+ end
183
+ return repo
184
+ end
185
+
186
+ end
187
+
188
+ if __FILE__ == $0
189
+ m = Modules.new("./modules")
190
+
191
+ repo = Repo.create("local:///home/toma/projects/sandbox/xpflow-test")
192
+ latest = repo.get_latest
193
+ # repo.checkout_version(latest)
194
+ end
195
+
196
+ end