automate-em 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/app/controllers/tokens_controller.rb +1 -1
- data/app/models/dependency.rb +2 -2
- data/lib/automate-em/core/communicator.rb +12 -10
- data/lib/automate-em/core/modules.rb +60 -62
- data/lib/automate-em/core/system.rb +205 -184
- data/lib/automate-em/device/device.rb +1 -82
- data/lib/automate-em/device/device_connection.rb +59 -44
- data/lib/automate-em/device/tcp_control.rb +2 -6
- data/lib/automate-em/logic/logic.rb +1 -1
- data/lib/automate-em/module_core.rb +83 -0
- data/lib/automate-em/service/service.rb +1 -1
- data/lib/automate-em/status.rb +25 -12
- data/lib/automate-em/version.rb +1 -1
- data/lib/automate-em.rb +35 -5
- metadata +5 -4
data/app/models/dependency.rb
CHANGED
@@ -14,7 +14,7 @@ class Dependency < ActiveRecord::Base
|
|
14
14
|
protected
|
15
15
|
|
16
16
|
|
17
|
-
validates_presence_of :classname, :
|
18
|
-
validates_uniqueness_of :
|
17
|
+
validates_presence_of :classname, :module_name, :actual_name
|
18
|
+
validates_uniqueness_of :classname
|
19
19
|
validates_uniqueness_of :actual_name
|
20
20
|
end
|
@@ -56,10 +56,8 @@ class Communicator
|
|
56
56
|
|
57
57
|
if user.class == User
|
58
58
|
user.control_systems.select('control_systems.id, control_systems.name').each do |controller|
|
59
|
-
|
60
|
-
|
61
|
-
response[:names] << controller.name
|
62
|
-
end
|
59
|
+
response[:ids] << controller.id
|
60
|
+
response[:names] << controller.name
|
63
61
|
end # We ignore token requests here as they should know the system they can connect to
|
64
62
|
end
|
65
63
|
return response
|
@@ -77,11 +75,11 @@ class Communicator
|
|
77
75
|
else
|
78
76
|
sys = nil
|
79
77
|
|
80
|
-
if user.
|
81
|
-
sys = user.control_systems.select('control_systems.
|
78
|
+
if user.is_a? User
|
79
|
+
sys = user.control_systems.select('control_systems.id').where('control_systems.id = ? AND control_systems.active = ?', system.to_i, true).first
|
82
80
|
|
83
|
-
elsif user.
|
84
|
-
sys = User.find(user.user_id).control_systems.select('control_systems.
|
81
|
+
elsif user.is_a?(TrustedDevice) && user.control_system_id == system.to_i
|
82
|
+
sys = User.find(user.user_id).control_systems.select('control_systems.id, control_systems.active').where('control_systems.id = ?', system.to_i).first
|
85
83
|
if sys.nil?
|
86
84
|
#
|
87
85
|
# Kill comms, this key is not valid
|
@@ -99,7 +97,7 @@ class Communicator
|
|
99
97
|
end
|
100
98
|
end
|
101
99
|
|
102
|
-
system = sys.nil? ? nil : sys.
|
100
|
+
system = sys.nil? ? nil : sys.id
|
103
101
|
if System[system].nil?
|
104
102
|
interface.shutdown #kill comms
|
105
103
|
return nil
|
@@ -278,7 +276,11 @@ class Communicator
|
|
278
276
|
|
279
277
|
begin
|
280
278
|
@command_lock.synchronize {
|
281
|
-
@system
|
279
|
+
if @system != System
|
280
|
+
@system.modules[mod].instance.public_send(command, *args) # Not send string however call function command
|
281
|
+
else
|
282
|
+
@system.public_send(command, *args)
|
283
|
+
end
|
282
284
|
}
|
283
285
|
rescue => e
|
284
286
|
AutomateEm.print_error(logger, e, {
|
@@ -1,42 +1,50 @@
|
|
1
1
|
module AutomateEm
|
2
2
|
class Modules
|
3
3
|
@@modules = {} # modules (dependency_id => module class)
|
4
|
-
@@load_lock =
|
5
|
-
@@loading = nil
|
4
|
+
@@load_lock = Mutex.new
|
6
5
|
|
7
6
|
def self.[] (dep_id)
|
8
|
-
@@load_lock.
|
7
|
+
@@load_lock.synchronize {
|
9
8
|
@@modules[dep_id]
|
10
9
|
}
|
11
10
|
end
|
11
|
+
|
12
|
+
def self.lazy_load(dep)
|
13
|
+
theClass = Modules[dep.id]
|
14
|
+
theClass = Modules.load_module(dep) if theClass.nil?
|
15
|
+
theClass
|
16
|
+
end
|
12
17
|
|
13
18
|
def self.load_module(dep)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
begin
|
20
|
+
found = false
|
21
|
+
file = "#{dep.classname.underscore}.rb"
|
22
|
+
|
23
|
+
Rails.configuration.automate.module_paths.each do |path|
|
24
|
+
if File.exists?("#{path}/#{file}")
|
25
|
+
@@load_lock.synchronize {
|
21
26
|
load "#{path}/#{file}"
|
22
|
-
|
23
|
-
|
24
|
-
|
27
|
+
}
|
28
|
+
found = true
|
29
|
+
break
|
25
30
|
end
|
26
|
-
|
27
|
-
if not found
|
28
|
-
raise "File not found! (#{file})"
|
29
|
-
end
|
30
|
-
|
31
|
-
@@modules[dep.id] = dep.classname.constantize
|
32
|
-
rescue => e
|
33
|
-
AutomateEm.print_error(System.logger, e, {
|
34
|
-
:message => "device module #{dep.actual_name} error whilst loading",
|
35
|
-
:level => Logger::ERROR
|
36
|
-
})
|
37
31
|
end
|
38
|
-
|
39
|
-
|
32
|
+
|
33
|
+
if not found
|
34
|
+
raise "File not found! (#{file})"
|
35
|
+
end
|
36
|
+
|
37
|
+
@@load_lock.synchronize {
|
38
|
+
@@modules[dep.id] = dep.classname.constantize # this is the return value
|
39
|
+
}
|
40
|
+
rescue Exception => e
|
41
|
+
AutomateEm.print_error(System.logger, e, {
|
42
|
+
:message => "device module #{dep.actual_name} error whilst loading.",
|
43
|
+
:level => Logger::ERROR
|
44
|
+
})
|
45
|
+
|
46
|
+
return false
|
47
|
+
end
|
40
48
|
end
|
41
49
|
end
|
42
50
|
|
@@ -51,7 +59,7 @@ module AutomateEm
|
|
51
59
|
@@lookup = {} # @instance => db id array
|
52
60
|
@@lookup_lock = Mutex.new
|
53
61
|
|
54
|
-
def initialize(system, controllerDevice)
|
62
|
+
def initialize(system, controllerDevice, theModule)
|
55
63
|
@@lookup_lock.synchronize {
|
56
64
|
if @@instances[controllerDevice.id].nil?
|
57
65
|
@system = system
|
@@ -59,7 +67,7 @@ module AutomateEm
|
|
59
67
|
@@dbentry[controllerDevice.id] = controllerDevice
|
60
68
|
end
|
61
69
|
}
|
62
|
-
instantiate_module(controllerDevice)
|
70
|
+
instantiate_module(controllerDevice, theModule)
|
63
71
|
end
|
64
72
|
|
65
73
|
|
@@ -103,12 +111,7 @@ module AutomateEm
|
|
103
111
|
protected
|
104
112
|
|
105
113
|
|
106
|
-
def instantiate_module(controllerDevice)
|
107
|
-
if Modules[controllerDevice.dependency_id].nil?
|
108
|
-
Modules.load_module(controllerDevice.dependency) # This is the re-load code function (live bug fixing - removing functions does not work)
|
109
|
-
end
|
110
|
-
|
111
|
-
|
114
|
+
def instantiate_module(controllerDevice, theModule)
|
112
115
|
baselookup = "#{controllerDevice.ip}:#{controllerDevice.port}:#{controllerDevice.udp}"
|
113
116
|
|
114
117
|
@@lookup_lock.lock
|
@@ -118,7 +121,7 @@ module AutomateEm
|
|
118
121
|
# Instance of a user module
|
119
122
|
#
|
120
123
|
begin
|
121
|
-
@instance =
|
124
|
+
@instance = theModule.new(controllerDevice.tls, controllerDevice.makebreak)
|
122
125
|
@instance.join_system(@system)
|
123
126
|
@@instances[@device] = @instance
|
124
127
|
@@devices[baselookup] = @instance
|
@@ -145,9 +148,9 @@ module AutomateEm
|
|
145
148
|
end
|
146
149
|
|
147
150
|
if controllerDevice.udp
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
+
EM.schedule do
|
152
|
+
devBase.call_connected # UDP is stateless (always connected)
|
153
|
+
end
|
151
154
|
end
|
152
155
|
end
|
153
156
|
}
|
@@ -205,7 +208,7 @@ module AutomateEm
|
|
205
208
|
@@lookup = {} # @instance => db id array
|
206
209
|
@@lookup_lock = Mutex.new
|
207
210
|
|
208
|
-
def initialize(system, controllerService)
|
211
|
+
def initialize(system, controllerService, theModule)
|
209
212
|
@@lookup_lock.synchronize {
|
210
213
|
if @@instances[controllerService.id].nil?
|
211
214
|
@system = system
|
@@ -213,7 +216,7 @@ module AutomateEm
|
|
213
216
|
@@dbentry[controllerService.id] = controllerService
|
214
217
|
end
|
215
218
|
}
|
216
|
-
instantiate_module(controllerService)
|
219
|
+
instantiate_module(controllerService, theModule)
|
217
220
|
end
|
218
221
|
|
219
222
|
|
@@ -253,23 +256,21 @@ module AutomateEm
|
|
253
256
|
protected
|
254
257
|
|
255
258
|
|
256
|
-
def instantiate_module(controllerService)
|
257
|
-
if Modules[controllerService.dependency_id].nil?
|
258
|
-
Modules.load_module(controllerService.dependency) # This is the re-load code function (live bug fixing - removing functions does not work)
|
259
|
-
end
|
260
|
-
|
259
|
+
def instantiate_module(controllerService, theModule)
|
261
260
|
@@lookup_lock.lock
|
262
261
|
if @@services[controllerService.uri].nil?
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
262
|
+
begin
|
263
|
+
#
|
264
|
+
# Instance of a user module
|
265
|
+
#
|
266
|
+
@instance = theModule.new
|
267
|
+
@instance.join_system(@system)
|
268
|
+
@@instances[@service] = @instance
|
269
|
+
@@services[controllerService.uri] = @instance
|
270
|
+
@@lookup[@instance] = [@service]
|
271
|
+
ensure
|
272
|
+
@@lookup_lock.unlock #UNLOCK
|
273
|
+
end
|
273
274
|
|
274
275
|
HttpService.new(@instance, controllerService)
|
275
276
|
|
@@ -308,10 +309,10 @@ module AutomateEm
|
|
308
309
|
@@lookup_lock = Mutex.new
|
309
310
|
|
310
311
|
|
311
|
-
def initialize(system, controllerLogic)
|
312
|
+
def initialize(system, controllerLogic, theModule)
|
312
313
|
@@lookup_lock.synchronize {
|
313
314
|
if @@instances[controllerLogic.id].nil?
|
314
|
-
instantiate_module(controllerLogic, system)
|
315
|
+
instantiate_module(controllerLogic, system, theModule)
|
315
316
|
end
|
316
317
|
}
|
317
318
|
if @instance.respond_to?(:on_load)
|
@@ -368,11 +369,8 @@ module AutomateEm
|
|
368
369
|
protected
|
369
370
|
|
370
371
|
|
371
|
-
def instantiate_module(controllerLogic, system)
|
372
|
-
|
373
|
-
Modules.load_module(controllerLogic.dependency) # This is the re-load code function (live bug fixing - removing functions does not work)
|
374
|
-
end
|
375
|
-
@instance = Modules[controllerLogic.dependency_id].new(system)
|
372
|
+
def instantiate_module(controllerLogic, system, theModule)
|
373
|
+
@instance = theModule.new(system)
|
376
374
|
@@instances[controllerLogic.id] = @instance
|
377
375
|
@@lookup[@instance] = controllerLogic
|
378
376
|
end
|
@@ -1,78 +1,144 @@
|
|
1
1
|
module AutomateEm
|
2
2
|
class System
|
3
|
-
|
4
|
-
@@systems = {:'---GOD---' => self} # system_name => system instance
|
5
|
-
@@controllers = {} # controller_id => system instance
|
3
|
+
@@controllers = {0 => self} # controller_id => system instance (0 is the system class)
|
6
4
|
@@logger = nil
|
7
|
-
@@communicator = AutomateEm::Communicator.new(self)
|
5
|
+
@@communicator = AutomateEm::Communicator.new(self) # TODO:: remove the need for communicator.start
|
8
6
|
@@communicator.start(true)
|
9
7
|
@@god_lock = Mutex.new
|
10
8
|
|
11
9
|
|
12
|
-
|
10
|
+
|
11
|
+
#
|
12
|
+
# Error thrown means: mark as offline, do not retry and email
|
13
|
+
# Return false means: retry and email if a second attempt fails
|
14
|
+
# Return true means: all is good! system running
|
15
|
+
#
|
16
|
+
def self.start(controller, log_level = Logger::INFO)
|
13
17
|
begin
|
14
|
-
|
18
|
+
|
19
|
+
#
|
20
|
+
# Ensure we are dealing with a controller
|
21
|
+
#
|
22
|
+
if controller.is_a? Fixnum
|
15
23
|
controller = ControlSystem.find(controller)
|
16
|
-
elsif controller.
|
24
|
+
elsif controller.is_a? String
|
17
25
|
controller = ControlSystem.where('name = ?', controller).first
|
18
26
|
end
|
19
27
|
|
20
|
-
if controller.
|
28
|
+
if not controller.is_a? ControlSystem
|
21
29
|
raise 'invalid controller identifier'
|
22
30
|
end
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
EM.add_timer(60) do # Attempt a single restart
|
40
|
-
EM.defer do
|
41
|
-
begin
|
42
|
-
sys.start(true)
|
43
|
-
rescue => e
|
44
|
-
begin
|
45
|
-
AutomateEm.print_error(@@logger, e, {
|
46
|
-
:message => "Second start attempt failed..",
|
47
|
-
:level => Logger::ERROR
|
48
|
-
})
|
49
|
-
sys.stop
|
50
|
-
rescue
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
rescue => e
|
57
|
-
AutomateEm.print_error(@@logger, e, {
|
58
|
-
:message => "Error stopping system after problems starting..",
|
59
|
-
:level => Logger::ERROR
|
60
|
-
})
|
61
|
-
end
|
31
|
+
|
32
|
+
|
33
|
+
#
|
34
|
+
# Check if the system is already loaded or loading
|
35
|
+
#
|
36
|
+
@@god_lock.synchronize {
|
37
|
+
if @@controllers[controller.id].present?
|
38
|
+
return true
|
39
|
+
end
|
40
|
+
|
41
|
+
begin
|
42
|
+
controller.reload(:lock => true)
|
43
|
+
if controller.active
|
44
|
+
return true
|
45
|
+
else
|
46
|
+
controller.active = true
|
62
47
|
end
|
48
|
+
ensure
|
49
|
+
controller.save
|
50
|
+
end
|
51
|
+
}
|
52
|
+
|
53
|
+
#
|
54
|
+
# Create the system
|
55
|
+
#
|
56
|
+
system = System.new(controller, log_level)
|
57
|
+
|
58
|
+
#
|
59
|
+
# Load modules here (Producer)
|
60
|
+
#
|
61
|
+
proceed = Atomic.new(true)
|
62
|
+
queue = Queue.new
|
63
|
+
producer = Thread.new do # New thread here to prevent circular waits on the thread pool
|
64
|
+
begin
|
65
|
+
controller.devices.includes(:dependency).each do |device|
|
66
|
+
theClass = Modules.lazy_load(device.dependency)
|
67
|
+
raise "Load Error" if theClass == false
|
68
|
+
queue.push([device, theClass])
|
69
|
+
end
|
70
|
+
|
71
|
+
controller.services.includes(:dependency).each do |service|
|
72
|
+
theClass = Modules.lazy_load(service.dependency)
|
73
|
+
raise "Load Error" if theClass == false
|
74
|
+
queue.push([service, theClass])
|
75
|
+
end
|
76
|
+
|
77
|
+
controller.logics.includes(:dependency).each do |logic|
|
78
|
+
theClass = Modules.lazy_load(logic.dependency)
|
79
|
+
raise "Load Error" if theClass == false
|
80
|
+
queue.push([logic, theClass])
|
81
|
+
end
|
82
|
+
rescue
|
83
|
+
proceed.value = false
|
84
|
+
ensure
|
85
|
+
ActiveRecord::Base.clear_active_connections! # Clear any unused connections
|
86
|
+
queue.push(:done)
|
63
87
|
end
|
64
|
-
else
|
65
|
-
@@god_lock.unlock
|
66
88
|
end
|
89
|
+
|
90
|
+
#
|
91
|
+
# Consume the newly loaded modules here (Consumer)
|
92
|
+
#
|
93
|
+
mod = queue.pop
|
94
|
+
while mod.is_a?(Array) && proceed.value == true
|
95
|
+
begin
|
96
|
+
system.load(*mod)
|
97
|
+
|
98
|
+
mod = queue.pop
|
99
|
+
rescue => e
|
100
|
+
AutomateEm.print_error(@@logger, e, {
|
101
|
+
:message => "Error stopping system after problems starting..",
|
102
|
+
:level => Logger::ERROR
|
103
|
+
})
|
104
|
+
|
105
|
+
proceed.value = false
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
#
|
111
|
+
# Check if system modules loaded properly
|
112
|
+
#
|
113
|
+
if proceed.value == false
|
114
|
+
#
|
115
|
+
# Unload any loaded modules
|
116
|
+
#
|
117
|
+
system.stop
|
118
|
+
|
119
|
+
return false
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
#
|
124
|
+
# Setup the systems link
|
125
|
+
#
|
126
|
+
system.start # Start the systems communicator
|
127
|
+
return true
|
67
128
|
ensure
|
68
129
|
ActiveRecord::Base.clear_active_connections! # Clear any unused connections
|
69
130
|
end
|
70
131
|
end
|
71
132
|
|
72
133
|
|
134
|
+
def self.stop(system)
|
135
|
+
System[system].stop
|
136
|
+
end
|
137
|
+
|
138
|
+
|
73
139
|
#
|
74
140
|
# Reloads a dependency live
|
75
|
-
# This is the re-load code function (live bug fixing - removing
|
141
|
+
# This is the re-load code function (live bug fixing - removing / adding / modifying functions)
|
76
142
|
#
|
77
143
|
def self.reload(dep)
|
78
144
|
System.logger.info "reloading dependency: #{dep}"
|
@@ -90,6 +156,16 @@ module AutomateEm
|
|
90
156
|
end
|
91
157
|
end
|
92
158
|
|
159
|
+
updated = {}
|
160
|
+
dep.services.select('id').each do |ser|
|
161
|
+
begin
|
162
|
+
inst = ServiceModule.instance_of(ser.id)
|
163
|
+
inst.on_update if (!!!updated[inst]) && inst.respond_to?(:on_update)
|
164
|
+
ensure
|
165
|
+
updated[inst] = true
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
93
169
|
updated = {}
|
94
170
|
dep.logics.select('id').each do |log|
|
95
171
|
begin
|
@@ -109,6 +185,11 @@ module AutomateEm
|
|
109
185
|
#
|
110
186
|
def self.force_load_file(path)
|
111
187
|
load path if File.exists?(path) && File.extname(path) == '.rb'
|
188
|
+
rescue LoadError => e # load error explicitly handled
|
189
|
+
AutomateEm.print_error(System.logger, e, {
|
190
|
+
:message => "force load of #{path} failed",
|
191
|
+
:level => Logger::ERROR
|
192
|
+
})
|
112
193
|
end
|
113
194
|
|
114
195
|
|
@@ -123,36 +204,30 @@ module AutomateEm
|
|
123
204
|
@@logger = log
|
124
205
|
end
|
125
206
|
|
126
|
-
#def self.controllers
|
127
|
-
# @@controllers
|
128
|
-
#end
|
129
|
-
|
130
|
-
#def self.systems
|
131
|
-
# @@systems
|
132
|
-
#end
|
133
|
-
|
134
207
|
def self.communicator
|
135
208
|
@@communicator
|
136
209
|
end
|
137
210
|
|
138
211
|
def self.[] (system)
|
139
|
-
|
212
|
+
if system.is_a?(Symbol) || system.is_a?(String)
|
213
|
+
id = ControlSystem.where('name = ?', system.to_s).pluck(:id).first
|
214
|
+
if id.nil? && system.is_a?(String)
|
215
|
+
system = system.to_i
|
216
|
+
else
|
217
|
+
system = id
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
140
221
|
@@god_lock.synchronize {
|
141
|
-
@@
|
222
|
+
@@controllers[system]
|
142
223
|
}
|
143
224
|
end
|
144
225
|
|
145
226
|
|
146
227
|
|
147
228
|
#
|
148
|
-
# For access via communicator
|
229
|
+
# For access via communicator
|
149
230
|
#
|
150
|
-
def self.modules
|
151
|
-
self
|
152
|
-
end
|
153
|
-
def self.instance
|
154
|
-
self
|
155
|
-
end
|
156
231
|
def instance
|
157
232
|
self
|
158
233
|
end
|
@@ -174,49 +249,27 @@ module AutomateEm
|
|
174
249
|
attr_accessor :logger
|
175
250
|
|
176
251
|
|
252
|
+
#
|
253
|
+
# Loads a module into a system
|
254
|
+
#
|
255
|
+
def load(dbSetting, theClass)
|
256
|
+
if dbSetting.is_a?(ControllerDevice)
|
257
|
+
load_hooks(dbSetting, DeviceModule.new(self, dbSetting, theClass))
|
258
|
+
elsif dbSetting.is_a?(ControllerHttpService)
|
259
|
+
load_hooks(dbSetting, ServiceModule.new(self, dbSetting, theClass))
|
260
|
+
else # ControllerLogic
|
261
|
+
load_hooks(dbSetting, LogicModule.new(self, dbSetting, theClass))
|
262
|
+
end
|
263
|
+
end
|
177
264
|
|
178
265
|
#
|
179
|
-
#
|
266
|
+
# The system is ready to go
|
180
267
|
#
|
181
|
-
def start
|
182
|
-
|
183
|
-
|
184
|
-
@@god_lock.synchronize {
|
185
|
-
@@systems.delete(@controller.name.to_sym)
|
186
|
-
@controller.reload #(:lock => true)
|
187
|
-
@@systems[@controller.name.to_sym] = self
|
188
|
-
}
|
189
|
-
|
190
|
-
if !@controller.active || force
|
191
|
-
if @logger.nil?
|
192
|
-
if Rails.env.production?
|
193
|
-
@logger = Logger.new(Rails.root.join("log/system_#{@controller.id}.log").to_s, 10, 4194304)
|
194
|
-
else
|
195
|
-
@logger = Logger.new(STDOUT)
|
196
|
-
end
|
197
|
-
@logger.formatter = proc { |severity, datetime, progname, msg|
|
198
|
-
"#{datetime.strftime("%d/%m/%Y @ %I:%M%p")} #{severity}: #{@controller.name} - #{msg}\n"
|
199
|
-
}
|
200
|
-
end
|
201
|
-
|
202
|
-
@controller.devices.includes(:dependency).each do |device|
|
203
|
-
load_hooks(device, DeviceModule.new(self, device))
|
204
|
-
end
|
205
|
-
|
206
|
-
@controller.services.includes(:dependency).each do |service|
|
207
|
-
load_hooks(service, ServiceModule.new(self, service))
|
208
|
-
end
|
209
|
-
|
210
|
-
@controller.logics.includes(:dependency).each do |logic|
|
211
|
-
load_hooks(logic, LogicModule.new(self, logic))
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
@controller.active = true
|
216
|
-
@controller.save
|
217
|
-
|
218
|
-
@communicator.start
|
268
|
+
def start
|
269
|
+
@@god_lock.synchronize {
|
270
|
+
@@controllers[@controller.id] = self
|
219
271
|
}
|
272
|
+
@communicator.start
|
220
273
|
end
|
221
274
|
|
222
275
|
#
|
@@ -226,29 +279,31 @@ module AutomateEm
|
|
226
279
|
def stop
|
227
280
|
System.logger.info "stopping #{@controller.name}"
|
228
281
|
@sys_lock.synchronize {
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
282
|
+
if @controller.active
|
283
|
+
@communicator.shutdown
|
284
|
+
modules_unloaded = {}
|
285
|
+
@modules.each_value do |mod|
|
286
|
+
|
287
|
+
if modules_unloaded[mod] == nil
|
288
|
+
modules_unloaded[mod] = :unloaded
|
289
|
+
mod.unload
|
290
|
+
end
|
291
|
+
|
292
|
+
end
|
293
|
+
@modules = {} # Modules no longer referenced. Cleanup time!
|
294
|
+
@logger.close if Rails.env.production?
|
295
|
+
@logger = nil
|
296
|
+
end
|
240
297
|
|
241
298
|
@@god_lock.synchronize {
|
242
|
-
@@systems.delete(@controller.name.to_sym)
|
243
299
|
@@controllers.delete(@controller.id)
|
300
|
+
begin
|
301
|
+
@controller.reload(:lock => true)
|
302
|
+
@controller.active = false
|
303
|
+
ensure
|
304
|
+
@controller.save
|
305
|
+
end
|
244
306
|
}
|
245
|
-
|
246
|
-
begin
|
247
|
-
@controller.destroy!
|
248
|
-
rescue
|
249
|
-
# Controller may already be deleted
|
250
|
-
end
|
251
|
-
@modules = nil
|
252
307
|
}
|
253
308
|
end
|
254
309
|
|
@@ -267,43 +322,6 @@ module AutomateEm
|
|
267
322
|
|
268
323
|
|
269
324
|
protected
|
270
|
-
|
271
|
-
|
272
|
-
def stop_nolock
|
273
|
-
|
274
|
-
begin
|
275
|
-
@@god_lock.synchronize {
|
276
|
-
@@systems.delete(@controller.name.to_sym)
|
277
|
-
@controller.reload(:lock => true)
|
278
|
-
@@systems[@controller.name.to_sym] = self
|
279
|
-
}
|
280
|
-
rescue
|
281
|
-
# Assume controller may have been deleted
|
282
|
-
end
|
283
|
-
|
284
|
-
if @controller.active
|
285
|
-
@communicator.shutdown
|
286
|
-
modules_unloaded = {}
|
287
|
-
@modules.each_value do |mod|
|
288
|
-
|
289
|
-
if modules_unloaded[mod] == nil
|
290
|
-
modules_unloaded[mod] = :unloaded
|
291
|
-
mod.unload
|
292
|
-
end
|
293
|
-
|
294
|
-
end
|
295
|
-
@modules = {} # Modules no longer referenced. Cleanup time!
|
296
|
-
@logger.close if Rails.env.production?
|
297
|
-
@logger = nil
|
298
|
-
end
|
299
|
-
|
300
|
-
@controller.active = false
|
301
|
-
begin
|
302
|
-
@controller.save
|
303
|
-
rescue
|
304
|
-
# Assume controller may have been deleted
|
305
|
-
end
|
306
|
-
end
|
307
325
|
|
308
326
|
|
309
327
|
def load_hooks(device, mod)
|
@@ -315,27 +333,29 @@ module AutomateEm
|
|
315
333
|
# The first module of a type has two names (display and display_1 for example)
|
316
334
|
# Load order is controlled by the control_system model based on the ordinal
|
317
335
|
#
|
318
|
-
|
319
|
-
|
320
|
-
count
|
336
|
+
@sys_lock.synchronize {
|
337
|
+
if not @modules[module_name.to_sym].nil?
|
338
|
+
while @modules["#{module_name}_#{count}".to_sym].present?
|
339
|
+
count += 1
|
340
|
+
end
|
341
|
+
module_name = "#{module_name}_#{count}"
|
342
|
+
else
|
343
|
+
@modules["#{module_name}_1".to_sym] = mod
|
321
344
|
end
|
322
|
-
module_name =
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
if !device.custom_name.nil?
|
332
|
-
@modules[device.custom_name.to_sym] = mod
|
333
|
-
end
|
345
|
+
@modules[module_name.to_sym] = mod
|
346
|
+
|
347
|
+
#
|
348
|
+
# Allow for system specific custom names
|
349
|
+
#
|
350
|
+
if !device.custom_name.nil?
|
351
|
+
@modules[device.custom_name.to_sym] = mod
|
352
|
+
end
|
353
|
+
}
|
334
354
|
end
|
335
355
|
|
336
356
|
|
337
357
|
def initialize(controller, log_level)
|
338
|
-
|
358
|
+
System.logger.info "starting #{controller.name}"
|
339
359
|
|
340
360
|
@modules = {} # controller modules :name => module instance (device or logic)
|
341
361
|
@communicator = AutomateEm::Communicator.new(self)
|
@@ -344,12 +364,13 @@ module AutomateEm
|
|
344
364
|
@sys_lock = Mutex.new
|
345
365
|
|
346
366
|
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
367
|
+
if Rails.env.production?
|
368
|
+
@logger = Logger.new(Rails.root.join("log/system_#{@controller.id}.log").to_s, 10, 4194304)
|
369
|
+
else
|
370
|
+
@logger = Logger.new(STDOUT)
|
371
|
+
end
|
372
|
+
@logger.formatter = proc { |severity, datetime, progname, msg|
|
373
|
+
"#{datetime.strftime("%d/%m/%Y @ %I:%M%p")} #{severity}: #{@controller.name} - #{msg}\n"
|
353
374
|
}
|
354
375
|
end
|
355
376
|
end
|
@@ -1,85 +1,4 @@
|
|
1
1
|
module AutomateEm
|
2
|
-
module ModuleCore
|
3
|
-
include Status # The observable pattern (Should not be called directly)
|
4
|
-
include Constants
|
5
|
-
include Utilities
|
6
|
-
|
7
|
-
#
|
8
|
-
# Sets up a link for the user code to the eventmachine class
|
9
|
-
# This way the namespace is clean.
|
10
|
-
#
|
11
|
-
def setbase(base)
|
12
|
-
@base = base
|
13
|
-
end
|
14
|
-
|
15
|
-
|
16
|
-
def join_system(system)
|
17
|
-
@system_lock.synchronize {
|
18
|
-
@systems << system
|
19
|
-
}
|
20
|
-
end
|
21
|
-
|
22
|
-
def leave_system(system)
|
23
|
-
@system_lock.synchronize {
|
24
|
-
@systems.delete(system)
|
25
|
-
return @systems.length
|
26
|
-
}
|
27
|
-
end
|
28
|
-
|
29
|
-
def clear_active_timers
|
30
|
-
@schedule.clear_jobs unless @schedule.nil?
|
31
|
-
end
|
32
|
-
|
33
|
-
|
34
|
-
#def command_successful(result) # TODO:: needs a re-think
|
35
|
-
# @base.process_data_result(result)
|
36
|
-
#end
|
37
|
-
|
38
|
-
|
39
|
-
def logger
|
40
|
-
@system_lock.synchronize {
|
41
|
-
return @systems[0].logger unless @systems.empty?
|
42
|
-
}
|
43
|
-
System.logger
|
44
|
-
end
|
45
|
-
|
46
|
-
attr_reader :systems
|
47
|
-
attr_reader :base
|
48
|
-
|
49
|
-
|
50
|
-
protected
|
51
|
-
|
52
|
-
|
53
|
-
#
|
54
|
-
# Configuration and settings
|
55
|
-
# => TODO:: We should get all zones that the pod is in with the setting set and select the first setting (vs first zone)
|
56
|
-
#
|
57
|
-
def setting(name)
|
58
|
-
val = config.settings.where("name = ?", name.to_s).first
|
59
|
-
if val.nil?
|
60
|
-
val = config.control_system.zones.joins(:settings).where('settings.name = ?', name.to_s).first
|
61
|
-
val = val.settings.where("name = ?", name.to_s).first unless val.nil?
|
62
|
-
|
63
|
-
val = config.dependency.settings.where("name = ?", name.to_s).first if val.nil?
|
64
|
-
end
|
65
|
-
|
66
|
-
if val.present?
|
67
|
-
case val.value_type
|
68
|
-
when 0
|
69
|
-
return val.text_value
|
70
|
-
when 1
|
71
|
-
return val.integer_value
|
72
|
-
when 2
|
73
|
-
return val.float_value
|
74
|
-
when 3
|
75
|
-
return val.datetime_value
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
return nil
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
2
|
class Device
|
84
3
|
include ModuleCore
|
85
4
|
|
@@ -93,7 +12,7 @@ module AutomateEm
|
|
93
12
|
@secure_connection = tls
|
94
13
|
@makebreak_connection = makebreak
|
95
14
|
@status = {}
|
96
|
-
@status_lock =
|
15
|
+
@status_lock = Object.new.extend(MonitorMixin)
|
97
16
|
@system_lock = Mutex.new
|
98
17
|
@status_waiting = false
|
99
18
|
end
|
@@ -28,7 +28,10 @@ module AutomateEm
|
|
28
28
|
:max_buffer => 524288, # 512kb
|
29
29
|
:clear_queue_on_disconnect => false,
|
30
30
|
:flush_buffer_on_disconnect => false,
|
31
|
-
:priority_bonus => 20
|
31
|
+
:priority_bonus => 20,
|
32
|
+
:inactivity_timeout => 0 # part of make and break options
|
33
|
+
# :response_length # an alternative to response_delimiter (lower priority)
|
34
|
+
# :response_delimiter # here instead of a function call
|
32
35
|
}
|
33
36
|
|
34
37
|
|
@@ -251,10 +254,10 @@ module AutomateEm
|
|
251
254
|
def do_receive_data(data)
|
252
255
|
@last_recieve_at = Time.now.to_f
|
253
256
|
|
254
|
-
|
255
|
-
|
257
|
+
begin
|
258
|
+
if @config[:response_delimiter].present?
|
256
259
|
if @buf.nil?
|
257
|
-
del = @
|
260
|
+
del = @config[:response_delimiter]
|
258
261
|
if del.class == Array
|
259
262
|
del = array_to_str(del)
|
260
263
|
elsif del.class == Fixnum
|
@@ -263,17 +266,26 @@ module AutomateEm
|
|
263
266
|
@buf = BufferedTokenizer.new(del, @config[:max_buffer]) # Call back for character
|
264
267
|
end
|
265
268
|
data = @buf.extract(data)
|
266
|
-
|
267
|
-
@buf
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
269
|
+
elsif @config[:response_length].present?
|
270
|
+
(@buf ||= "") << data
|
271
|
+
data = @buf.scan(/.{1,#{@config[:response_length]}}/)
|
272
|
+
if data[-1].length == @config[:response_length]
|
273
|
+
@buf = nil
|
274
|
+
else
|
275
|
+
@buf = data[-1]
|
276
|
+
data = data[0..-2]
|
273
277
|
end
|
278
|
+
else
|
274
279
|
data = [data]
|
275
280
|
end
|
276
|
-
|
281
|
+
rescue => e
|
282
|
+
@buf = nil # clear the buffer
|
283
|
+
EM.defer do # Error in a thread
|
284
|
+
AutomateEm.print_error(logger, e, {
|
285
|
+
:message => "module #{@parent.class} error whilst setting delimiter",
|
286
|
+
:level => Logger::ERROR
|
287
|
+
})
|
288
|
+
end
|
277
289
|
data = [data]
|
278
290
|
end
|
279
291
|
|
@@ -297,7 +309,7 @@ module AutomateEm
|
|
297
309
|
|
298
310
|
|
299
311
|
#
|
300
|
-
#
|
312
|
+
# Called from receive
|
301
313
|
#
|
302
314
|
def process_response(response, command)
|
303
315
|
EM.defer do
|
@@ -438,7 +450,7 @@ module AutomateEm
|
|
438
450
|
end
|
439
451
|
|
440
452
|
def process_response_complete
|
441
|
-
if (@make_break && @send_queue.empty?) || @command[:force_disconnect]
|
453
|
+
if (@make_break && @config[:inactivity_timeout] == 0 && @send_queue.empty?) || @command[:force_disconnect]
|
442
454
|
if @connected
|
443
455
|
close_connection_after_writing
|
444
456
|
@disconnecting = true
|
@@ -483,7 +495,7 @@ module AutomateEm
|
|
483
495
|
#
|
484
496
|
# Make sure we are sending appropriately formatted data
|
485
497
|
#
|
486
|
-
if data.
|
498
|
+
if data.is_a?(Array)
|
487
499
|
data = array_to_str(data)
|
488
500
|
elsif options[:hex_string] == true
|
489
501
|
data = hex_to_byte(data)
|
@@ -591,42 +603,45 @@ module AutomateEm
|
|
591
603
|
#
|
592
604
|
# Connection state
|
593
605
|
#
|
594
|
-
def call_connected(*args)
|
606
|
+
def call_connected(*args)
|
595
607
|
#
|
596
608
|
# NOTE:: Same as add parent in device module!!!
|
597
609
|
# TODO:: Should break into a module and include it
|
598
610
|
#
|
611
|
+
set_comm_inactivity_timeout(@config[:inactivity_timeout])
|
599
612
|
@task_queue.push lambda {
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
@
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
# save from bad user code (don't want to deplete thread pool)
|
609
|
-
#
|
610
|
-
AutomateEm.print_error(logger, e, {
|
611
|
-
:message => "module #{@parent.class} error whilst calling: connect",
|
612
|
-
:level => Logger::ERROR
|
613
|
-
})
|
614
|
-
ensure
|
615
|
-
EM.schedule do
|
613
|
+
EM.defer do
|
614
|
+
@parent[:connected] = true
|
615
|
+
|
616
|
+
begin
|
617
|
+
@send_monitor.mon_synchronize { # Any sends in here are high priority (no emits as this function must return)
|
618
|
+
@parent.connected(*args) if @parent.respond_to?(:connected)
|
619
|
+
}
|
620
|
+
rescue => e
|
616
621
|
#
|
617
|
-
#
|
622
|
+
# save from bad user code (don't want to deplete thread pool)
|
618
623
|
#
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
624
|
+
AutomateEm.print_error(logger, e, {
|
625
|
+
:message => "module #{@parent.class} error whilst calling: connect",
|
626
|
+
:level => Logger::ERROR
|
627
|
+
})
|
628
|
+
ensure
|
629
|
+
EM.schedule do
|
630
|
+
#
|
631
|
+
# First connect if no commands pushed then we disconnect asap
|
632
|
+
#
|
633
|
+
if @make_break && @first_connect && @send_queue.size == 0
|
634
|
+
close_connection_after_writing
|
635
|
+
@disconnecting = true
|
636
|
+
@com_paused = true
|
637
|
+
@first_connect = false
|
638
|
+
elsif @com_paused
|
639
|
+
@com_paused = false
|
640
|
+
@wait_queue.push(nil)
|
641
|
+
else
|
642
|
+
EM.defer do
|
643
|
+
logger.info "Reconnected, communications not paused."
|
644
|
+
end
|
630
645
|
end
|
631
646
|
end
|
632
647
|
end
|
@@ -51,9 +51,7 @@ module AutomateEm
|
|
51
51
|
if !@tls_enabled
|
52
52
|
@connected = true
|
53
53
|
@connecting = false
|
54
|
-
|
55
|
-
call_connected
|
56
|
-
end
|
54
|
+
call_connected
|
57
55
|
else
|
58
56
|
if !@parent.respond_to?(:certificates)
|
59
57
|
start_tls
|
@@ -78,9 +76,7 @@ module AutomateEm
|
|
78
76
|
def ssl_handshake_completed
|
79
77
|
@connected = true
|
80
78
|
@connecting = false
|
81
|
-
|
82
|
-
call_connected(get_peer_cert) # this will mark the true connection complete stage for encrypted devices
|
83
|
-
end
|
79
|
+
call_connected(get_peer_cert) # this will mark the true connection complete stage for encrypted devices
|
84
80
|
end
|
85
81
|
|
86
82
|
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module AutomateEm
|
2
|
+
module ModuleCore
|
3
|
+
include Status # The observable pattern (Should not be called directly)
|
4
|
+
include Constants
|
5
|
+
include Utilities
|
6
|
+
|
7
|
+
#
|
8
|
+
# Sets up a link for the user code to the eventmachine class
|
9
|
+
# This way the namespace is clean.
|
10
|
+
#
|
11
|
+
def setbase(base)
|
12
|
+
@base = base
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def join_system(system)
|
17
|
+
@system_lock.synchronize {
|
18
|
+
@systems << system
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def leave_system(system)
|
23
|
+
@system_lock.synchronize {
|
24
|
+
@systems.delete(system)
|
25
|
+
return @systems.length
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def clear_active_timers
|
30
|
+
@schedule.clear_jobs unless @schedule.nil?
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
#def command_successful(result) # TODO:: needs a re-think
|
35
|
+
# @base.process_data_result(result)
|
36
|
+
#end
|
37
|
+
|
38
|
+
|
39
|
+
def logger
|
40
|
+
@system_lock.synchronize {
|
41
|
+
return @systems[0].logger unless @systems.empty?
|
42
|
+
}
|
43
|
+
System.logger
|
44
|
+
end
|
45
|
+
|
46
|
+
attr_reader :systems
|
47
|
+
attr_reader :base
|
48
|
+
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
|
53
|
+
#
|
54
|
+
# Configuration and settings
|
55
|
+
# => Get all zones that the pod is in with the setting set and select the first setting
|
56
|
+
# => TODO:: Replace this with NoSQL
|
57
|
+
#
|
58
|
+
def setting(name)
|
59
|
+
val = config.settings.where("name = ?", name.to_s).first
|
60
|
+
if val.nil?
|
61
|
+
val = config.control_system.zones.joins(:settings).where('settings.name = ?', name.to_s).first
|
62
|
+
val = val.settings.where("name = ?", name.to_s).first unless val.nil?
|
63
|
+
|
64
|
+
val = config.dependency.settings.where("name = ?", name.to_s).first if val.nil?
|
65
|
+
end
|
66
|
+
|
67
|
+
if val.present?
|
68
|
+
case val.value_type
|
69
|
+
when 0
|
70
|
+
return val.text_value
|
71
|
+
when 1
|
72
|
+
return val.integer_value
|
73
|
+
when 2
|
74
|
+
return val.float_value
|
75
|
+
when 3
|
76
|
+
return val.datetime_value
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
return nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/lib/automate-em/status.rb
CHANGED
@@ -6,35 +6,48 @@ module AutomateEm
|
|
6
6
|
|
7
7
|
def [] (status)
|
8
8
|
status = status.to_sym if status.class == String
|
9
|
-
@status_lock.
|
9
|
+
@status_lock.mon_synchronize {
|
10
10
|
return @status[status]
|
11
11
|
}
|
12
12
|
end
|
13
13
|
|
14
14
|
def []= (status, data)
|
15
15
|
status = status.to_sym if status.class == String
|
16
|
-
old_data = check_for_emit(status, data)
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
17
|
+
@status_lock.mon_synchronize {
|
18
|
+
old_data = check_for_emit(status, data)
|
19
|
+
|
20
|
+
if data != old_data
|
21
|
+
changed # so that the notify is applied
|
22
|
+
logger.debug "#{self.class} status updated: #{status} = #{data}"
|
23
|
+
end
|
24
|
+
|
25
|
+
notify_observers(self, status, data) # only notify changes
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def update_status(status, &block)
|
30
|
+
status = status.to_sym if status.class == String
|
31
|
+
@status_lock.mon_synchronize {
|
32
|
+
data = @status[status]
|
33
|
+
data = data.clone unless data.nil?
|
34
|
+
newValue = block.call(data)
|
35
|
+
self[status] = newValue
|
36
|
+
return @status[status]
|
37
|
+
}
|
25
38
|
end
|
26
39
|
|
27
40
|
attr_reader :status # Should not be accessed like this for modification
|
28
41
|
|
29
42
|
|
30
43
|
def mark_emit_start(status)
|
31
|
-
@status_lock.
|
44
|
+
@status_lock.mon_synchronize {
|
32
45
|
@emit_hasnt_occured = status
|
33
46
|
}
|
34
47
|
end
|
35
48
|
|
36
49
|
def mark_emit_end
|
37
|
-
@status_lock.
|
50
|
+
@status_lock.mon_synchronize {
|
38
51
|
@emit_hasnt_occured.each_pair do | key, block |
|
39
52
|
data = @status[key]
|
40
53
|
task do
|
@@ -56,7 +69,7 @@ module AutomateEm
|
|
56
69
|
|
57
70
|
|
58
71
|
def check_for_emit(status, data)
|
59
|
-
@status_lock.
|
72
|
+
@status_lock.mon_synchronize {
|
60
73
|
old_data = @status[status]
|
61
74
|
@status[status] = data
|
62
75
|
|
data/lib/automate-em/version.rb
CHANGED
data/lib/automate-em.rb
CHANGED
@@ -32,6 +32,7 @@ require 'ipaddress'
|
|
32
32
|
require 'automate-em/constants.rb'
|
33
33
|
require 'automate-em/utilities.rb'
|
34
34
|
require 'automate-em/status.rb'
|
35
|
+
require 'automate-em/module_core.rb'
|
35
36
|
|
36
37
|
require 'automate-em/core/resolver_pool.rb'
|
37
38
|
require 'automate-em/core/modules.rb'
|
@@ -122,17 +123,46 @@ module AutomateEm
|
|
122
123
|
#
|
123
124
|
# Load the system based on the database
|
124
125
|
#
|
125
|
-
ControlSystem.
|
126
|
+
ControlSystem.update_all(:active => false)
|
127
|
+
ControlSystem.find_each do |controller|
|
126
128
|
EM.defer do
|
127
129
|
begin
|
128
130
|
System.logger.debug "Booting #{controller.name}"
|
129
|
-
System.
|
131
|
+
result = System.start(controller, Rails.configuration.automate.log_level)
|
132
|
+
if result == false
|
133
|
+
#
|
134
|
+
# TODO:: we need a class for handling failed starts
|
135
|
+
#
|
136
|
+
AutomateEm.print_error(AutomateEm::System.logger, e, {
|
137
|
+
:message => "System #{controller.name} failed to start (gracefully). It is now offline",
|
138
|
+
:level => Logger::WARN
|
139
|
+
})
|
140
|
+
controller.active = false
|
141
|
+
controller.save
|
142
|
+
@@scheduler.in '5m' do
|
143
|
+
System.start(controller, Rails.configuration.automate.log_level)
|
144
|
+
end
|
145
|
+
end
|
130
146
|
rescue => e
|
131
147
|
AutomateEm.print_error(AutomateEm::System.logger, e, {
|
132
|
-
:message => "
|
133
|
-
:level => Logger::
|
148
|
+
:message => "System #{controller.name} threw an error whilst starting. It is now offline",
|
149
|
+
:level => Logger::WARN
|
134
150
|
})
|
135
|
-
|
151
|
+
#
|
152
|
+
# Mark as offline, do not retry and email
|
153
|
+
#
|
154
|
+
begin
|
155
|
+
controller.active = false
|
156
|
+
controller.save
|
157
|
+
#
|
158
|
+
# TODO:: email admin about failure
|
159
|
+
#
|
160
|
+
rescue => e
|
161
|
+
AutomateEm.print_error(AutomateEm::System.logger, e, {
|
162
|
+
:message => "Error marking system as offline",
|
163
|
+
:level => Logger::ERROR
|
164
|
+
})
|
165
|
+
end
|
136
166
|
end
|
137
167
|
end
|
138
168
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: automate-em
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-06-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -34,7 +34,7 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - ! '>='
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version: 1.0.0.beta.
|
37
|
+
version: 1.0.0.beta.4.1
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,7 +42,7 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: 1.0.0.beta.
|
45
|
+
version: 1.0.0.beta.4.1
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: em-priority-queue
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -230,6 +230,7 @@ files:
|
|
230
230
|
- lib/automate-em/interfaces/OLD CODE/telnet/ansi.rb
|
231
231
|
- lib/automate-em/interfaces/OLD CODE/telnet/telnet.rb
|
232
232
|
- lib/automate-em/logic/logic.rb
|
233
|
+
- lib/automate-em/module_core.rb
|
233
234
|
- lib/automate-em/service/http_service.rb
|
234
235
|
- lib/automate-em/service/service.rb
|
235
236
|
- lib/automate-em/status.rb
|