isono 0.1.0

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 (43) hide show
  1. data/LICENSE +202 -0
  2. data/NOTICE +2 -0
  3. data/bin/cli +122 -0
  4. data/isono.gemspec +47 -0
  5. data/lib/ext/shellwords.rb +172 -0
  6. data/lib/isono.rb +61 -0
  7. data/lib/isono/amqp_client.rb +169 -0
  8. data/lib/isono/daemonize.rb +96 -0
  9. data/lib/isono/event_delegate_context.rb +56 -0
  10. data/lib/isono/event_observable.rb +86 -0
  11. data/lib/isono/logger.rb +48 -0
  12. data/lib/isono/manifest.rb +161 -0
  13. data/lib/isono/messaging_client.rb +116 -0
  14. data/lib/isono/models/event_log.rb +28 -0
  15. data/lib/isono/models/job_state.rb +35 -0
  16. data/lib/isono/models/node_state.rb +70 -0
  17. data/lib/isono/models/resource_instance.rb +35 -0
  18. data/lib/isono/node.rb +158 -0
  19. data/lib/isono/node_modules/base.rb +65 -0
  20. data/lib/isono/node_modules/data_store.rb +57 -0
  21. data/lib/isono/node_modules/event_channel.rb +72 -0
  22. data/lib/isono/node_modules/event_logger.rb +39 -0
  23. data/lib/isono/node_modules/job_channel.rb +86 -0
  24. data/lib/isono/node_modules/job_collector.rb +47 -0
  25. data/lib/isono/node_modules/job_worker.rb +152 -0
  26. data/lib/isono/node_modules/node_collector.rb +87 -0
  27. data/lib/isono/node_modules/node_heartbeat.rb +26 -0
  28. data/lib/isono/node_modules/rpc_channel.rb +482 -0
  29. data/lib/isono/rack.rb +67 -0
  30. data/lib/isono/rack/builder.rb +40 -0
  31. data/lib/isono/rack/data_store.rb +20 -0
  32. data/lib/isono/rack/job.rb +74 -0
  33. data/lib/isono/rack/map.rb +56 -0
  34. data/lib/isono/rack/object_method.rb +20 -0
  35. data/lib/isono/rack/proc.rb +50 -0
  36. data/lib/isono/rack/thread_pass.rb +22 -0
  37. data/lib/isono/resource_manifest.rb +273 -0
  38. data/lib/isono/runner/agent.rb +89 -0
  39. data/lib/isono/runner/rpc_server.rb +198 -0
  40. data/lib/isono/serializer.rb +43 -0
  41. data/lib/isono/thread_pool.rb +169 -0
  42. data/lib/isono/util.rb +212 -0
  43. metadata +185 -0
