automate-em 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/LGPL3-LICENSE +165 -0
  2. data/README.textile +48 -0
  3. data/Rakefile +40 -0
  4. data/app/models/control_system.rb +20 -0
  5. data/app/models/controller_device.rb +21 -0
  6. data/app/models/controller_http_service.rb +17 -0
  7. data/app/models/controller_logic.rb +5 -0
  8. data/app/models/controller_zone.rb +10 -0
  9. data/app/models/dependency.rb +20 -0
  10. data/app/models/server.rb +12 -0
  11. data/app/models/setting.rb +38 -0
  12. data/app/models/trusted_device.rb +63 -0
  13. data/app/models/user_zone.rb +10 -0
  14. data/app/models/zone.rb +16 -0
  15. data/db/migrate/20111001022500_init.rb +147 -0
  16. data/db/migrate/20111017213801_one_time_key.rb +9 -0
  17. data/db/migrate/20111021071632_encrypt_setting.rb +9 -0
  18. data/db/migrate/20111110075444_servers.rb +15 -0
  19. data/db/migrate/20111114074538_default_port.rb +9 -0
  20. data/db/migrate/20111122073055_makebreak.rb +9 -0
  21. data/db/migrate/20111211062846_create_controller_http_services.rb +18 -0
  22. data/lib/automate-em.rb +155 -0
  23. data/lib/automate-em/constants.rb +6 -0
  24. data/lib/automate-em/core/communicator.rb +318 -0
  25. data/lib/automate-em/core/modules.rb +373 -0
  26. data/lib/automate-em/core/resolver_pool.rb +76 -0
  27. data/lib/automate-em/core/system.rb +356 -0
  28. data/lib/automate-em/device/datagram_server.rb +111 -0
  29. data/lib/automate-em/device/device.rb +140 -0
  30. data/lib/automate-em/device/device_connection.rb +689 -0
  31. data/lib/automate-em/device/tcp_control.rb +210 -0
  32. data/lib/automate-em/engine.rb +36 -0
  33. data/lib/automate-em/interfaces/OLD CODE/deferred.rb +67 -0
  34. data/lib/automate-em/interfaces/OLD CODE/telnet/ansi.rb +137 -0
  35. data/lib/automate-em/interfaces/OLD CODE/telnet/telnet.rb +137 -0
  36. data/lib/automate-em/interfaces/html5.rb +302 -0
  37. data/lib/automate-em/logic/logic.rb +76 -0
  38. data/lib/automate-em/service/http_service.rb +584 -0
  39. data/lib/automate-em/service/service.rb +48 -0
  40. data/lib/automate-em/status.rb +89 -0
  41. data/lib/automate-em/utilities.rb +195 -0
  42. data/lib/automate-em/version.rb +3 -0
  43. data/lib/generators/module/USAGE +8 -0
  44. data/lib/generators/module/module_generator.rb +47 -0
  45. data/lib/tasks/automate-em_tasks.rake +5 -0
  46. data/test/automate-em_test.rb +7 -0
  47. data/test/dummy/README.rdoc +261 -0
  48. data/test/dummy/Rakefile +7 -0
  49. data/test/dummy/app/assets/javascripts/application.js +15 -0
  50. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  51. data/test/dummy/app/controllers/application_controller.rb +3 -0
  52. data/test/dummy/app/helpers/application_helper.rb +2 -0
  53. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  54. data/test/dummy/config.ru +4 -0
  55. data/test/dummy/config/application.rb +56 -0
  56. data/test/dummy/config/boot.rb +10 -0
  57. data/test/dummy/config/database.yml +25 -0
  58. data/test/dummy/config/environment.rb +5 -0
  59. data/test/dummy/config/environments/development.rb +37 -0
  60. data/test/dummy/config/environments/production.rb +67 -0
  61. data/test/dummy/config/environments/test.rb +37 -0
  62. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  63. data/test/dummy/config/initializers/inflections.rb +15 -0
  64. data/test/dummy/config/initializers/mime_types.rb +5 -0
  65. data/test/dummy/config/initializers/secret_token.rb +7 -0
  66. data/test/dummy/config/initializers/session_store.rb +8 -0
  67. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  68. data/test/dummy/config/locales/en.yml +5 -0
  69. data/test/dummy/config/routes.rb +4 -0
  70. data/test/dummy/public/404.html +26 -0
  71. data/test/dummy/public/422.html +26 -0
  72. data/test/dummy/public/500.html +25 -0
  73. data/test/dummy/public/favicon.ico +0 -0
  74. data/test/dummy/script/rails +6 -0
  75. data/test/integration/navigation_test.rb +10 -0
  76. data/test/test_helper.rb +15 -0
  77. metadata +328 -0
