nutella_framework 0.4.18 → 0.4.19
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.
- checksums.yaml +4 -4
- data/Gemfile +2 -1
- data/README.md +1 -1
- data/VERSION +1 -1
- data/framework_components/beacon-cloud-interface/js/lib/nutella_lib.js +1095 -13
- data/framework_components/monitoring-bot/.gitignore +34 -0
- data/framework_components/monitoring-bot/README.md +1 -0
- data/framework_components/monitoring-bot/monitoring-bot.rb +476 -0
- data/framework_components/monitoring-bot/nutella.json +6 -0
- data/framework_components/monitoring-bot/startup +6 -0
- data/lib/commands/checkup.rb +8 -2
- data/lib/commands/start.rb +2 -0
- data/lib/commands/stop.rb +7 -0
- data/lib/commands/util/components_starter.rb +36 -0
- data/nutella_framework.gemspec +14 -3
- data/nutella_lib/framework_net.rb +38 -2
- metadata +41 -2
@@ -0,0 +1,34 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/test/tmp/
|
9
|
+
/test/version_tmp/
|
10
|
+
/tmp/
|
11
|
+
|
12
|
+
## Specific to RubyMotion:
|
13
|
+
.dat*
|
14
|
+
.repl_history
|
15
|
+
build/
|
16
|
+
|
17
|
+
## Documentation cache and generated files:
|
18
|
+
/.yardoc/
|
19
|
+
/_yardoc/
|
20
|
+
/doc/
|
21
|
+
/rdoc/
|
22
|
+
|
23
|
+
## Environment normalisation:
|
24
|
+
/.bundle/
|
25
|
+
/lib/bundler/man/
|
26
|
+
|
27
|
+
# for a library or gem, you might want to ignore these files since the code is
|
28
|
+
# intended to run in multiple environments; otherwise, check them in:
|
29
|
+
# Gemfile.lock
|
30
|
+
# .ruby-version
|
31
|
+
# .ruby-gemset
|
32
|
+
|
33
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
34
|
+
.rvmrc
|
@@ -0,0 +1 @@
|
|
1
|
+
# monitoring-bot
|
@@ -0,0 +1,476 @@
|
|
1
|
+
require_relative '../../lib/config/runlist'
|
2
|
+
require_relative '../../lib/config/config'
|
3
|
+
require_relative '../../nutella_lib/framework_core'
|
4
|
+
require_relative '../../lib/commands/util/components_list'
|
5
|
+
require 'active_support/core_ext/object/deep_dup'
|
6
|
+
require 'mandrill'
|
7
|
+
require 'mongo'
|
8
|
+
|
9
|
+
# Framework bots can access all the parameters they need directly
|
10
|
+
# from the configuration file and the runlist,
|
11
|
+
# to which they have full access to.
|
12
|
+
|
13
|
+
# Access the config file like so:
|
14
|
+
# Nutella.config['broker']
|
15
|
+
|
16
|
+
# Access the runs list like so:
|
17
|
+
# Nutella.runlist.all_runs
|
18
|
+
|
19
|
+
|
20
|
+
# Initialize this bot as framework component
|
21
|
+
nutella.f.init(Nutella.config['broker'], 'monitoring_bot')
|
22
|
+
|
23
|
+
# Mandrill access key
|
24
|
+
$m = Mandrill::API.new 'i4frQYcTBMyZ6bYyLkEVOQ'
|
25
|
+
|
26
|
+
# Open the resources database
|
27
|
+
$messages = nutella.f.persist.get_json_object_store('messages')
|
28
|
+
|
29
|
+
# Application structure
|
30
|
+
$applications = {}
|
31
|
+
|
32
|
+
# MongoDB client
|
33
|
+
Mongo::Logger.logger.level = ::Logger::INFO
|
34
|
+
client = Mongo::Client.new([Nutella.config['broker']], :database => 'nutella')
|
35
|
+
|
36
|
+
puts 'Monitoring bot initialization'
|
37
|
+
|
38
|
+
def send_subscription_mail(mail, application, instance = nil, component = nil)
|
39
|
+
object = application
|
40
|
+
|
41
|
+
if instance != nil
|
42
|
+
object = object + ' > ' + instance
|
43
|
+
if rcomponent != nil
|
44
|
+
object = object + ' > ' + component
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
puts "Send mail to " + mail + "message: " + object
|
49
|
+
|
50
|
+
|
51
|
+
template_name = 'Nutella subscription'
|
52
|
+
template_content = [
|
53
|
+
{
|
54
|
+
:name=> 'main',
|
55
|
+
:content=> "Congratulation: subscription to component
|
56
|
+
<b>#{object}</b>
|
57
|
+
has been succeded."
|
58
|
+
}
|
59
|
+
]
|
60
|
+
message = {
|
61
|
+
:subject=> "Subscription to #{object}",
|
62
|
+
:from_name=> 'Nutella Monitoring Interface',
|
63
|
+
:to=>[
|
64
|
+
{
|
65
|
+
:email=> mail,
|
66
|
+
# :name=> ""
|
67
|
+
}
|
68
|
+
],
|
69
|
+
:from_email=>'nutellamonitoring@gmail.com'
|
70
|
+
}
|
71
|
+
|
72
|
+
sending = $m.messages.send_template template_name, template_content, message
|
73
|
+
end
|
74
|
+
|
75
|
+
def send_notification_mail(mail, application, instance = nil, component = nil)
|
76
|
+
object = application
|
77
|
+
|
78
|
+
if instance != nil
|
79
|
+
object = object + ' > ' + instance
|
80
|
+
if component != nil
|
81
|
+
object = object + ' > ' + component
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
puts "Send mail to " + mail + "message: " + object
|
86
|
+
|
87
|
+
template_name = 'Nutella alert'
|
88
|
+
template_content = [
|
89
|
+
{
|
90
|
+
:name=> 'main',
|
91
|
+
:content=> "Attention: component
|
92
|
+
<b>#{object}</b>
|
93
|
+
had a problem and went down."
|
94
|
+
}
|
95
|
+
]
|
96
|
+
message = {
|
97
|
+
:subject=> "Alert: #{object} went down",
|
98
|
+
:from_name=> 'Nutella Monitoring Interface',
|
99
|
+
:to=>[
|
100
|
+
{
|
101
|
+
:email=> mail,
|
102
|
+
# :name=> ""
|
103
|
+
}
|
104
|
+
],
|
105
|
+
:from_email=>'nutellamonitoring@gmail.com'
|
106
|
+
}
|
107
|
+
|
108
|
+
sending = $m.messages.send_template template_name, template_content, message
|
109
|
+
puts sending
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
# Add an alert on a specific application/instance/component
|
114
|
+
nutella.f.net.subscribe_to_all_runs('monitoring/alert/add', lambda do |message, appId, runId, from|
|
115
|
+
application = message['application']
|
116
|
+
instance = message['instance']
|
117
|
+
component = message['component']
|
118
|
+
mail = message['mail']
|
119
|
+
|
120
|
+
create_if_not_present(application, instance, component)
|
121
|
+
|
122
|
+
if application != nil
|
123
|
+
puts "Subscribed to #{application} with mail #{mail}";
|
124
|
+
end
|
125
|
+
|
126
|
+
if application != nil && instance != nil && component != nil
|
127
|
+
a = $applications[application]
|
128
|
+
if a['instances'][instance]['components'][component]['alert'] == nil
|
129
|
+
a['instances'][instance]['components'][component]['alert'] = []
|
130
|
+
end
|
131
|
+
if !a['instances'][instance]['components'][component]['alert'].include? mail
|
132
|
+
a['instances'][instance]['components'][component]['alert'].push(mail)
|
133
|
+
end
|
134
|
+
$applications[application] = a
|
135
|
+
elsif application != nil && instance != nil
|
136
|
+
a = $applications[application]
|
137
|
+
if a['instances'][instance]['alert'] == nil
|
138
|
+
a['instances'][instance]['alert'] = []
|
139
|
+
end
|
140
|
+
if !a['instances'][instance]['alert'].include? mail
|
141
|
+
a['instances'][instance]['alert'].push(mail)
|
142
|
+
end
|
143
|
+
$applications[application] = a
|
144
|
+
elsif application != nil
|
145
|
+
a = $applications[application]
|
146
|
+
if a['alert'] == nil
|
147
|
+
a['alert'] = []
|
148
|
+
end
|
149
|
+
emails = a['alert']
|
150
|
+
if !emails.include? mail
|
151
|
+
emails.push(mail)
|
152
|
+
send_subscription_mail(mail, application)
|
153
|
+
end
|
154
|
+
$applications[application] = a
|
155
|
+
end
|
156
|
+
|
157
|
+
end)
|
158
|
+
|
159
|
+
# Listen for published messages
|
160
|
+
=begin
|
161
|
+
nutella.net.subscribe('#', lambda do |message, channel, from|
|
162
|
+
puts message
|
163
|
+
puts channel
|
164
|
+
#application = from['app_id']
|
165
|
+
#instance = from['run_id']
|
166
|
+
#component = from['component_id']
|
167
|
+
puts from
|
168
|
+
#puts application, instance, component
|
169
|
+
|
170
|
+
#create_if_not_present(application, instance, component)
|
171
|
+
|
172
|
+
#if !($applications[application]['instances'][instance]['components'][component]['publish'].include? channel)
|
173
|
+
# $applications[application]['instances'][instance]['components'][component]['publish'].push(channel)
|
174
|
+
#end
|
175
|
+
|
176
|
+
end)
|
177
|
+
=end
|
178
|
+
|
179
|
+
# Add an alert on a specific application/instance/component
|
180
|
+
nutella.f.net.subscribe_to_all_runs('monitoring/alert/remove', lambda do |message, appId, runId, from|
|
181
|
+
puts "Delete alert"
|
182
|
+
puts message
|
183
|
+
application = message['application']
|
184
|
+
instance = message['instance']
|
185
|
+
component = message['component']
|
186
|
+
mail = message['mail']
|
187
|
+
|
188
|
+
if application != nil && instance != nil && component != nil
|
189
|
+
a = $applications[application]
|
190
|
+
a['instances'][instance]['components'][component]['alert'] -=[mail]
|
191
|
+
$applications[application] = a
|
192
|
+
elsif application != nil && instance != nil
|
193
|
+
a = $applications[application]
|
194
|
+
a['instances'][instance]['alert'] -= [mail]
|
195
|
+
$applications[application] = a
|
196
|
+
elsif application != nil
|
197
|
+
a = $applications[application]
|
198
|
+
a['alert'] -= [mail]
|
199
|
+
puts a['alert']
|
200
|
+
$applications[application] = a
|
201
|
+
end
|
202
|
+
end)
|
203
|
+
|
204
|
+
# Listen for subscribe
|
205
|
+
# Listen for request
|
206
|
+
# Listen for handle_request
|
207
|
+
|
208
|
+
# Request the list of alert for an application/instance/component
|
209
|
+
nutella.f.net.handle_requests_on_all_runs('monitoring/alert', lambda do |request, appId, runId, from|
|
210
|
+
puts 'Sending alert list'
|
211
|
+
application = request['application']
|
212
|
+
instance = request['instance']
|
213
|
+
component = request['component']
|
214
|
+
|
215
|
+
alert = nil
|
216
|
+
|
217
|
+
begin
|
218
|
+
if application != nil && instance != nil && component != nil
|
219
|
+
a = $applications[application]
|
220
|
+
alert = a['instances'][instance]['components'][component]['alert']
|
221
|
+
elsif application != nil && instance != nil
|
222
|
+
a = $applications[application]
|
223
|
+
alert = a['instances'][instance]['alert']
|
224
|
+
elsif application != nil
|
225
|
+
a = $applications[application]
|
226
|
+
alert = a['alert']
|
227
|
+
end
|
228
|
+
rescue
|
229
|
+
end
|
230
|
+
|
231
|
+
if alert == nil
|
232
|
+
alert = []
|
233
|
+
end
|
234
|
+
|
235
|
+
{:emails => alert}
|
236
|
+
end)
|
237
|
+
|
238
|
+
# Create the application structure if it is not present
|
239
|
+
def create_if_not_present(application, instance=nil, component=nil)
|
240
|
+
|
241
|
+
a = $applications[application]
|
242
|
+
|
243
|
+
if a == nil
|
244
|
+
a = {
|
245
|
+
'name' => application,
|
246
|
+
'instances' => {}
|
247
|
+
}
|
248
|
+
end
|
249
|
+
|
250
|
+
begin
|
251
|
+
if instance != nil && a['instances'][instance] == nil
|
252
|
+
a['instances'][instance] = {
|
253
|
+
'name' => instance,
|
254
|
+
'components' => {}
|
255
|
+
}
|
256
|
+
end
|
257
|
+
rescue
|
258
|
+
a['instances'][instance] = {
|
259
|
+
'name' => instance,
|
260
|
+
'components' => {}
|
261
|
+
}
|
262
|
+
end
|
263
|
+
|
264
|
+
begin
|
265
|
+
if component != nil && instance != nil && a['instances'][instance]['components'][component] == nil
|
266
|
+
a['instances'][instance]['components'][component] = {
|
267
|
+
'name' => component,
|
268
|
+
'publish' => [],
|
269
|
+
'subscribe' => [],
|
270
|
+
'request' => [],
|
271
|
+
'handle_request' => []
|
272
|
+
}
|
273
|
+
end
|
274
|
+
rescue
|
275
|
+
a['instances'][instance]['components'][component] = {
|
276
|
+
'name' => component,
|
277
|
+
'publish' => [],
|
278
|
+
'subscribe' => [],
|
279
|
+
'request' => [],
|
280
|
+
'handle_request' => []
|
281
|
+
}
|
282
|
+
end
|
283
|
+
|
284
|
+
$applications[application] = a
|
285
|
+
|
286
|
+
end
|
287
|
+
|
288
|
+
nutella.f.net.handle_requests_on_all_runs('monitoring/application', lambda do |request, appId, runId, from|
|
289
|
+
apps = []
|
290
|
+
|
291
|
+
$applications.each do |_, application|
|
292
|
+
app = application.deep_dup
|
293
|
+
app['instances'] = []
|
294
|
+
if application['instances'] != nil
|
295
|
+
application['instances'].each do |_, instance|
|
296
|
+
inst = instance.deep_dup
|
297
|
+
|
298
|
+
app['instances'].push(inst)
|
299
|
+
|
300
|
+
inst['components'] = []
|
301
|
+
if instance['components'] != nil
|
302
|
+
instance['components'].each do |_, component|
|
303
|
+
comp = component.deep_dup
|
304
|
+
inst['components'].push(comp)
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
apps.push(app)
|
310
|
+
end
|
311
|
+
{:applications => apps}
|
312
|
+
end)
|
313
|
+
|
314
|
+
nutella.f.net.handle_requests_on_all_runs('monitoring/message', lambda do |request, appId, runId, from|
|
315
|
+
application = request['application']
|
316
|
+
instance = request['instance']
|
317
|
+
channel = request['channel']
|
318
|
+
|
319
|
+
collection = client['dump']
|
320
|
+
|
321
|
+
messages = []
|
322
|
+
|
323
|
+
collection.find({'channel' => '/nutella/apps/crepe/runs/default/location/resources'}).sort({:_id => -1}).limit(5).each do |message|
|
324
|
+
messages.push(message)
|
325
|
+
end
|
326
|
+
|
327
|
+
{:messages => messages}
|
328
|
+
end)
|
329
|
+
|
330
|
+
# Catch publish messages
|
331
|
+
nutella.f.net.subscribe_to_all_runs("#", lambda do |channel, payload, app_id, run_id, from|
|
332
|
+
|
333
|
+
component_id = from['component_id']
|
334
|
+
|
335
|
+
if component_id != nil
|
336
|
+
create_if_not_present(app_id, run_id, component_id)
|
337
|
+
|
338
|
+
publish = $applications[app_id]['instances'][run_id]['components'][component_id]['publish']
|
339
|
+
|
340
|
+
if not publish.include? ({'channel' => channel})
|
341
|
+
publish.push({'channel' => channel})
|
342
|
+
end
|
343
|
+
|
344
|
+
$applications[app_id]['instances'][run_id]['components'][component_id]['publish'] = publish
|
345
|
+
|
346
|
+
end
|
347
|
+
|
348
|
+
end)
|
349
|
+
|
350
|
+
# Catch subscribe / handle_request messages
|
351
|
+
nutella.f.net.subscribe_to_all_runs("subscriptions", lambda do |payload, app_id, run_id, from|
|
352
|
+
|
353
|
+
component_id = from['component_id']
|
354
|
+
type = payload['type']
|
355
|
+
channel = nutella.net.un_pad_channel(payload['channel'], app_id, run_id)
|
356
|
+
|
357
|
+
if type == 'subscribe'
|
358
|
+
create_if_not_present(app_id, run_id, component_id)
|
359
|
+
|
360
|
+
subscribe = $applications[app_id]['instances'][run_id]['components'][component_id]['subscribe']
|
361
|
+
|
362
|
+
if not subscribe.include? ({'channel' => channel})
|
363
|
+
subscribe.push({'channel' => channel})
|
364
|
+
end
|
365
|
+
|
366
|
+
$applications[app_id]['instances'][run_id]['components'][component_id]['subscribe'] = subscribe
|
367
|
+
|
368
|
+
end
|
369
|
+
|
370
|
+
if type == 'handle_requests'
|
371
|
+
create_if_not_present(app_id, run_id, component_id)
|
372
|
+
|
373
|
+
handle_request = $applications[app_id]['instances'][run_id]['components'][component_id]['handle_request']
|
374
|
+
|
375
|
+
if not handle_request.include? ({'channel' => channel})
|
376
|
+
handle_request.push({'channel' => channel})
|
377
|
+
end
|
378
|
+
|
379
|
+
$applications[app_id]['instances'][run_id]['components'][component_id]['handle_request'] = handle_request
|
380
|
+
|
381
|
+
end
|
382
|
+
|
383
|
+
end)
|
384
|
+
|
385
|
+
# Catch requests
|
386
|
+
nutella.f.net.catch_requests_on_all_runs_wildcard(lambda do |channel, payload, app_id, run_id, from|
|
387
|
+
|
388
|
+
component_id = from['component_id']
|
389
|
+
|
390
|
+
if component_id != nil
|
391
|
+
|
392
|
+
create_if_not_present(app_id, run_id, component_id)
|
393
|
+
|
394
|
+
request = $applications[app_id]['instances'][run_id]['components'][component_id]['request']
|
395
|
+
|
396
|
+
unless request.include? ({'channel' => channel})
|
397
|
+
request.push({'channel' => channel})
|
398
|
+
end
|
399
|
+
|
400
|
+
$applications[app_id]['instances'][run_id]['components'][component_id]['request'] = request
|
401
|
+
|
402
|
+
end
|
403
|
+
|
404
|
+
|
405
|
+
end)
|
406
|
+
|
407
|
+
|
408
|
+
nutella.f.net.subscribe_to_all_runs("pings", lambda do |payload, app_id, run_id, from|
|
409
|
+
|
410
|
+
component_id = from['component_id']
|
411
|
+
|
412
|
+
create_if_not_present(app_id, run_id, component_id)
|
413
|
+
|
414
|
+
$applications[app_id]['instances'][run_id]['components'][component_id]['timestamp'] = Time.now.to_f
|
415
|
+
|
416
|
+
end)
|
417
|
+
|
418
|
+
# TODO implement framework pings
|
419
|
+
|
420
|
+
puts 'Initialization completed'
|
421
|
+
|
422
|
+
while sleep 0.25
|
423
|
+
n = Nutella.runlist.all_runs
|
424
|
+
Nutella.runlist.all_apps.each do |app_id, _|
|
425
|
+
Nutella.runlist.runs_for_app(app_id).each do |run_id|
|
426
|
+
pathBots = "#{Nutella.runlist.app_path(app_id)}/bots"
|
427
|
+
pathInterfaces = "#{Nutella.runlist.app_path(app_id)}/interfaces"
|
428
|
+
|
429
|
+
create_if_not_present(app_id, run_id)
|
430
|
+
|
431
|
+
ComponentsList.for_each_component_in_dir(pathBots) do |comp_name|
|
432
|
+
create_if_not_present(app_id, run_id, comp_name)
|
433
|
+
end
|
434
|
+
|
435
|
+
ComponentsList.for_each_component_in_dir(pathInterfaces) do |comp_name|
|
436
|
+
create_if_not_present(app_id, run_id, comp_name)
|
437
|
+
end
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
$applications.each do |_, application|
|
442
|
+
appProblems = 0
|
443
|
+
application['instances'].each do |_, instance|
|
444
|
+
instanceProblems = 0
|
445
|
+
instance['components'].each do |_, component|
|
446
|
+
if component['timestamp'] == nil || Time.now.to_f - component['timestamp'] > 16.0
|
447
|
+
appProblems += 1
|
448
|
+
instanceProblems += 1
|
449
|
+
if component['problem'] != true
|
450
|
+
component['problem'] = true
|
451
|
+
#puts "Set problem on #{application['name']} > #{instance['name']} > #{component['name']}}"
|
452
|
+
if component['alert'] != nil
|
453
|
+
component['alert'].each do |mail|
|
454
|
+
send_notification_mail(mail, application['name'], instance['name'], component['name'])
|
455
|
+
end
|
456
|
+
end
|
457
|
+
if instance['alert'] != nil
|
458
|
+
instance['alert'].each do |mail|
|
459
|
+
send_notification_mail(mail, application['name'], instance['name'], component['name'])
|
460
|
+
end
|
461
|
+
end
|
462
|
+
if application['alert'] != nil
|
463
|
+
application['alert'].each do |mail|
|
464
|
+
send_notification_mail(mail, application['name'], instance['name'], component['name'])
|
465
|
+
end
|
466
|
+
end
|
467
|
+
end
|
468
|
+
else
|
469
|
+
component['problem'] = false
|
470
|
+
end
|
471
|
+
instance['problems'] = instanceProblems
|
472
|
+
end
|
473
|
+
application['problems'] = appProblems
|
474
|
+
end
|
475
|
+
end
|
476
|
+
end
|