pampa 2.0.12 → 2.0.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/pampa.rb +177 -34
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: efa42c22ec0a02a9ae9e1ff633d6b034606a78f944f842cf782b13adeb59242e
4
- data.tar.gz: 8efad57c243fc4de08f64d3fd6935d8393fb965cdfe2174749e466d2f571aa4a
3
+ metadata.gz: 0137672f5c0b7c0cd2be75ddf221d84d65d824c8ba4bdf87b5cfd369bf9eef14
4
+ data.tar.gz: 7d8bb53cfd11c3d37b69b8408c544f1718fc0178f130f5f16785771e84af9ac9
5
5
  SHA512:
6
- metadata.gz: '08d7f6166b24bcc2abd501bf62f6acae0d60aefe1283b14bbea5f079bd3a9a6b38307cb80d3dd626a49a5652093d9120793274d4816e9e7a4380c039f95a4ae8'
7
- data.tar.gz: 6ec308ec2f54ca6e81c7e3b2089d60fc1fd2c88e36f97ad8dad8dab7231eaf2c2cb62a8d3ed6000d03615315ddbd2fe364b722edd725437b8652427fd5f8dd95
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 ~/pampa to ~/pampa.<current timestamp>.
301
- # create a new folder ~/pampa.
302
- # build the file ~/pampa/config.rb in the remote node.
303
- # copy the file ~/pampa/worker.rb to the remote node.
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(config_filename='./config.rb', worker_filename='./worker.rb')
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
- `ps ax | grep ruby | grep -v grep | grep -v #{Process.pid} | cut -b3-7 | xargs -t kill;`
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
- `mv ~/pampa ~/pampa.#{Time.now().to_i.to_s}`
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
- `mkdir ~/pampa`
369
+ node.exec("mkdir #{BlackStack::Pampa.working_directory}", false);
338
370
  l.done
339
- # build the file ~/pampa/config.rb in the remote node. - Be sure the BlackStack::Pampa.to_hash.to_s don't have single-quotes (') in the string.
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)}\" > ~/pampa/config.rb"
342
- `#{s}`
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 ~/pampa/worker.rb to the remote node. - Be sure the script don't have single-quotes (') in the string.
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)}\" > ~/pampa/worker.rb"
347
- `#{s}`
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 worker.rb id=#{worker.id} config=~/pampa/config.rb >/dev/null 2>&1 &"
355
- `#{s}`
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(config_filename='~/pampa/config.rb', worker_filename='~/pampa/worker.rb')
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
- `ps ax | grep ruby | grep -v grep | grep -v #{Process.pid} | cut -b3-7 | xargs -t kill;`
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
- s = "nohup ruby #{worker_filename} id=#{worker.id} config=#{config_filename} >/dev/null 2>&1 &"
397
- `#{s}`
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(config_filename='./config.rb')
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
- `ps ax | grep ruby | grep -v grep | grep -v #{Process.pid} | cut -b3-7 | xargs -t kill;`
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
- self.workers << BlackStack::Pampa::Worker.new({:id => "#{self.name}.#{(i+1).to_s}", :node => self.to_hash})
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.12
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-09 00:00:00.000000000 Z
11
+ date: 2022-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel