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.
- data/bin/xpflow +96 -0
- data/lib/colorado.rb +198 -0
- data/lib/json/add/core.rb +243 -0
- data/lib/json/add/rails.rb +8 -0
- data/lib/json/common.rb +423 -0
- data/lib/json/editor.rb +1369 -0
- data/lib/json/ext.rb +28 -0
- data/lib/json/pure/generator.rb +442 -0
- data/lib/json/pure/parser.rb +320 -0
- data/lib/json/pure.rb +15 -0
- data/lib/json/version.rb +8 -0
- data/lib/json.rb +62 -0
- data/lib/mime/types.rb +881 -0
- data/lib/mime-types.rb +3 -0
- data/lib/restclient/abstract_response.rb +106 -0
- data/lib/restclient/exceptions.rb +193 -0
- data/lib/restclient/net_http_ext.rb +55 -0
- data/lib/restclient/payload.rb +235 -0
- data/lib/restclient/raw_response.rb +34 -0
- data/lib/restclient/request.rb +316 -0
- data/lib/restclient/resource.rb +169 -0
- data/lib/restclient/response.rb +24 -0
- data/lib/restclient.rb +174 -0
- data/lib/xpflow/bash.rb +341 -0
- data/lib/xpflow/bundle.rb +113 -0
- data/lib/xpflow/cmdline.rb +249 -0
- data/lib/xpflow/collection.rb +122 -0
- data/lib/xpflow/concurrency.rb +79 -0
- data/lib/xpflow/data.rb +393 -0
- data/lib/xpflow/dsl.rb +816 -0
- data/lib/xpflow/engine.rb +574 -0
- data/lib/xpflow/ensemble.rb +135 -0
- data/lib/xpflow/events.rb +56 -0
- data/lib/xpflow/experiment.rb +65 -0
- data/lib/xpflow/exts/facter.rb +30 -0
- data/lib/xpflow/exts/g5k.rb +931 -0
- data/lib/xpflow/exts/g5k_use.rb +50 -0
- data/lib/xpflow/exts/gui.rb +140 -0
- data/lib/xpflow/exts/model.rb +155 -0
- data/lib/xpflow/graph.rb +1603 -0
- data/lib/xpflow/graph_xpflow.rb +251 -0
- data/lib/xpflow/import.rb +196 -0
- data/lib/xpflow/library.rb +349 -0
- data/lib/xpflow/logging.rb +153 -0
- data/lib/xpflow/manager.rb +147 -0
- data/lib/xpflow/nodes.rb +1250 -0
- data/lib/xpflow/runs.rb +773 -0
- data/lib/xpflow/runtime.rb +125 -0
- data/lib/xpflow/scope.rb +168 -0
- data/lib/xpflow/ssh.rb +186 -0
- data/lib/xpflow/stat.rb +50 -0
- data/lib/xpflow/stdlib.rb +381 -0
- data/lib/xpflow/structs.rb +369 -0
- data/lib/xpflow/taktuk.rb +193 -0
- data/lib/xpflow/templates/ssh-config.basic +14 -0
- data/lib/xpflow/templates/ssh-config.inria +18 -0
- data/lib/xpflow/templates/ssh-config.proxy +13 -0
- data/lib/xpflow/templates/taktuk +6590 -0
- data/lib/xpflow/templates/utils/batch +4 -0
- data/lib/xpflow/templates/utils/bootstrap +12 -0
- data/lib/xpflow/templates/utils/hostname +3 -0
- data/lib/xpflow/templates/utils/ping +3 -0
- data/lib/xpflow/templates/utils/rsync +12 -0
- data/lib/xpflow/templates/utils/scp +17 -0
- data/lib/xpflow/templates/utils/scp_many +8 -0
- data/lib/xpflow/templates/utils/ssh +3 -0
- data/lib/xpflow/templates/utils/ssh-interactive +4 -0
- data/lib/xpflow/templates/utils/taktuk +19 -0
- data/lib/xpflow/threads.rb +187 -0
- data/lib/xpflow/utils.rb +569 -0
- data/lib/xpflow/visual.rb +230 -0
- data/lib/xpflow/with_g5k.rb +7 -0
- data/lib/xpflow.rb +349 -0
- 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
|