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,50 @@
1
+
2
+ # just reuse existing thing
3
+
4
+ def __check_g5k_credentials_path__
5
+ home = Etc.getpwuid.dir
6
+ return File.join(home, '.g5k.yaml')
7
+ end
8
+
9
+ def __check_g5k_credentials__
10
+ path = __check_g5k_credentials_path__()
11
+ if File.exist?(path)
12
+ h = YAML.load_file(path)
13
+ mode = File::Stat.new(path).mode
14
+ raise "#{path} is accessible by other users" if (mode & 077 != 0)
15
+ else
16
+ return nil
17
+ end
18
+ if !h.is_a?(Hash) or h["user"].nil? or h["pass"].nil?
19
+ raise "bad credentials"
20
+ end
21
+ [ h["user"], h["pass"] ]
22
+ end
23
+
24
+ def __save_g5k_credentials__
25
+ path = __check_g5k_credentials_path__()
26
+ File.open(path, "w") do |f|
27
+ f.puts({
28
+ "user" => $g5k_user,
29
+ "pass" => $g5k_pass
30
+ }.to_yaml)
31
+ end
32
+ File.chmod(0600, path)
33
+ end
34
+
35
+ $g5k_creds = __check_g5k_credentials__()
36
+
37
+ if $g5k_creds.nil?
38
+ # no credentials
39
+ $g5k_user = var(:g5k_user, :str, :text => "Provide G5K username: ")
40
+ $g5k_pass = var(:g5k_pass, :pass, :text => "Provide G5K password: ")
41
+ $g5k_save = var(:g5k_save, :bool, :callback => proc { |x| __save_g5k_credentials__ if x }, :text => "Do you want to save these credentials?")
42
+ else
43
+ $g5k_user = set_var(:g5k_user, $g5k_creds.first)
44
+ $g5k_pass = set_var(:g5k_pass, $g5k_creds.last)
45
+ end
46
+
47
+ # hide the password
48
+ set_var(:g5k_pass, "*" * $g5k_pass.length)
49
+
50
+ require 'xpflow/with_g5k'
@@ -0,0 +1,140 @@
1
+
2
+ require 'sinatra/base'
3
+ require 'json'
4
+
5
+ class << Sinatra::Base
6
+
7
+ def quit!(server, handler_name)
8
+ server.respond_to?(:stop!) ? server.stop! : server.stop
9
+ end
10
+
11
+ # copy-pasted-adjusted from sinatra code (1.3.2-2 in Debian)
12
+ def _run_custom!(options={})
13
+ set options
14
+ set :logging, nil
15
+ handler = detect_rack_handler
16
+ handler_name = handler.name.gsub(/.*::/, '')
17
+ handler.run self, :Host => bind, :Port => port do |server|
18
+ @__quit__ = proc { || quit!(server, handler_name) }
19
+ server.threaded = settings.threaded if server.respond_to? :threaded=
20
+ set :running, true
21
+ yield server if block_given?
22
+ end
23
+ end
24
+
25
+ def run_custom!(options={})
26
+ # it may result in a race
27
+ # small note here:
28
+ # THERE MUST BE A SPECIAL PLACE
29
+ # IN HELL FOR PEOPLE DOING THINGS LIKE THIS!!!
30
+ handler = trap(:INT, 'DEFAULT') # take previous handler
31
+ trap(:INT, handler)
32
+ t = Thread.new(handler) do |h|
33
+ x = h
34
+ while x == h do
35
+ sleep 0.1
36
+ x = trap(:INT, &h)
37
+ end
38
+ # x is sinatra wicked handler
39
+ # let's overwrite it back
40
+ trap(:INT, &h)
41
+ end
42
+ _run_custom!(options)
43
+ end
44
+
45
+ def quit_custom!
46
+ return @__quit__.call()
47
+ end
48
+
49
+ public
50
+
51
+ # sets xpflow engine
52
+ def set_engine(engine)
53
+ $__gui_engine__ = engine
54
+ end
55
+
56
+ end
57
+
58
+
59
+ class Rest
60
+
61
+ attr_reader :engine
62
+
63
+ def initialize(engine)
64
+ @engine = engine
65
+ end
66
+
67
+ def activities
68
+ ns = @engine.get_global_namespace()
69
+ return ns.each.map do |name, o|
70
+ { :name => name, :info => o.info }
71
+ end.to_a
72
+ end
73
+
74
+ def active
75
+ h = @engine.spectator.info
76
+ h2 = []
77
+ h.each_pair do |k, v|
78
+ h2.push({ :name => k, :info => v })
79
+ end
80
+ return h2
81
+ end
82
+
83
+ end
84
+
85
+
86
+ class Controller < Sinatra::Base
87
+
88
+ set :port, 8080
89
+ set :public_folder, File.join(File.dirname(__FILE__), 'gui-files')
90
+
91
+ def rest
92
+ return Rest.new($__gui_engine__)
93
+ end
94
+
95
+ def json(obj)
96
+ content_type 'application/json', :charset => 'utf-8'
97
+ return obj.to_json
98
+ end
99
+
100
+ get '/__rest__/:method' do |m|
101
+ x = rest.send(m.to_sym)
102
+ json x
103
+ end
104
+
105
+ get '/' do
106
+ erb :index
107
+ end
108
+
109
+ end
110
+
111
+ if $0 == __FILE__
112
+
113
+ require 'xpflow'
114
+
115
+ process :main do
116
+ run :whatever
117
+ run :whatever
118
+ end
119
+
120
+ activity :whatever do |x|
121
+ sleep 10
122
+ log "cze"
123
+ end
124
+
125
+ Controller.set_engine($engine)
126
+
127
+ trap(:INT) do
128
+ puts 'Shutting everything down...'
129
+ Controller.quit_custom!
130
+ end
131
+
132
+ t = Thread.new do
133
+ Controller.run_custom!
134
+ end
135
+
136
+ $engine.execute_from_argv :main
137
+
138
+ t.join
139
+
140
+ end
@@ -0,0 +1,155 @@
1
+
2
+ # this is pulled in by the main xpflow command line tool
3
+
4
+ # a standard model for an experiment
5
+
6
+ NODES_OPTS = { :doc => "Resource acquisition" }
7
+ DEPLOYMENT_OPTS = { :doc => "Deployment", :idempotent => true }
8
+ COLLECTION_OPTS = { :doc => "Collection of results" }
9
+ ANALYSIS_OPTS = { :doc => "Data analysis" }
10
+ EXPERIMENT_OPTS = { :doc => "Experiment" }
11
+ STANDARD_OPTS = { :doc => "Experiment model" }
12
+
13
+ $engine.process :__reservation__, NODES_OPTS do |nodes|
14
+ value(nodes)
15
+ end
16
+
17
+ $engine.process :__deployment__, DEPLOYMENT_OPTS do |nodes|
18
+ value(nodes)
19
+ end
20
+
21
+ $engine.process :__collection__, COLLECTION_OPTS do
22
+ debug "Collecting results from nodes..."
23
+ save_all_results
24
+ end
25
+
26
+ $engine.process :__analysis__, ANALYSIS_OPTS do |exp_result|
27
+ value(exp_result)
28
+ end
29
+
30
+ $engine.activity :__install_node__, :doc => "Install a given node", :log_level => :none do |node|
31
+ node.install()
32
+ end
33
+
34
+ $engine.process :__install_nodes__, :doc => "Initial node setup", :log_level => :none do |nodes|
35
+ foreach nodes do |node|
36
+ debug "Installing ", node
37
+ run :__install_node__, node
38
+ end
39
+ count = (length_of nodes)
40
+ on(count > 0) do
41
+ bootstrap_taktuk(nodes)
42
+ end
43
+ # TODO: more parallel and more scalable
44
+ forall nodes, :pool => 10 do |node|
45
+ debug "Bootstrapping ", node
46
+ code(node) { |node| node.bootstrap }
47
+ end
48
+
49
+ # checking nodes - run a simple command everywhere
50
+ # be idempotent - if some nodes fail, retry them
51
+
52
+ run :__check_nodes__, nodes
53
+ value(nodes)
54
+ end
55
+
56
+ $engine.process :__check_nodes__, :doc => "Checking all nodes", :log_level => :none do |nodes|
57
+ results = execute_many nodes, "true", :idempotent => true
58
+ length = length_of results
59
+ debug "All nodes (#{length}) checked"
60
+ end
61
+
62
+ $engine.activity :__fix_node_list__ do |list|
63
+ (list.nil?) ? [] : list
64
+ end
65
+
66
+ $engine.process :__standard__, STANDARD_OPTS do |node_list|
67
+
68
+ flattened_node_list = run :__fix_node_list__, node_list
69
+
70
+ nodes = cache :__reservation__ do
71
+ run :__reservation__, flattened_node_list
72
+ end
73
+
74
+ nodes_list = run :__install_nodes__, nodes
75
+
76
+ # replace __reservation__ with a new set
77
+ set_scope :__nodes__, nodes_list
78
+
79
+ deployed = cache :__deployment__ do
80
+ run :__deployment__, nodes
81
+ end
82
+
83
+ exp_result = run :__experiment__, deployed
84
+ run :__collection__
85
+ run :__analysis__, exp_result
86
+
87
+ end
88
+
89
+ # helpers
90
+
91
+ def nodes(&block)
92
+ return $engine.process(:__reservation__, NODES_OPTS, &block)
93
+ end
94
+
95
+ def deployment(name = nil, &block)
96
+ if name.nil?
97
+ return $engine.process(:__deployment__, DEPLOYMENT_OPTS, &block)
98
+ else
99
+ return $engine.process(:__deployment__, DEPLOYMENT_OPTS) { |nodes| run(name, nodes) }
100
+ end
101
+ end
102
+
103
+ def body(&block)
104
+ return $engine.process(:__experiment__, EXPERIMENT_OPTS, &block)
105
+ end
106
+
107
+ def analysis(&block)
108
+ return $engine.process(:__analysis__, ANALYSIS_OPTS, &block)
109
+ end
110
+
111
+
112
+ # importer of subexperiments
113
+ # TODO: this is rather ugly!
114
+
115
+ def with_sublibrary()
116
+ exp = nil
117
+ begin
118
+ old_engine = $engine
119
+ exp = $engine = XPFlow::BasicLibrary.new
120
+ yield
121
+ ensure
122
+ $engine = old_engine
123
+ end
124
+ return exp
125
+ end
126
+
127
+ def import(name, path = nil, opts = {})
128
+ if path.nil?
129
+ return import_file(name)
130
+ end
131
+ lib = with_sublibrary do
132
+ Kernel.load(__FILE__, true)
133
+ Kernel.load(path)
134
+ end
135
+ $engine.import_library(name, lib)
136
+ return lib
137
+ end
138
+
139
+ def library(name, &block)
140
+ lib = with_sublibrary do
141
+ Kernel.load(__FILE__, true)
142
+ block.call
143
+ end
144
+ $engine.import_library(name, lib)
145
+ return lib
146
+ end
147
+
148
+ # includes the file as-it-is
149
+ def import_file(path)
150
+ return Kernel.load(path)
151
+ end
152
+
153
+ def experiment_entry(&block)
154
+ return $engine.process(:__standard__, &block)
155
+ end