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
data/bin/xpflow ADDED
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+ # Runs xpflow script
4
+
5
+ require('pathname')
6
+
7
+ def realpath(x)
8
+ Pathname.new(x).realpath.to_s
9
+ end
10
+
11
+ # code that magically switches ruby interpreter
12
+ if ENV.key?("__RUBY__")
13
+ __ruby__ = ENV["__RUBY__"]
14
+ __here__ = realpath(__FILE__)
15
+ ENV.delete("__RUBY__") # avoid infinite loop
16
+ begin
17
+ exec(__ruby__, __here__, *ARGV)
18
+ rescue Errno::ENOENT => e
19
+ puts "Could not launch with custom Ruby (#{e})."
20
+ end
21
+ exit 1
22
+ end
23
+
24
+ def get_lib_dir
25
+ f = __FILE__
26
+ f = File.readlink(f) if File.symlink?(f)
27
+ p = Pathname.new(File.dirname(f))
28
+ lib = File.join(p.realpath, '..', 'lib')
29
+ return Pathname.new(lib).realpath.to_s
30
+ end
31
+
32
+ $:.unshift(get_lib_dir)
33
+
34
+ #XSTART
35
+ require 'xpflow'
36
+ #XEND
37
+
38
+ def usage
39
+ puts "XPFlow (running on Ruby #{RUBY_VERSION})"
40
+ puts
41
+ puts "Usage:"
42
+ puts " xpflow <cmd> <workflow> [OPTIONS]"
43
+ puts
44
+ puts "Standard commands:"
45
+ puts " xpflow run <workflow> - run a workflow"
46
+ puts
47
+ end
48
+
49
+ def use(*args)
50
+
51
+ # TODO: this should be more sophisticated
52
+ # for now it's so so
53
+
54
+ args.each do |lib|
55
+ require "xpflow/exts/#{lib.to_s}_use"
56
+ end
57
+ end
58
+
59
+ if true
60
+
61
+ $original_argv = ARGV.clone
62
+
63
+ begin
64
+ $cmdline_options = XPFlow::Options.new(ARGV.dup)
65
+ $variables = $cmdline_options.vars
66
+ $engine.init_from_options($cmdline_options)
67
+ rescue XPFlow::CmdlineError => e
68
+ if e.ignore?
69
+ exit 0
70
+ else
71
+ Kernel.puts "Error while parsing cmdline: #{e}"
72
+ exit 1
73
+ end
74
+ end
75
+
76
+ $cmdline_options.includes.each do |filename|
77
+ filename = realpath(filename)
78
+ require(filename)
79
+ end
80
+
81
+ ok = nil
82
+ begin
83
+ XPFlow::TerminalThread.start_thread
84
+ _, ok = $cmdline_options.dispatch($engine)
85
+ rescue => e
86
+ Kernel.puts "Error while running : #{e}."
87
+ if $cmdline_options.verbose?
88
+ Kernel.puts "Backtrace:"
89
+ e.backtrace.each do |line|
90
+ Kernel.puts(" " + line)
91
+ end
92
+ end
93
+ ok = false
94
+ end
95
+ exit(ok ? 0 : 1)
96
+ end
data/lib/colorado.rb ADDED
@@ -0,0 +1,198 @@
1
+
2
+ # This simple library allows you to use
3
+ # colors with strings
4
+
5
+ module Colorado
6
+
7
+ COLORS = {
8
+ :red => 31,
9
+ :green => 32,
10
+ :yellow => 33,
11
+ :blue => 34,
12
+ :violet => 35,
13
+ :magenta => 36,
14
+ :white => 37,
15
+ :normal => 0
16
+ }
17
+
18
+ KEYS = COLORS.keys + COLORS.keys.map { |c| "#{c}!" }
19
+
20
+ module StringMix
21
+
22
+ Colorado::KEYS.each do |color|
23
+ define_method(color) do
24
+ return Colorado::Str.new(self, color)
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ module BaseMix
31
+
32
+ Colorado::KEYS.each do |color|
33
+ define_method(color) do
34
+ return self.plain.send(:color)
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ class Color
41
+
42
+ attr_reader :bold
43
+ attr_reader :color
44
+
45
+ def initialize(c)
46
+ @color = (c.is_a?(Color) ? c.color : c)
47
+ @bold = @color.to_s.end_with?('!')
48
+ @index = @color.to_s.chomp('!').to_sym
49
+ end
50
+
51
+ def code
52
+ return COLORS[@index]
53
+ end
54
+
55
+ def prefix
56
+ return '' if @index == :normal
57
+ return (@bold ? "\e[#{code};1m" : "\e[#{code}m")
58
+ end
59
+
60
+ def suffix
61
+ return '' if @index == :normal
62
+ return "\e[0m"
63
+ end
64
+
65
+ def to_s
66
+ return @color.to_s
67
+ end
68
+
69
+ def normal?
70
+ return @index == :normal
71
+ end
72
+
73
+ end
74
+
75
+ class Base
76
+
77
+ include BaseMix
78
+
79
+ attr_reader :color
80
+
81
+ def initialize(color)
82
+ @color = Color.new(color)
83
+ end
84
+
85
+ def +(s)
86
+ s = Str.new(s) if s.is_a?(String)
87
+ return Group.new(self.parts + s.parts)
88
+ end
89
+
90
+ end
91
+
92
+ class Str < Base
93
+
94
+ def initialize(s, color = :normal)
95
+ super(color)
96
+ raise "Already colorized: #{s}" if Colorado.colorized(s)
97
+ @s = s.to_s
98
+ end
99
+
100
+ def inspect
101
+ "<'#{@s}' in #{@color}>"
102
+ end
103
+
104
+ def plain
105
+ return @s
106
+ end
107
+
108
+ def parts
109
+ return [ self ]
110
+ end
111
+
112
+ def to_s
113
+ return "#{color.prefix}#{@s}#{color.suffix}"
114
+ end
115
+ end
116
+
117
+ class Group < Base
118
+
119
+ def initialize(array)
120
+ super(:normal)
121
+ @array = array
122
+ end
123
+
124
+ def exec(method)
125
+ return @array.map { |it| it.send(method) }
126
+ end
127
+
128
+ def parts
129
+ return exec(:parts).reduce(:+)
130
+ end
131
+
132
+ def plain
133
+ return exec(:plain).reduce(:+)
134
+ end
135
+
136
+ def inspect
137
+ return parts.inspect
138
+ end
139
+
140
+ def to_s
141
+ return exec(:to_s).reduce(:+)
142
+ end
143
+
144
+ end
145
+
146
+ def self.substitute(fmt, array)
147
+ parts = fmt.split(/%(.)/)
148
+ strings = []
149
+ idx = 0
150
+ parts.each_index do |i|
151
+ s = parts[i]
152
+ if i.even? # normal string
153
+ next if s == ''
154
+ strings.push(Str.new(s))
155
+ else
156
+ if s == 's'
157
+ strings.push(fix(array[idx]))
158
+ idx += 1
159
+ elsif s == '%'
160
+ strings.push(fix('%'))
161
+ else
162
+ raise "Error!"
163
+ end
164
+ end
165
+ end
166
+ return Group.new(strings)
167
+ end
168
+
169
+ def self.fix(x)
170
+ return x if x.is_a?(Base)
171
+ return Str.new(x.to_s)
172
+ end
173
+
174
+ def self.colorized(s)
175
+ return (!s.is_a?(Base) && s.to_s.include?("\e"))
176
+ end
177
+
178
+ end
179
+
180
+ class String
181
+
182
+ include Colorado::StringMix
183
+
184
+ alias old_addition :+
185
+ alias old_modulo :%
186
+
187
+ def +(x)
188
+ return Colorado::Str.new(self) + x if x.is_a?(Colorado::Base)
189
+ return old_addition(x)
190
+ end
191
+
192
+ def %(x)
193
+ return Colorado.substitute(self, [x]) if x.is_a?(Colorado::Base)
194
+ return Colorado.substitute(self, x) if (x.is_a?(Array) && x.any? { |el| el.is_a?(Colorado::Base) } )
195
+ return old_modulo(x)
196
+ end
197
+
198
+ end
@@ -0,0 +1,243 @@
1
+ # This file contains implementations of ruby core's custom objects for
2
+ # serialisation/deserialisation.
3
+
4
+ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
5
+ require 'json'
6
+ end
7
+ require 'date'
8
+
9
+ # Symbol serialization/deserialization
10
+ class Symbol
11
+ # Returns a hash, that will be turned into a JSON object and represent this
12
+ # object.
13
+ def as_json(*)
14
+ {
15
+ JSON.create_id => self.class.name,
16
+ 's' => to_s,
17
+ }
18
+ end
19
+
20
+ # Stores class name (Symbol) with String representation of Symbol as a JSON string.
21
+ def to_json(*a)
22
+ as_json.to_json(*a)
23
+ end
24
+
25
+ # Deserializes JSON string by converting the <tt>string</tt> value stored in the object to a Symbol
26
+ def self.json_create(o)
27
+ o['s'].to_sym
28
+ end
29
+ end
30
+
31
+ # Time serialization/deserialization
32
+ class Time
33
+
34
+ # Deserializes JSON string by converting time since epoch to Time
35
+ def self.json_create(object)
36
+ if usec = object.delete('u') # used to be tv_usec -> tv_nsec
37
+ object['n'] = usec * 1000
38
+ end
39
+ if respond_to?(:tv_nsec)
40
+ at(*object.values_at('s', 'n'))
41
+ else
42
+ at(object['s'], object['n'] / 1000)
43
+ end
44
+ end
45
+
46
+ # Returns a hash, that will be turned into a JSON object and represent this
47
+ # object.
48
+ def as_json(*)
49
+ {
50
+ JSON.create_id => self.class.name,
51
+ 's' => tv_sec,
52
+ 'n' => respond_to?(:tv_nsec) ? tv_nsec : tv_usec * 1000
53
+ }
54
+ end
55
+
56
+ # Stores class name (Time) with number of seconds since epoch and number of
57
+ # microseconds for Time as JSON string
58
+ def to_json(*args)
59
+ as_json.to_json(*args)
60
+ end
61
+ end
62
+
63
+ # Date serialization/deserialization
64
+ class Date
65
+
66
+ # Deserializes JSON string by converting Julian year <tt>y</tt>, month
67
+ # <tt>m</tt>, day <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> to Date.
68
+ def self.json_create(object)
69
+ civil(*object.values_at('y', 'm', 'd', 'sg'))
70
+ end
71
+
72
+ alias start sg unless method_defined?(:start)
73
+
74
+ # Returns a hash, that will be turned into a JSON object and represent this
75
+ # object.
76
+ def as_json(*)
77
+ {
78
+ JSON.create_id => self.class.name,
79
+ 'y' => year,
80
+ 'm' => month,
81
+ 'd' => day,
82
+ 'sg' => start,
83
+ }
84
+ end
85
+
86
+ # Stores class name (Date) with Julian year <tt>y</tt>, month <tt>m</tt>, day
87
+ # <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string
88
+ def to_json(*args)
89
+ as_json.to_json(*args)
90
+ end
91
+ end
92
+
93
+ # DateTime serialization/deserialization
94
+ class DateTime
95
+
96
+ # Deserializes JSON string by converting year <tt>y</tt>, month <tt>m</tt>,
97
+ # day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>,
98
+ # offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> to DateTime.
99
+ def self.json_create(object)
100
+ args = object.values_at('y', 'm', 'd', 'H', 'M', 'S')
101
+ of_a, of_b = object['of'].split('/')
102
+ if of_b and of_b != '0'
103
+ args << Rational(of_a.to_i, of_b.to_i)
104
+ else
105
+ args << of_a
106
+ end
107
+ args << object['sg']
108
+ civil(*args)
109
+ end
110
+
111
+ alias start sg unless method_defined?(:start)
112
+
113
+ # Returns a hash, that will be turned into a JSON object and represent this
114
+ # object.
115
+ def as_json(*)
116
+ {
117
+ JSON.create_id => self.class.name,
118
+ 'y' => year,
119
+ 'm' => month,
120
+ 'd' => day,
121
+ 'H' => hour,
122
+ 'M' => min,
123
+ 'S' => sec,
124
+ 'of' => offset.to_s,
125
+ 'sg' => start,
126
+ }
127
+ end
128
+
129
+ # Stores class name (DateTime) with Julian year <tt>y</tt>, month <tt>m</tt>,
130
+ # day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>,
131
+ # offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string
132
+ def to_json(*args)
133
+ as_json.to_json(*args)
134
+ end
135
+ end
136
+
137
+ # Range serialization/deserialization
138
+ class Range
139
+
140
+ # Deserializes JSON string by constructing new Range object with arguments
141
+ # <tt>a</tt> serialized by <tt>to_json</tt>.
142
+ def self.json_create(object)
143
+ new(*object['a'])
144
+ end
145
+
146
+ # Returns a hash, that will be turned into a JSON object and represent this
147
+ # object.
148
+ def as_json(*)
149
+ {
150
+ JSON.create_id => self.class.name,
151
+ 'a' => [ first, last, exclude_end? ]
152
+ }
153
+ end
154
+
155
+ # Stores class name (Range) with JSON array of arguments <tt>a</tt> which
156
+ # include <tt>first</tt> (integer), <tt>last</tt> (integer), and
157
+ # <tt>exclude_end?</tt> (boolean) as JSON string.
158
+ def to_json(*args)
159
+ as_json.to_json(*args)
160
+ end
161
+ end
162
+
163
+ # Struct serialization/deserialization
164
+ class Struct
165
+
166
+ # Deserializes JSON string by constructing new Struct object with values
167
+ # <tt>v</tt> serialized by <tt>to_json</tt>.
168
+ def self.json_create(object)
169
+ new(*object['v'])
170
+ end
171
+
172
+ # Returns a hash, that will be turned into a JSON object and represent this
173
+ # object.
174
+ def as_json(*)
175
+ klass = self.class.name
176
+ klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!"
177
+ {
178
+ JSON.create_id => klass,
179
+ 'v' => values,
180
+ }
181
+ end
182
+
183
+ # Stores class name (Struct) with Struct values <tt>v</tt> as a JSON string.
184
+ # Only named structs are supported.
185
+ def to_json(*args)
186
+ as_json.to_json(*args)
187
+ end
188
+ end
189
+
190
+ # Exception serialization/deserialization
191
+ class Exception
192
+
193
+ # Deserializes JSON string by constructing new Exception object with message
194
+ # <tt>m</tt> and backtrace <tt>b</tt> serialized with <tt>to_json</tt>
195
+ def self.json_create(object)
196
+ result = new(object['m'])
197
+ result.set_backtrace object['b']
198
+ result
199
+ end
200
+
201
+ # Returns a hash, that will be turned into a JSON object and represent this
202
+ # object.
203
+ def as_json(*)
204
+ {
205
+ JSON.create_id => self.class.name,
206
+ 'm' => message,
207
+ 'b' => backtrace,
208
+ }
209
+ end
210
+
211
+ # Stores class name (Exception) with message <tt>m</tt> and backtrace array
212
+ # <tt>b</tt> as JSON string
213
+ def to_json(*args)
214
+ as_json.to_json(*args)
215
+ end
216
+ end
217
+
218
+ # Regexp serialization/deserialization
219
+ class Regexp
220
+
221
+ # Deserializes JSON string by constructing new Regexp object with source
222
+ # <tt>s</tt> (Regexp or String) and options <tt>o</tt> serialized by
223
+ # <tt>to_json</tt>
224
+ def self.json_create(object)
225
+ new(object['s'], object['o'])
226
+ end
227
+
228
+ # Returns a hash, that will be turned into a JSON object and represent this
229
+ # object.
230
+ def as_json(*)
231
+ {
232
+ JSON.create_id => self.class.name,
233
+ 'o' => options,
234
+ 's' => source,
235
+ }
236
+ end
237
+
238
+ # Stores class name (Regexp) with options <tt>o</tt> and source <tt>s</tt>
239
+ # (Regexp or String) as JSON string
240
+ def to_json(*)
241
+ as_json.to_json
242
+ end
243
+ end
@@ -0,0 +1,8 @@
1
+ # This file used to implementations of rails custom objects for
2
+ # serialisation/deserialisation and is obsoleted now.
3
+
4
+ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
5
+ require 'json'
6
+ end
7
+
8
+ $DEBUG and warn "required json/add/rails which is obsolete now!"