@@ -0,0 +1,210 @@
1
+ require 'atomic'
2
+
3
+ module AutomateEm
4
+
5
+ class Device
6
+
7
+
8
+ #
9
+ # This is how sending works
10
+ # Send recieves data, turns a mutex on and sends the data
11
+ # -- It goes into the recieve mutex critical section and sleeps waiting for a response
12
+ # -- a timeout is used as a backup in case no response is received
13
+ # The recieve function does the following
14
+ # -- If the send lock is not active it processes the received data
15
+ # -- otherwise it notifies the send function that data is avaliable
16
+ #
17
+ class Base < EventMachine::Connection
18
+ include Utilities
19
+ include DeviceConnection
20
+
21
+ #
22
+ # EM Callbacks: --------------------------------------------------------
23
+ #
24
+ #def post_init
25
+ # return unless @parent.respond_to?(:initiate_session)
26
+ #
27
+ # begin
28
+ # @parent.initiate_session(@tls_enabled)
29
+ # rescue => e
30
+ # #
31
+ # # save from bad user code (don't want to deplete thread pool)
32
+ # #
33
+ # EM.defer do
34
+ # logger.error "-- module #{@parent.class} error whilst calling: initiate_session --"
35
+ # logger.error e.message
36
+ # logger.error e.backtrace
37
+ # end
38
+ # end
39
+ #end
40
+
41
+
42
+ def connection_completed
43
+ # set status
44
+ resume if paused?
45
+
46
+ @connect_retry = @connect_retry || Atomic.new(0)
47
+ EM.defer do
48
+ @connect_retry.value = 0
49
+ end
50
+
51
+ if !@tls_enabled
52
+ @connected = true
53
+ @connecting = false
54
+ EM.defer do
55
+ call_connected
56
+ end
57
+ else
58
+ if !@parent.respond_to?(:certificates)
59
+ start_tls
60
+ else
61
+ begin
62
+ certs = @parent.certificates
63
+ start_tls(certs)
64
+ rescue => e
65
+ EM.defer do
66
+ AutomateEm.print_error(logger, e, {
67
+ :message => "module #{@parent.class} error whilst starting TLS with certificates",
68
+ :level => Logger::ERROR
69
+ })
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ @make_occured = true
76
+ end
77
+
78
+ def ssl_handshake_completed
79
+ @connected = true
80
+ @connecting = false
81
+ EM.defer do
82
+ call_connected(get_peer_cert) # this will mark the true connection complete stage for encrypted devices
83
+ end
84
+ end
85
+
86
+
87
+ def unbind
88
+ @connected = false # set offline
89
+ @connecting = false
90
+ @disconnecting = false
91
+
92
+ if @config[:flush_buffer_on_disconnect]
93
+ process_response(@buf.flush, nil) unless @buf.nil?
94
+ else
95
+ @buf.flush unless @buf.nil? # Any incomplete from TCP stream is now invalid
96
+ end
97
+
98
+ @connect_retry = @connect_retry || Atomic.new(0)
99
+
100
+ if @config[:clear_queue_on_disconnect] || (@make_break && !@make_occured)
101
+ @send_queue.clear
102
+ end
103
+ @make_occured = false
104
+
105
+ EM.defer do
106
+ if !@shutting_down.value
107
+
108
+ @task_queue.push lambda {
109
+ @parent[:connected] = false
110
+ return unless @parent.respond_to?(:disconnected)
111
+ begin
112
+ @parent.disconnected
113
+ rescue => e
114
+ #
115
+ # save from bad user code (don't want to deplete thread pool)
116
+ #
117
+ AutomateEm.print_error(logger, e, {
118
+ :message => "module #{@parent.class} error whilst calling: disconnected",
119
+ :level => Logger::ERROR
120
+ })
121
+ end
122
+ }
123
+ end
124
+ end
125
+
126
+ if !@make_break
127
+ do_connect
128
+ elsif @send_queue.size() > 0
129
+ do_connect
130
+ end
131
+ end
132
+
133
+ def do_connect
134
+ if @disconnecting
135
+ EM.next_tick do
136
+ do_connect
137
+ end
138
+ return
139
+ end
140
+ return if @connected # possible to get here
141
+
142
+ makebreak = @make_break
143
+ @connecting = true
144
+ EM.defer do
145
+ if !@shutting_down.value
146
+ begin
147
+ settings = DeviceModule.lookup(@parent) #.reload # Don't reload here (user driven)
148
+
149
+ @connect_retry.update { |v| v += 1}
150
+
151
+ if @connect_retry.value == 1 || makebreak
152
+ res = ResolverJob.new(settings.ip)
153
+ res.callback {|ip|
154
+ reconnect ip, settings.port
155
+ }
156
+ res.errback {|error|
157
+ EM.defer do
158
+ logger.info "module #{@parent.class} in tcp_control.rb, unbind"
159
+ logger.info "Reconnect failed for #{settings.ip}:#{settings.port} - #{error.inspect}"
160
+ end
161
+ @connect_retry.value = 2
162
+ do_reconnect(settings) unless makebreak
163
+ }
164
+ else
165
+ #
166
+ # log this once if had to retry more than once
167
+ #
168
+ if @connect_retry.value == 2
169
+ logger.info "module #{@parent.class} in tcp_control.rb, unbind"
170
+ logger.info "Reconnect failed for #{settings.ip}:#{settings.port}"
171
+ end
172
+
173
+ do_reconnect(settings)
174
+ end
175
+ rescue
176
+ AutomateEm.print_error(logger, e, {
177
+ :message => "module #{@parent.class} in tcp_control.rb, unbind\nFailed to lookup settings. Device probably going offline.",
178
+ :level => Logger::FATAL
179
+ })
180
+
181
+ # Do not attempt to reconnect this device!
182
+ end
183
+ end
184
+ end
185
+ end
186
+
187
+ def do_reconnect(settings)
188
+ EM::Timer.new(5) do
189
+ if !@shutting_down.value
190
+ res = ResolverJob.new(settings.ip)
191
+ res.callback {|ip|
192
+ reconnect ip, settings.port
193
+ }
194
+ res.errback {|error|
195
+ do_reconnect(settings)
196
+ }
197
+ end
198
+ end
199
+ end
200
+
201
+ def receive_data(data)
202
+ do_receive_data(data)
203
+ end
204
+
205
+ def do_send_data(data)
206
+ send_data(data)
207
+ end
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,36 @@
1
+ module AutomateEm
2
+ class Engine < ::Rails::Engine
3
+ engine_name :automate
4
+
5
+
6
+ rake_tasks do
7
+ load "tasks/automate-em_tasks.rake"
8
+ end
9
+
10
+ #
11
+ # Define the application configuration
12
+ #
13
+ config.before_initialize do |app| # Rails.configuration
14
+ app.config.automate = ActiveSupport::OrderedOptions.new
15
+ app.config.automate.module_paths = []
16
+ app.config.automate.log_level = Logger::INFO
17
+ end
18
+
19
+ #
20
+ # Discover the possible module location paths after initialisation is complete
21
+ #
22
+ config.after_initialize do |app|
23
+
24
+ app.config.assets.paths.each do |path|
25
+ Pathname.new(path).ascend do |v|
26
+ if ['app', 'vendor'].include?(v.basename.to_s)
27
+ app.config.automate.module_paths << "#{v.to_s}/modules"
28
+ break
29
+ end
30
+ end
31
+ end
32
+
33
+ app.config.automate.module_paths.uniq!
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,67 @@
1
+
2
+
3
+ #
4
+ # This reduces load on the reactor thread.
5
+ # Use as a helper if desired
6
+ #
7
+ module Control
8
+ class Deferred < EventMachine::Connection
9
+ def initialize(*args)
10
+ super
11
+
12
+ @selected = nil
13
+ @receive_queue = Queue.new
14
+ @command_lock = Mutex.new
15
+ end
16
+
17
+ def post_init
18
+ return unless self.respond_to?(:initiate_session)
19
+ begin
20
+ self.initiate_session
21
+ rescue => e
22
+ if !@system.nil?
23
+ @system.logger.error "-- in defferred.rb, post_init : bad user code in #{self.class}.initiate_session --"
24
+ @system.logger.error e.message
25
+ @system.logger.error e.backtrace
26
+ end
27
+ end
28
+ end
29
+
30
+ def connection_completed
31
+ if self.respond_to?(:connected)
32
+ EM.defer do
33
+ begin
34
+ self.connected
35
+ rescue => e
36
+ if !@system.nil?
37
+ @system.logger.error "-- in defferred.rb, connection_completed : bad user code in #{self.class}.connected --"
38
+ @system.logger.error e.message
39
+ @system.logger.error e.backtrace
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ def unbind
47
+ @selected.disconnected(self) unless @selected.nil?
48
+ end
49
+
50
+ def receive_data(data)
51
+ @receive_queue.push(data)
52
+ EM.defer do
53
+ begin
54
+ @command_lock.synchronize {
55
+ self.received
56
+ }
57
+ rescue => e
58
+ if !@system.nil?
59
+ @system.logger.error "-- in defferred.rb, receive_data : bad user code in #{self.class}.received --"
60
+ @system.logger.error e.message
61
+ @system.logger.error e.backtrace
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,137 @@
1
+ #taken from the dorkbuster gem
2
+
3
+ module ANSI
4
+ Reset = "0"
5
+ Bright = "1"
6
+
7
+ Black = "30"
8
+ Red = "31"
9
+ Green = "32"
10
+ Yellow = "33"
11
+ Blue = "34"
12
+ Magenta = "35"
13
+ Cyan = "36"
14
+ White = "37"
15
+
16
+ BGBlack = "40"
17
+ BGRed = "41"
18
+ BGGreen = "42"
19
+ BGYellow = "43"
20
+ BGBlue = "44"
21
+ BGMagenta = "45"
22
+ BGCyan = "46"
23
+ BGWhite = "47"
24
+
25
+ Bright_Magenta = Bright+';'+BGBlack+';'+Magenta # "1;35;40"
26
+
27
+ class << self
28
+ def color(*colors)
29
+ "\033[#{colors.join(';')}m"
30
+ end
31
+
32
+ def colorize(str, start_color, end_color = Reset)
33
+ "#{color(start_color)}#{str}#{color(end_color)}"
34
+ end
35
+
36
+ def attr_is_fgcolor?(str)
37
+ str.to_i.between?(30, 37)
38
+ end
39
+
40
+ def attr_is_bgcolor?(str)
41
+ str.to_i.between?(40, 47)
42
+ end
43
+
44
+ def strip(str)
45
+ str.gsub(/\e\[[\d;]*[A-Za-z]/, "")
46
+ end
47
+
48
+ def strlen(str)
49
+ str.strip.length
50
+ end
51
+
52
+ def strclip(str, len)
53
+ out = ""
54
+ nout = 0
55
+ str.scan(/\e\[[\d;]*[A-Za-z]|[^\e]/) do |tok|
56
+ if tok[0] != ?\e
57
+ nout += 1
58
+ break if nout > len
59
+ end
60
+ out << tok
61
+ end
62
+ out
63
+ end
64
+
65
+ def strbreak(str, len)
66
+ out = []
67
+ buf = ""
68
+ nout = 0
69
+ str.scan(/\e\[[\d;]*[A-Za-z]|[^\e]/) do |tok|
70
+ if tok[0] != ?\e
71
+ nout += 1
72
+ if nout > len
73
+ out << buf
74
+ nout -= len
75
+ buf = ""
76
+ end
77
+ end
78
+ buf << tok
79
+ end
80
+ out << buf unless buf.empty?
81
+ out
82
+ end
83
+
84
+ def red(str); colorize(str, Red) end
85
+ def green(str); colorize(str, Green) end
86
+ def yellow(str); colorize(str, Yellow) end
87
+ def blue(str); colorize(str, Blue) end
88
+ def magenta(str); colorize(str, Magenta) end
89
+ def cyan(str); colorize(str, Cyan) end
90
+
91
+ def bright_magenta(str); colorize(str, Bright_Magenta) end
92
+
93
+ def set_scroll_fullscreen; "\e[r" end
94
+ def set_scroll_region(row_start, row_end); "\e[#{row_start};#{row_end}r" end
95
+
96
+ def set_cursor_pos(row, col); "\e[#{row};#{col}H" end
97
+
98
+ def cursor_left(cnt=1); "\e[#{cnt}D" end
99
+ def cursor_right(cnt=1); "\e[#{cnt}C" end
100
+ def cursor_up(cnt=1); "\e[#{cnt}A" end
101
+ def cursor_down(cnt=1); "\e[#{cnt}B" end
102
+
103
+ def save_cursor_pos; "\e[s" end
104
+ def restore_cursor_pos; "\e[u" end
105
+
106
+ def backspace_rubout(cnt=1); ("\b \b" * cnt) end
107
+
108
+ def erase_line; "\e[2K" end
109
+ def erase_eol; "\e[K" end
110
+
111
+ end
112
+ end
113
+
114
+
115
+
116
+ if $0 == __FILE__
117
+ require 'test/unit'
118
+
119
+ class TestANSI < Test::Unit::TestCase
120
+
121
+ def test_strclip
122
+ assert_equal( "ab\e[34;56mc", ANSI.strclip("ab\e[34;56mcd", 3) )
123
+ assert_equal( "ab\e[34;56mc\e[12;34r\e[H", ANSI.strclip("ab\e[34;56mc\e[12;34r\e[Hd", 3) )
124
+ assert_equal( "ab\e[34;56mc\e[12;34r\e[Hd", ANSI.strclip("ab\e[34;56mc\e[12;34r\e[Hde", 4) )
125
+ assert_equal( "ab\e[34;56mc\e[12;34r\e[Hde", ANSI.strclip("ab\e[34;56mc\e[12;34r\e[Hde", 5) )
126
+ end
127
+
128
+ def test_strbreak
129
+ assert_equal( ["ab\e[34;56mc", "d"], ANSI.strbreak("ab\e[34;56mcd", 3) )
130
+ assert_equal( ["ab\e[34;56m", "c\e[12;34r\e[Hd", "e"], ANSI.strbreak("ab\e[34;56mc\e[12;34r\e[Hde", 2) )
131
+ end
132
+
133
+ end
134
+
135
+ end
136
+
137
+