pampa 2.0.12 → 2.0.14
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/lib/pampa.rb +177 -34
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0137672f5c0b7c0cd2be75ddf221d84d65d824c8ba4bdf87b5cfd369bf9eef14
|
4
|
+
data.tar.gz: 7d8bb53cfd11c3d37b69b8408c544f1718fc0178f130f5f16785771e84af9ac9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz: '
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '00540329934fd5d5d22cae40967fee37ba4eba39a4383d324999da4902ea0a8e83c489a320820102ec3c8175a37fdace4a2147b0be490ec22e6c8380ab29f1a2'
|
7
|
+
data.tar.gz: 4efb7d405e0aa5d6a7c6f8b613b83fe14511d2f15a14f9338c48da4676204631a0c99fc34491474571c164779ad730e5820b397f2dc93a3abb3ff5bee6ec1851
|
data/lib/pampa.rb
CHANGED
@@ -9,6 +9,11 @@ module BlackStack
|
|
9
9
|
module Pampa
|
10
10
|
# activate this flag if you want to add pampa nodes to blackstack-deployer.
|
11
11
|
@@integrate_with_blackstack_deployer = false
|
12
|
+
# setup custom locations for config and worker files.
|
13
|
+
@@config_filename = "config.rb"
|
14
|
+
@@worker_filename = "worker.rb"
|
15
|
+
# setu the directory where the worker.rb file will be lauched, and the log files will be stored.
|
16
|
+
@@working_directory = "$HOME/pampa"
|
12
17
|
# arrays of workers, nodes, and jobs.
|
13
18
|
@@nodes = []
|
14
19
|
@@jobs = []
|
@@ -17,7 +22,43 @@ module BlackStack
|
|
17
22
|
@@logger = BlackStack::DummyLogger.new(nil)
|
18
23
|
# Connection string to the database. Example: mysql2://user:password@localhost:3306/database
|
19
24
|
@@connection_string = nil
|
20
|
-
|
25
|
+
|
26
|
+
# @@integrate_with_blackstack_deployer
|
27
|
+
def self.integrate_with_blackstack_deployer()
|
28
|
+
@@integrate_with_blackstack_deployer
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.set_integrate_with_blackstack_deployer(b)
|
32
|
+
@@integrate_with_blackstack_deployer = b
|
33
|
+
end
|
34
|
+
|
35
|
+
# @@config_filename
|
36
|
+
def self.config_filename()
|
37
|
+
@@config_filename
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.set_config_filename(s)
|
41
|
+
@@config_filename = s
|
42
|
+
end
|
43
|
+
|
44
|
+
# @@worker_filename
|
45
|
+
def self.worker_filename()
|
46
|
+
@@worker_filename
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.set_worker_filename(s)
|
50
|
+
@@worker_filename = s
|
51
|
+
end
|
52
|
+
|
53
|
+
## @@working_directory
|
54
|
+
def self.working_directory()
|
55
|
+
@@working_directory
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.set_working_directory(s)
|
59
|
+
@@working_directory = s
|
60
|
+
end
|
61
|
+
|
21
62
|
# define a filename for the log file.
|
22
63
|
def self.set_log_filename(s)
|
23
64
|
@@log_filename = s
|
@@ -33,15 +74,6 @@ module BlackStack
|
|
33
74
|
@@logger = l
|
34
75
|
end
|
35
76
|
|
36
|
-
# @@integrate_with_blackstack_deployer
|
37
|
-
def self.integrate_with_blackstack_deployer()
|
38
|
-
@@integrate_with_blackstack_deployer
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.set_integrate_with_blackstack_deployer(b)
|
42
|
-
@@integrate_with_blackstack_deployer = b
|
43
|
-
end
|
44
|
-
|
45
77
|
# return the log filename.
|
46
78
|
def self.log_filename()
|
47
79
|
@@log_filename
|
@@ -297,10 +329,10 @@ module BlackStack
|
|
297
329
|
|
298
330
|
# connect the nodes via ssh.
|
299
331
|
# kill all Ruby processes except this one.
|
300
|
-
# rename any existing folder
|
301
|
-
# create a new folder
|
302
|
-
# build the file
|
303
|
-
# copy the file
|
332
|
+
# rename any existing folder $HOME/pampa to $HOME/pampa.<current timestamp>.
|
333
|
+
# create a new folder $HOME/pampa.
|
334
|
+
# build the file $HOME/pampa/config.rb in the remote node.
|
335
|
+
# copy the file $HOME/pampa/worker.rb to the remote node.
|
304
336
|
# run the number of workers specified in the configuration of the Pampa module.
|
305
337
|
# return an array with the IDs of the workers.
|
306
338
|
#
|
@@ -308,7 +340,7 @@ module BlackStack
|
|
308
340
|
# - config: relative path of the configuration file. Example: '../config.rb'
|
309
341
|
# - worker: relative path of the worker.rb file. Example: '../worker.rb'
|
310
342
|
#
|
311
|
-
def self.deploy(
|
343
|
+
def self.deploy()
|
312
344
|
# validate: the connection string is not nil
|
313
345
|
raise "The connection string is nil" if @@connection_string.nil?
|
314
346
|
# validate: the connection string is not empty
|
@@ -326,33 +358,33 @@ module BlackStack
|
|
326
358
|
l.done
|
327
359
|
# kill all ruby processes except this one
|
328
360
|
l.logs("Killing all Ruby processes except this one... ")
|
329
|
-
|
361
|
+
node.exec("ps ax | grep ruby | grep -v grep | grep -v #{Process.pid} | cut -b3-7 | xargs -t kill;", false);
|
330
362
|
l.done
|
331
363
|
# rename any existing folder ~/code/pampa to ~/code/pampa.<current timestamp>.
|
332
364
|
l.logs("Renaming old folder... ")
|
333
|
-
|
365
|
+
node.exec("mv #{BlackStack::Pampa.working_directory} #{BlackStack::Pampa.working_directory}.#{Time.now().to_i.to_s}", false);
|
334
366
|
l.done
|
335
367
|
# create a new folder ~/code. - ignore if it already exists.
|
336
368
|
l.logs("Creating new folder... ")
|
337
|
-
|
369
|
+
node.exec("mkdir #{BlackStack::Pampa.working_directory}", false);
|
338
370
|
l.done
|
339
|
-
# build the file
|
371
|
+
# build the file $HOME/pampa/config.rb in the remote node. - Be sure the BlackStack::Pampa.to_hash.to_s don't have single-quotes (') in the string.
|
340
372
|
l.logs("Building config file... ")
|
341
|
-
s = "echo \"#{File.read(config_filename)}\" >
|
342
|
-
|
373
|
+
s = "echo \"#{File.read(config_filename)}\" > #{BlackStack::Pampa.working_directory}/#{BlackStack::Pampa.config_filename}"
|
374
|
+
node.exec("#{s}", false);
|
343
375
|
l.done
|
344
|
-
# copy the file
|
376
|
+
# copy the file $HOME/pampa/worker.rb to the remote node. - Be sure the script don't have single-quotes (') in the string.
|
345
377
|
l.logs("Copying worker file... ")
|
346
|
-
s = "echo \"#{File.read(worker_filename)}\" >
|
347
|
-
|
378
|
+
s = "echo \"#{File.read(worker_filename)}\" > #{BlackStack::Pampa.working_directory}/#{BlackStack::Pampa.worker_filename}"
|
379
|
+
node.exec("#{s}", false);
|
348
380
|
l.done
|
349
381
|
# run the number of workers specified in the configuration of the Pampa module.
|
350
382
|
node.workers.each { |worker|
|
351
383
|
# run the worker
|
352
384
|
# add these parameters for debug: debug=yes pampa=~/code/pampa/lib/pampa.rb
|
353
385
|
l.logs "Running worker #{worker.id}... "
|
354
|
-
s = "nohup ruby
|
355
|
-
|
386
|
+
s = "nohup ruby #{BlackStack::Pampa.worker_filename} id=#{worker.id} config=#{BlackStack::Pampa.working_directory}/#{BlackStack::Pampa.config_filename} >/dev/null 2>&1 &"
|
387
|
+
node.exec("#{s}", false);
|
356
388
|
l.done
|
357
389
|
}
|
358
390
|
# disconnect the node
|
@@ -368,7 +400,7 @@ module BlackStack
|
|
368
400
|
# run the number of workers specified in the configuration of the Pampa module.
|
369
401
|
# return an array with the IDs of the workers.
|
370
402
|
#
|
371
|
-
def self.start(
|
403
|
+
def self.start()
|
372
404
|
# validate: the connection string is not nil
|
373
405
|
raise "The connection string is nil" if @@connection_string.nil?
|
374
406
|
# validate: the connection string is not empty
|
@@ -386,15 +418,23 @@ module BlackStack
|
|
386
418
|
l.done
|
387
419
|
# kill all ruby processes except this one
|
388
420
|
l.logs("Killing all Ruby processes except this one... ")
|
389
|
-
|
421
|
+
node.exec("ps ax | grep ruby | grep -v grep | grep -v #{Process.pid} | cut -b3-7 | xargs -t kill;", true);
|
390
422
|
l.done
|
391
423
|
# run the number of workers specified in the configuration of the Pampa module.
|
392
424
|
node.workers.each { |worker|
|
393
425
|
# run the worker
|
394
426
|
# add these parameters for debug: debug=yes pampa=~/code/pampa/lib/pampa.rb
|
427
|
+
# run a bash command that sources the .profile file and runs the ruby script in the background, returning immediatelly.
|
428
|
+
|
395
429
|
l.logs "Running worker #{worker.id}... "
|
396
|
-
|
397
|
-
|
430
|
+
|
431
|
+
# write bash command to initialize bash file
|
432
|
+
s = "echo \"source $HOME/.profile; cd #{BlackStack::Pampa.working_directory}; nohup ruby #{worker_filename} id=#{worker.id} config=#{self.config_filename} >/dev/null 2>&1 &\" > #{BlackStack::Pampa.working_directory}/worker.sh"
|
433
|
+
node.exec(s, false);
|
434
|
+
|
435
|
+
s = "nohup bash #{BlackStack::Pampa.working_directory}/worker.sh >/dev/null 2>&1 &"
|
436
|
+
node.exec(s, false);
|
437
|
+
|
398
438
|
l.done
|
399
439
|
}
|
400
440
|
# disconnect the node
|
@@ -411,7 +451,7 @@ module BlackStack
|
|
411
451
|
# Parameters:
|
412
452
|
# - config: relative path of the configuration file. Example: '../config.rb'
|
413
453
|
#
|
414
|
-
def self.stop(
|
454
|
+
def self.stop()
|
415
455
|
# validate: the connection string is not nil
|
416
456
|
raise "The connection string is nil" if @@connection_string.nil?
|
417
457
|
# validate: the connection string is not empty
|
@@ -429,7 +469,7 @@ module BlackStack
|
|
429
469
|
l.done
|
430
470
|
# kill all ruby processes except this one
|
431
471
|
l.logs("Killing all Ruby processes except this one... ")
|
432
|
-
|
472
|
+
node.exec("ps ax | grep ruby | grep -v grep | grep -v #{Process.pid} | cut -b3-7 | xargs -t kill;", false);
|
433
473
|
l.done
|
434
474
|
# disconnect the node
|
435
475
|
l.logs("Disconnecting... ")
|
@@ -439,10 +479,43 @@ module BlackStack
|
|
439
479
|
} # @@nodes.each do |node|
|
440
480
|
end
|
441
481
|
|
482
|
+
# get the node by `node_name`
|
483
|
+
# connect the nodes via ssh.
|
484
|
+
# get how many minutes the worker wrote the log file
|
485
|
+
# close the connection
|
486
|
+
def self.log_minutes_ago(node_name, worker_id)
|
487
|
+
# get the node
|
488
|
+
n = self.nodes.select { |n| n.name == node_name }.first
|
489
|
+
return nil if !n
|
490
|
+
# connect the node
|
491
|
+
n.connect()
|
492
|
+
# get the time of the last time the worker wrote the log file
|
493
|
+
s = n.exec("cat #{BlackStack::Pampa.working_directory}/worker.#{worker_id}.log | tail -n 1 | cut -b1-19", false).to_s.strip
|
494
|
+
# run bash command to get the difference in minutes beteen now and the last time the worker wrote the log file
|
495
|
+
s = n.exec("echo \"$(($(date +%s) - $(date -d '#{s}' +%s))) / 60\" | bc", false).to_s.strip
|
496
|
+
# disconnect the node
|
497
|
+
n.disconnect
|
498
|
+
# return the number of minutes
|
499
|
+
s
|
500
|
+
end # log_minutes_ago
|
501
|
+
|
502
|
+
# get the node usage of CPU, RAM, DISK, and NETWORK
|
503
|
+
# return a hash with the usage of CPU, RAM, DISK, and NETWORK
|
504
|
+
#
|
505
|
+
# sudo apt install sysstat
|
506
|
+
#
|
507
|
+
def self.node_usage(node_name)
|
508
|
+
ret = {}
|
509
|
+
# get the node
|
510
|
+
n = self.nodes.select { |n| n.name == node_name }.first
|
511
|
+
return nil if !n
|
512
|
+
n.usage
|
513
|
+
end # node_usage
|
514
|
+
|
442
515
|
# stub worker class
|
443
516
|
class Worker
|
444
517
|
# name to identify uniquely the worker
|
445
|
-
attr_accessor :id, :assigned_job, :attached
|
518
|
+
attr_accessor :id, :assigned_job, :attached, :node
|
446
519
|
# return an array with the errors found in the description of the job
|
447
520
|
def self.descriptor_errors(h)
|
448
521
|
errors = []
|
@@ -471,6 +544,10 @@ module BlackStack
|
|
471
544
|
def detach()
|
472
545
|
self.attached = false
|
473
546
|
end
|
547
|
+
# get the latest n lines of the log of this worker
|
548
|
+
def tail(n=10)
|
549
|
+
self.node.tail("#{BlackStack::Pampa.working_directory}/worker.#{self.id}.log", n)
|
550
|
+
end
|
474
551
|
end
|
475
552
|
|
476
553
|
# stub node class
|
@@ -500,7 +577,9 @@ module BlackStack
|
|
500
577
|
self.max_workers = h[:max_workers]
|
501
578
|
self.workers = []
|
502
579
|
self.max_workers.times do |i|
|
503
|
-
|
580
|
+
new_worker = BlackStack::Pampa::Worker.new({:id => "#{self.name}.#{(i+1).to_s}", :node => self.to_hash})
|
581
|
+
new_worker.node = self
|
582
|
+
self.workers << new_worker
|
504
583
|
end
|
505
584
|
end # def self.create(h)
|
506
585
|
# returh a hash descriptor of the node
|
@@ -569,6 +648,8 @@ module BlackStack
|
|
569
648
|
# stretch assignation/unassignation of workers
|
570
649
|
attr_accessor :max_pending_tasks
|
571
650
|
attr_accessor :max_assigned_workers
|
651
|
+
# tags in order to choose on which nodes the job will be executed
|
652
|
+
attr_accessor :tags
|
572
653
|
|
573
654
|
# return a hash descriptor of the job
|
574
655
|
def to_hash()
|
@@ -596,6 +677,7 @@ module BlackStack
|
|
596
677
|
:processing_function => self.processing_function.to_s,
|
597
678
|
:max_pending_tasks => self.max_pending_tasks,
|
598
679
|
:max_assigned_workers => self.max_assigned_workers,
|
680
|
+
:tags => self.tags
|
599
681
|
}
|
600
682
|
end
|
601
683
|
|
@@ -631,6 +713,7 @@ module BlackStack
|
|
631
713
|
self.processing_function = h[:processing_function]
|
632
714
|
self.max_pending_tasks = h[:max_pending_tasks]
|
633
715
|
self.max_assigned_workers = h[:max_assigned_workers]
|
716
|
+
self.tags = h[:tags].nil? ? [] : ( h[:tags].is_a?(Array) ? h[:tags] : [h[:tags].to_s] )
|
634
717
|
end
|
635
718
|
|
636
719
|
# returns an array of tasks pending to be processed by the worker.
|
@@ -785,6 +868,66 @@ module BlackStack
|
|
785
868
|
#
|
786
869
|
return i
|
787
870
|
end
|
871
|
+
|
872
|
+
# reporting method: idle
|
873
|
+
# reutrn the number of idle tasks.
|
874
|
+
# if the numbr if idle tasks is higher than `max_tasks_to_show` then it returns `max_tasks_to_show`+.
|
875
|
+
def idle(max_tasks_to_show=25)
|
876
|
+
j = self
|
877
|
+
ret = j.selecting(max_tasks_to_show).size
|
878
|
+
ret = ret >= max_tasks_to_show ? "#{ret.to_label}+" : ret.to_label
|
879
|
+
ret
|
880
|
+
end # def idle
|
881
|
+
|
882
|
+
# reporting method: running
|
883
|
+
# return the number of running tasks.
|
884
|
+
# if the numbr if running tasks is higher than `max_tasks_to_show` then it returns `max_tasks_to_show`+.
|
885
|
+
def running(max_tasks_to_show=25)
|
886
|
+
j = self
|
887
|
+
ret = 0
|
888
|
+
BlackStack::Pampa::nodes.each { |n|
|
889
|
+
n.workers.each { |w|
|
890
|
+
ret += j.occupied_slots(w).size
|
891
|
+
break if ret>=max_tasks_to_show
|
892
|
+
}
|
893
|
+
}
|
894
|
+
ret = ret >= max_tasks_to_show ? "#{max_tasks_to_show}+" : ret.to_label
|
895
|
+
ret
|
896
|
+
end # def idle
|
897
|
+
|
898
|
+
# reporting method: running
|
899
|
+
# return the number of running tasks.
|
900
|
+
# if the numbr if running tasks is higher than `max_tasks_to_show` then it returns `max_tasks_to_show`+.
|
901
|
+
def failed(max_tasks_to_show=25)
|
902
|
+
j = self
|
903
|
+
q = "
|
904
|
+
SELECT *
|
905
|
+
FROM #{j.table.to_s}
|
906
|
+
WHERE COALESCE(#{j.field_success.to_s},true)=false
|
907
|
+
--AND #{j.field_end_time.to_s} IS NULL
|
908
|
+
--AND COALESCE(#{j.field_times.to_s},0) >= #{j.max_try_times.to_i}
|
909
|
+
LIMIT #{max_tasks_to_show}
|
910
|
+
"
|
911
|
+
ret = DB[q].all.size
|
912
|
+
ret = ret >= max_tasks_to_show ? "#{ret.to_label}+" : ret.to_label
|
913
|
+
ret
|
914
|
+
end # def idle
|
915
|
+
|
916
|
+
# reporting method: error_descriptions
|
917
|
+
# return an array of hashes { :id, :error_description } with the tasks that have an the success flag in false, error description.
|
918
|
+
# if the numbr if running tasks is higher than `max_tasks_to_show` then it returns `max_tasks_to_show` errors.
|
919
|
+
def error_descriptions(max_tasks_to_show=25)
|
920
|
+
j = self
|
921
|
+
q = "
|
922
|
+
SELECT #{j.field_primary_key.to_s} as id, #{j.field_error_description.to_s} as description
|
923
|
+
FROM #{j.table.to_s}
|
924
|
+
WHERE COALESCE(#{j.field_success.to_s},true)=false
|
925
|
+
--AND #{j.field_end_time.to_s} IS NULL
|
926
|
+
--AND COALESCE(#{j.field_times.to_s},0) >= #{j.max_try_times.to_i}
|
927
|
+
LIMIT #{max_tasks_to_show}
|
928
|
+
"
|
929
|
+
DB[q].all
|
930
|
+
end
|
788
931
|
end # class Job
|
789
932
|
end # module Pampa
|
790
933
|
end # module BlackStack
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pampa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leandro Daniel Sardi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-12-
|
11
|
+
date: 2022-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|