@@ -0,0 +1,212 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'digest/sha1'
4
+ require 'hmac-sha1'
5
+ require 'thread'
6
+ require 'stringio'
7
+
8
+ require 'shellwords'
9
+ unless Shellwords.respond_to? :shellescape
10
+ require 'ext/shellwords'
11
+ end
12
+
13
+ require 'eventmachine'
14
+
15
+ module Isono
16
+ module Util
17
+
18
+ ##
19
+ # Convert to snake case.
20
+ #
21
+ # "FooBar".snake_case #=> "foo_bar"
22
+ # "HeadlineCNNNews".snake_case #=> "headline_cnn_news"
23
+ # "CNN".snake_case #=> "cnn"
24
+ #
25
+ # @return [String] Receiver converted to snake case.
26
+ #
27
+ # @api public
28
+ def snake_case(str)
29
+ return str.downcase if str.match(/\A[A-Z]+\z/)
30
+ str.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
31
+ gsub(/([a-z])([A-Z])/, '\1_\2').
32
+ downcase
33
+ end
34
+ module_function :snake_case
35
+
36
+ def gen_id(str=nil)
37
+ Digest::SHA1.hexdigest( (str.nil? ? rand.to_s : str) )
38
+ end
39
+ module_function :gen_id
40
+
41
+ # Return the IP address assigned to default gw interface
42
+ def default_gw_ipaddr
43
+ ip = case `/bin/uname -s`.rstrip
44
+ when 'Linux'
45
+ `/sbin/ip route get 8.8.8.8`.split("\n")[0].split.last
46
+ when 'SunOS'
47
+ `/sbin/ifconfig $(route get 1.1.1.1 | awk '$1 == "interface:" {print $2}') | awk '$1 == "inet" { print $2 }'`
48
+ else
49
+ raise "Unsupported platform to detect gateway IP address: #{`/bin/uname`}"
50
+ end
51
+ ip = ip.rstrip
52
+ raise "Failed to run command lines or empty result" if ip == '' || $?.exitstatus != 0
53
+ ip
54
+ end
55
+ module_function :default_gw_ipaddr
56
+
57
+ def quote_args(cmd_str, args=[], quote_char='\'')
58
+ quote_helper =
59
+ if quote_char
60
+ proc { |a|
61
+ [quote_char, Shellwords.shellescape(a), quote_char].join
62
+ }
63
+ else
64
+ proc { |a|
65
+ Shellwords.shellescape(a)
66
+ }
67
+ end
68
+ sprintf(cmd_str, *args.map {|a| quote_helper.call(a) })
69
+ end
70
+ module_function :quote_args
71
+
72
+ # system('/bin/ls')
73
+ # second arg gives
74
+ # system('/bin/ls %s', ['/home'])
75
+ def system(cmd_str, args=[], opts={})
76
+ unless EventMachine.reactor_running?
77
+ raise "has to prepare EventMachine context"
78
+ end
79
+
80
+ cmd = quote_args(cmd_str, args, (opts[:quote_char] || '\''))
81
+
82
+ capture_io = opts[:io] || StringIO.new
83
+ stdin_buf = opts[:stdin_input]
84
+
85
+ evmsg = {:cmd => cmd}
86
+ wait_q = ::Queue.new
87
+ if opts[:timeout] && opts[:timeout].to_f > 0.0
88
+ EventMachine.add_timer(opts[:timeout].to_f) {
89
+ wait_q.enq(RuntimeError.new("timeout child process wait: #{opts[:timeout].to_f} sec(s)"))
90
+ }
91
+ evmsg[:timeout] = opts[:timeout].to_f
92
+ end
93
+ popenobj = EventMachine.popen(cmd, EmSystemCb, capture_io, stdin_buf, proc { |exit_stat|
94
+ wait_q.enq(exit_stat)
95
+ })
96
+ pid = EventMachine.get_subprocess_pid(popenobj.signature)
97
+ evmsg[:pid] = pid
98
+ if self.respond_to? :logger
99
+ logger.debug("Exec command (pid=#{pid}): #{cmd}")
100
+ end
101
+
102
+ stat = wait_q.deq
103
+ evmsg = {}
104
+
105
+ case stat
106
+ when Process::Status
107
+ evmsg[:exit_code] = stat.exitstatus
108
+ if stat.exited? && stat.exitstatus == 0
109
+ else
110
+ raise "Unexpected status from child: #{stat}"
111
+ end
112
+ when Exception
113
+ raise stat
114
+ else
115
+ raise "Unknown signal from child: #{stat}"
116
+ end
117
+
118
+ end
119
+ module_function :system
120
+
121
+ class EmSystemCb < EventMachine::Connection
122
+ def initialize(io, in_buf, exit_cb)
123
+ @io = io
124
+ @in_buf = in_buf
125
+ @exit_cb = exit_cb
126
+ end
127
+
128
+ def post_init
129
+ # send data to stdin for child process
130
+ if @in_buf
131
+ send_data @in_buf
132
+ end
133
+ end
134
+
135
+ def receive_data data
136
+ @io.write(data)
137
+ end
138
+
139
+ def unbind()
140
+ @exit_cb.call(get_status)
141
+ end
142
+ end
143
+
144
+ # return ruby binary path which is expected to be used in
145
+ # the current environment.
146
+ def ruby_bin_path
147
+ #config_section.ruby_bin_path || ENV['_'] =~ /ruby/ ||
148
+ require 'rbconfig'
149
+ File.expand_path(Config::CONFIG['RUBY_INSTALL_NAME'], Config::CONFIG['bindir'])
150
+ end
151
+ module_function :ruby_bin_path
152
+
153
+ # A utility class to interact success/error message with two different threads.
154
+ # dm = DeferedMsg.new
155
+ # EM.schedule {
156
+ # if condition
157
+ # dm.success
158
+ # else
159
+ # dm.error(RuntimeError.new("fail"))
160
+ # end
161
+ #
162
+ # dm.wait rescue abort("got failure")
163
+ # }
164
+ # # will raise RuntimeError in case of error().
165
+ # dm.wait unless EM.reactor_thread?
166
+ #
167
+ class DeferedMsg < ::Queue
168
+ class TimeoutError < StandardError; end
169
+
170
+ def initialize(timeout=60*15, th=Thread.current)
171
+ super()
172
+ @thread_wait = th
173
+ @timer_sig = EventMachine.add_timer(timeout) {
174
+ error(TimeoutError.new)
175
+ }
176
+ end
177
+
178
+ def success(returnval=true)
179
+ self.enq(returnval)
180
+ @thread_called = Thread.current
181
+ end
182
+
183
+
184
+ def error(ex)
185
+ raise TypeError unless ex.is_a?(Exception)
186
+ self.enq(ex)
187
+ @thread_called = Thread.current
188
+ end
189
+
190
+ def wait
191
+ if (@thread_called == @thread_wait || @thread_called == Thread.current ) &&
192
+ self.empty?
193
+ raise "do success() or error() prior to calling wait()"
194
+ end
195
+
196
+ ret = self.deq()
197
+ # requeue the message to distribute to another wait().
198
+ self.enq(ret)
199
+ if ret.is_a?(Exception)
200
+ raise ret
201
+ else
202
+ return ret
203
+ end
204
+ ensure
205
+ @thread_wait = nil
206
+ EventMachine.cancel_timer(@timer_sig) rescue nil
207
+ end
208
+ end
209
+
210
+ end
211
+ end
212
+
metadata ADDED
@@ -0,0 +1,185 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: isono
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - axsh Ltd.
13
+ - Masahiro Fujiwara
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-18 00:00:00 +09:00
19
+ default_executable: cli
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: amqp
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ - 6
31
+ - 7
32
+ version: 0.6.7
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: eventmachine
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 0
44
+ - 12
45
+ - 10
46
+ version: 0.12.10
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: statemachine
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 1
58
+ - 0
59
+ - 0
60
+ version: 1.0.0
61
+ type: :runtime
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: log4r
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ type: :runtime
74
+ version_requirements: *id004
75
+ - !ruby/object:Gem::Dependency
76
+ name: bacon
77
+ prerelease: false
78
+ requirement: &id005 !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ segments:
83
+ - 0
84
+ version: "0"
85
+ type: :development
86
+ version_requirements: *id005
87
+ - !ruby/object:Gem::Dependency
88
+ name: rake
89
+ prerelease: false
90
+ requirement: &id006 !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ segments:
95
+ - 0
96
+ version: "0"
97
+ type: :development
98
+ version_requirements: *id006
99
+ description:
100
+ email:
101
+ - dev@axsh.net
102
+ - m-fujiwara@axsh.net
103
+ executables:
104
+ - cli
105
+ extensions: []
106
+
107
+ extra_rdoc_files: []
108
+
109
+ files:
110
+ - bin/cli
111
+ - lib/ext/shellwords.rb
112
+ - lib/isono.rb
113
+ - lib/isono/rack/object_method.rb
114
+ - lib/isono/rack/proc.rb
115
+ - lib/isono/rack/data_store.rb
116
+ - lib/isono/rack/map.rb
117
+ - lib/isono/rack/job.rb
118
+ - lib/isono/rack/builder.rb
119
+ - lib/isono/rack/thread_pass.rb
120
+ - lib/isono/logger.rb
121
+ - lib/isono/rack.rb
122
+ - lib/isono/messaging_client.rb
123
+ - lib/isono/resource_manifest.rb
124
+ - lib/isono/node.rb
125
+ - lib/isono/manifest.rb
126
+ - lib/isono/event_delegate_context.rb
127
+ - lib/isono/amqp_client.rb
128
+ - lib/isono/node_modules/job_channel.rb
129
+ - lib/isono/node_modules/base.rb
130
+ - lib/isono/node_modules/event_logger.rb
131
+ - lib/isono/node_modules/event_channel.rb
132
+ - lib/isono/node_modules/node_heartbeat.rb
133
+ - lib/isono/node_modules/node_collector.rb
134
+ - lib/isono/node_modules/data_store.rb
135
+ - lib/isono/node_modules/job_collector.rb
136
+ - lib/isono/node_modules/rpc_channel.rb
137
+ - lib/isono/node_modules/job_worker.rb
138
+ - lib/isono/serializer.rb
139
+ - lib/isono/models/node_state.rb
140
+ - lib/isono/models/resource_instance.rb
141
+ - lib/isono/models/event_log.rb
142
+ - lib/isono/models/job_state.rb
143
+ - lib/isono/daemonize.rb
144
+ - lib/isono/util.rb
145
+ - lib/isono/thread_pool.rb
146
+ - lib/isono/runner/rpc_server.rb
147
+ - lib/isono/runner/agent.rb
148
+ - lib/isono/event_observable.rb
149
+ - isono.gemspec
150
+ - LICENSE
151
+ - NOTICE
152
+ has_rdoc: true
153
+ homepage: http://github.com/axsh/isono
154
+ licenses: []
155
+
156
+ post_install_message:
157
+ rdoc_options: []
158
+
159
+ require_paths:
160
+ - lib
161
+ required_ruby_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ segments:
166
+ - 1
167
+ - 8
168
+ - 7
169
+ version: 1.8.7
170
+ required_rubygems_version: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ segments:
175
+ - 0
176
+ version: "0"
177
+ requirements: []
178
+
179
+ rubyforge_project:
180
+ rubygems_version: 1.3.6
181
+ signing_key:
182
+ specification_version: 3
183
+ summary: Messageing and agent fabric
184
+ test_files: []
185
+