automate-em 0.0.2 → 0.0.3
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.
- 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
|