naf 2.1.9 → 2.1.10

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -10,7 +10,7 @@ end
10
10
  gem 'jquery-ui-rails'
11
11
  gem 'awesome_print'
12
12
  gem 'will_paginate'
13
- gem 'facter'
13
+ gem 'facter', '1.7.5'
14
14
  gem 'shoulda-matchers', '2.0.0'
15
15
  gem 'timecop', '0.4.5'
16
16
  gem 'yajl-ruby'
@@ -1,5 +1,16 @@
1
1
  = Release Notes
2
2
 
3
+ === Version 2.1.10
4
+ Bug fixes:
5
+ * LogArchiver correctly removes files and directories
6
+ * Disabled machine is highlighted in red
7
+ * Custom validation for machine marked as enabled and deleted
8
+ * UI links behave correctly if the engine's mount path is different than '/job_system'
9
+
10
+ Changes:
11
+ * Improved memory management
12
+ * Removed machine log display
13
+
3
14
  === Version 2.1.9
4
15
  Bug fixes:
5
16
  * Logical::Naf::ConstructionZone doesn't properly propagate affinity parameters
@@ -63,12 +63,12 @@ jQuery(document).ready(function() {
63
63
 
64
64
  function addLinkToApplication(nRow, aData) {
65
65
  var id = aData[0];
66
- var row = jQuery('<a href="/job_system/applications/' + id + '">' + id + '</a>' );
66
+ var row = jQuery('<a href="applications/' + id + '">' + id + '</a>' );
67
67
  jQuery('td:nth-child(1)', nRow).empty().append(row);
68
68
  }
69
69
 
70
70
  function colorizationDeletedOrHidden(nRow, aData) {
71
- if (aData[6] == 'true') {
71
+ if (aData[7] == true) {
72
72
  jQuery(nRow).addClass('deleted_or_hidden');
73
73
  }
74
74
  }
@@ -59,19 +59,19 @@ jQuery(document).ready(function() {
59
59
  return false;
60
60
  }
61
61
  var id = jQuery(this).attr('id');
62
- var url = '/job_system/historical_jobs/' + id;
62
+ var url = 'job_system/historical_jobs/' + id;
63
63
  jQuery.ajax({
64
64
  url: url,
65
65
  type: 'POST',
66
66
  dataType: 'json',
67
67
  data: { "historical_job[request_to_terminate]": 1, "historical_job_id": id, "_method": "put" },
68
68
  success:function (data) {
69
- if (data.success) {
70
- var title = data.title ? data.title : data.command
71
- jQuery("<p id='notice'>A Job " + title + " was terminated!</p>").
72
- appendTo('#flash_message').slideDown().delay(5000).slideUp();
73
- jQuery('#datatable').dataTable().fnDraw();
74
- }
69
+ if (data.success) {
70
+ var title = data.title ? data.title : data.command
71
+ jQuery("<p id='notice'>A Job " + title + " was terminated!</p>").
72
+ appendTo('#flash_message').slideDown().delay(5000).slideUp();
73
+ jQuery('#datatable').dataTable().fnDraw();
74
+ }
75
75
  }
76
76
  });
77
77
  });
@@ -79,7 +79,7 @@ jQuery(document).ready(function() {
79
79
 
80
80
  function addLinkToJob(nRow, aData) {
81
81
  var id = aData[0];
82
- var row = jQuery('<a href="/job_system/historical_jobs/' + id + '">' + id + '</a>' );
82
+ var row = jQuery('<a href="job_system/historical_jobs/' + id + '">' + id + '</a>' );
83
83
  jQuery('td:nth-child(1)', nRow).empty().append(row);
84
84
  }
85
85
 
@@ -49,7 +49,7 @@ jQuery(document).ready(function() {
49
49
  return false;
50
50
  }
51
51
  var id = jQuery(this).attr('id');
52
- var url = '/job_system/machine_runner_invocations/' + id;
52
+ var url = 'machine_runner_invocations/' + id;
53
53
  jQuery.ajax({
54
54
  url: url,
55
55
  type: 'POST',
@@ -47,18 +47,18 @@ jQuery(document).ready(function() {
47
47
  return false;
48
48
  }
49
49
  var id = jQuery(this).attr('id');
50
- var url = '/job_system/machines/' + id;
50
+ var url = 'machines/' + id;
51
51
  jQuery.ajax({
52
52
  url: url,
53
53
  type: 'POST',
54
54
  dataType: 'json',
55
55
  data: { "machine[marked_down]": 1, "terminate": true, "_method": "put" },
56
56
  success:function (data) {
57
- if (data.success) {
58
- jQuery("<p id='notice'>Machine was marked down!</p>").
59
- appendTo('#flash_message').slideDown().delay(5000).slideUp();
60
- jQuery('#datatable').dataTable().fnDraw();
61
- }
57
+ if (data.success) {
58
+ jQuery("<p id='notice'>Machine was marked down!</p>").
59
+ appendTo('#flash_message').slideDown().delay(5000).slideUp();
60
+ jQuery('#datatable').dataTable().fnDraw();
61
+ }
62
62
  }
63
63
  });
64
64
  });
@@ -66,12 +66,12 @@ jQuery(document).ready(function() {
66
66
 
67
67
  function addLinkToMachines(nRow, aData) {
68
68
  var id = aData[0];
69
- var row = jQuery('<a href="/job_system/machines/' + id + '">' + id + '</a>' );
69
+ var row = jQuery('<a href="machines/' + id + '">' + id + '</a>' );
70
70
  jQuery('td:nth-child(1)', nRow).empty().append(row);
71
71
  }
72
72
 
73
73
  function colorizationDeletedOrHidden(nRow, aData) {
74
- if (aData[5] == 'true') {
74
+ if (aData[4] == false) {
75
75
  jQuery(nRow).addClass('deleted_or_hidden');
76
76
  }
77
77
  }
@@ -6,9 +6,6 @@ module Naf
6
6
  @job = ::Naf::HistoricalJob.find_by_id(params['record_id'].to_i)
7
7
  @status = ::Logical::Naf::Job.new(@job).status
8
8
  @partial = 'job_logs'
9
- elsif params['record_type'] == 'machine'
10
- @machine = ::Naf::Machine.find_by_id(params['record_id'].to_i)
11
- @partial = 'machine_logs'
12
9
  elsif params['record_type'] == 'runner'
13
10
  @runner = ::Naf::MachineRunner.find_by_id(params['record_id'].to_i)
14
11
  @partial = 'runner_logs'
@@ -94,8 +94,6 @@ module Logical::Naf
94
94
  parser.parse(json) do |log|
95
95
  if self.class.to_s == 'Logical::Naf::LogParser::Runner'
96
96
  log['id'] = get_invocation_id(file.scan(UUID_REGEX).first)
97
- elsif self.class.to_s == 'Logical::Naf::LogParser::Machine'
98
- log['job_id'] = get_job_id(file)
99
97
  end
100
98
  filter_log_messages(log)
101
99
  end
@@ -22,7 +22,7 @@ module Logical::Naf
22
22
  end
23
23
 
24
24
  def invocation_link(id)
25
- "<a href=\"\/job_system\/machine_runner_invocations\/#{id}\" style=\"font-weight:bold; color: #333399\">invocation(#{id})</a>"
25
+ "<a href=\"machine_runner_invocations\/#{id}\" style=\"font-weight:bold; color: #333399\">invocation(#{id})</a>"
26
26
  end
27
27
 
28
28
  def sort_jsons
@@ -35,6 +35,8 @@ module Logical::Naf
35
35
  end
36
36
 
37
37
  def retrieve_log_files_from_s3
38
+ return [] unless record_id.present?
39
+
38
40
  uuids = ::Naf::MachineRunner.
39
41
  joins(:machine_runner_invocations).
40
42
  where("#{Naf.schema_name}.machine_runners.id = ?", record_id).
@@ -7,8 +7,8 @@ module Logical
7
7
  DATE_REGEX = /((\d){4}-(\d){2}-(\d){2} (\d){2}:(\d){2}:(\d){2} UTC)/
8
8
 
9
9
  def log_files
10
- tree = bucket.objects.with_prefix(prefix).as_tree
11
- directories = tree.children.select(&:branch?).collect(&:prefix).uniq
10
+ tree = bucket.objects.with_prefix(job_log_prefix).as_tree
11
+ directories = tree.children.select(&:branch?).collect(&:job_log_prefix).uniq
12
12
 
13
13
  files = []
14
14
  directories.each do |directory|
@@ -21,8 +21,8 @@ module Logical
21
21
  end
22
22
 
23
23
  def runner_log_files
24
- tree = bucket.objects.with_prefix(prefix(true)).as_tree
25
- directories = tree.children.select(&:branch?).collect(&:prefix).uniq
24
+ tree = bucket.objects.with_prefix(runner_log_prefix).as_tree
25
+ directories = tree.children.select(&:branch?).collect(&:runner_log_prefix).uniq
26
26
 
27
27
  files = []
28
28
  directories.each do |directory|
@@ -40,7 +40,8 @@ module Logical
40
40
  end
41
41
 
42
42
  def retrieve_job_files(job_id)
43
- tree = bucket.objects.with_prefix(prefix + "#{job_id}").as_tree
43
+ return [] unless job_id.present?
44
+ tree = bucket.objects.with_prefix(job_log_prefix + "#{job_id}").as_tree
44
45
  sort_files(tree.children.select(&:leaf?).collect(&:key))
45
46
  end
46
47
 
@@ -57,12 +58,12 @@ module Logical
57
58
  @bucket ||= s3.buckets[NAF_BUCKET]
58
59
  end
59
60
 
60
- def prefix(runner_logs = false)
61
- if runner_logs
62
- "#{NAF_LOG_PATH}/#{creation_time}/#{::Naf::NAF_DATABASE_HOSTNAME}/#{::Naf::NAF_DATABASE}/#{::Naf.schema_name}/runners/"
63
- else
64
- "#{NAF_LOG_PATH}/#{creation_time}/#{::Naf::NAF_DATABASE_HOSTNAME}/#{::Naf::NAF_DATABASE}/#{::Naf.schema_name}/jobs/"
65
- end
61
+ def runner_log_prefix
62
+ @runner_log_prefix ||= "#{NAF_LOG_PATH}/#{creation_time}/#{::Naf::NAF_DATABASE_HOSTNAME}/#{::Naf::NAF_DATABASE}/#{::Naf.schema_name}/runners/"
63
+ end
64
+
65
+ def job_log_prefix
66
+ @job_log_prefix ||= "#{NAF_LOG_PATH}/#{creation_time}/#{::Naf::NAF_DATABASE_HOSTNAME}/#{::Naf::NAF_DATABASE}/#{::Naf.schema_name}/jobs/"
66
67
  end
67
68
 
68
69
  def sort_files(files)
@@ -43,6 +43,7 @@ module Naf
43
43
  greater_than: -2147483648,
44
44
  less_than: 2147483647
45
45
  }
46
+ before_save :check_presence_of_enabled_and_deleted
46
47
  before_save :check_blank_values
47
48
 
48
49
  #---------------------
@@ -261,5 +262,14 @@ module Naf
261
262
  self.log_level = nil if self.log_level.blank?
262
263
  end
263
264
 
265
+ def check_presence_of_enabled_and_deleted
266
+ if self.enabled && self.deleted
267
+ self.errors.add(:enabled, 'should not be true when deleted is true')
268
+ return false
269
+ end
270
+
271
+ return true
272
+ end
273
+
264
274
  end
265
275
  end
@@ -8,14 +8,14 @@ module Process::Naf
8
8
  DATE_REGEX = /\d{8}_\d{6}/
9
9
  LOG_RETENTION = 1
10
10
 
11
- def work
12
- # Use AWS credentials to access S3
13
- s3 = AWS::S3.new(access_key_id: AWS_ID,
11
+ def work
12
+ # Use AWS credentials to access S3
13
+ s3 = AWS::S3.new(access_key_id: AWS_ID,
14
14
  secret_access_key: AWS_KEY,
15
15
  ssl_verify_peer: false)
16
16
 
17
- # Each project will have a specific bucket
18
- bucket = s3.buckets[NAF_BUCKET]
17
+ # Each project will have a specific bucket
18
+ bucket = s3.buckets[NAF_BUCKET]
19
19
  files = log_files
20
20
 
21
21
  logger.info 'Starting to save files to s3...'
@@ -31,13 +31,13 @@ module Process::Naf
31
31
 
32
32
  logger.info 'Starting to archive files...'
33
33
  archive_old_files(files)
34
- end
34
+ end
35
35
 
36
- private
36
+ private
37
37
 
38
- def project_name
39
- (`git remote -v`).slice(/\/\S+/).sub('.git','')[1..-1]
40
- end
38
+ def project_name
39
+ (`git remote -v`).slice(/\/\S+/).sub('.git','')[1..-1]
40
+ end
41
41
 
42
42
  def log_files
43
43
  files = Dir[NAF_JOBS_LOG_PATH + "*/*"]
@@ -63,12 +63,22 @@ module Process::Naf
63
63
 
64
64
  def archive_old_files(files)
65
65
  copy_files
66
- today = Time.zone.now.to_date
67
66
  files.each do |file|
68
67
  logger.info "Archived file: #{file}"
69
- directory = `dirname #{file}`
70
- `rm -r #{directory}`
71
68
  end
69
+ File.delete(*files)
70
+
71
+ cleanup(NAF_JOBS_LOG_PATH + '*')
72
+ cleanup(NAF_RUNNERS_LOG_PATH + '*')
73
+ end
74
+
75
+ def cleanup(path)
76
+ Dir[path].select { |d| File.directory? d }. # select only directories
77
+ select { |d| (Dir.entries(d) - %w[ . .. ]).empty? }. # check if directory is empty
78
+ each do |d|
79
+ logger.info "Removing directory #{d}"
80
+ Dir.rmdir d
81
+ end
72
82
  end
73
83
 
74
84
  def copy_files
@@ -241,6 +241,7 @@ module Process::Naf
241
241
  end
242
242
 
243
243
  def check_schedules
244
+ logger.debug escape_html("last time schedules were checked: #{::Naf::Machine.last_time_schedules_were_checked}")
244
245
  if ::Naf::Machine.is_it_time_to_check_schedules?(@check_schedules_period.minutes)
245
246
  logger.debug "it's time to check schedules"
246
247
  if ::Naf::ApplicationSchedule.try_lock_schedules
@@ -544,7 +545,23 @@ module Process::Naf
544
545
  Facter.clear
545
546
  memory_size = Facter.memorysize_mb.to_f
546
547
  memory_free = Facter.memoryfree_mb.to_f
547
- memory_free_percentage = (memory_free / memory_size) * 100.0
548
+
549
+ # Linux breaks out kernel cache-use memory into an SReclaimable stat
550
+ # in /proc/meminfo which should be counted as free, but facter does not.
551
+ sreclaimable = 0.0
552
+ begin
553
+ File.readlines('/proc/meminfo').each do |l|
554
+ if l =~ /^(?:SReclaimable):\s+(\d+)\s+\S+/
555
+ # Convert the memory from Kilobytes to Gigabytes and
556
+ # store it into sreclaimable
557
+ sreclaimable = ('%.2f' % [$1.to_f / 1024.0]).to_f
558
+ break
559
+ end
560
+ end
561
+ rescue
562
+ end
563
+
564
+ memory_free_percentage = ((memory_free + sreclaimable) / memory_size) * 100.0
548
565
 
549
566
  if (memory_free_percentage >= @minimum_memory_free)
550
567
  logger.detail "memory available: #{memory_free_percentage}% (free) >= " +
@@ -186,9 +186,8 @@
186
186
  return false;
187
187
  }
188
188
  var id = <%= @historical_job.id %>;
189
- var url = '/job_system/historical_jobs/' + id;
190
189
  jQuery.ajax({
191
- url: url,
190
+ url: id,
192
191
  type:'POST',
193
192
  dataType:'json',
194
193
  data:{ "historical_job[request_to_terminate]": 1, "historical_job_id": id, "_method": "put" },
@@ -36,7 +36,7 @@
36
36
  jQuery('#deleted').removeAttr('checked');
37
37
  jQuery('#datatable').addDataTable({ "bProcessing": true });
38
38
  jQuery('.datatable_variable').click(function () {
39
- var url = '/job_system/<%= @params_name.to_s + 's' %>';
39
+ var url = '<%= @params_name.to_s + 's' %>';
40
40
  jQuery.ajax({
41
41
  url:url,
42
42
  type:'GET',
@@ -239,10 +239,7 @@
239
239
 
240
240
  function setLogicalType(){
241
241
  logical_type = '::Logical::Naf::LogParser::';
242
- if('<%= record_type %>' == 'machine'){
243
- logical_type += 'Machine';
244
- }
245
- else if('<%= record_type %>' == 'runner'){
242
+ if('<%= record_type %>' == 'runner'){
246
243
  logical_type += 'Runner';
247
244
  }
248
245
  else if('<%= record_type %>' == 'job'){
@@ -29,7 +29,9 @@
29
29
  if (!answer) {
30
30
  return false;
31
31
  }
32
- var url = '/job_system/machine_runner_invocations/';
32
+ var str = window.location.pathname;
33
+ var sub_path = str.substring(0, str.indexOf("job_system"));
34
+ var url = sub_path + 'job_system/machine_runner_invocations/';
33
35
  jQuery.ajax({
34
36
  url: url,
35
37
  type: 'POST',
@@ -103,8 +103,9 @@
103
103
  return false;
104
104
  }
105
105
  var id = <%= @machine_runner.machine_runner_invocations.last.id %>;
106
- var url = '/job_system/machine_runner_invocations/' + id;
107
- jQuery.ajax({
106
+ var str = window.location.pathname;
107
+ var sub_path = str.substring(0, str.indexOf("job_system"));
108
+ var url = sub_path + 'job_system/machine_runner_invocations/' + id; jQuery.ajax({
108
109
  url: url,
109
110
  type: 'POST',
110
111
  dataType: 'json',
@@ -1,15 +1,6 @@
1
1
  <%
2
2
  rows = @machines.each do |machine|
3
- machine[11] = link_to image_tag('machine.png',
4
- class: 'action',
5
- title: "View machine(id: #{machine[0]}, server:#{machine[1].blank? ? machine[2] : machine[1]}) log"),
6
- url_for({ controller: 'log_viewer',
7
- action: 'index',
8
- record_id: machine[0],
9
- record_type: 'machine' }),
10
- { target: '_blank', id: machine[0] }
11
- machine[11] << "&nbsp;&nbsp;".html_safe
12
- machine[11] << (link_to image_tag('machine_runner.png',
3
+ machine[11] = (link_to image_tag('machine_runner.png',
13
4
  class: 'action',
14
5
  title: "View machine(id: #{machine[0]}, server:#{machine[1].blank? ? machine[2] : machine[1]}) runner log"),
15
6
  url_for({ controller: 'log_viewer',
@@ -54,18 +54,10 @@
54
54
  </tbody>
55
55
  </table>
56
56
  </br>
57
- <%= render partial: 'naf/log_viewer/log_layout', locals: { record_id: @machine.id, record_type: 'machine' } %>
58
57
  </div>
59
58
  <% end %>
60
59
 
61
60
  <%= render partial: 'naf/shared/application' %>
62
- <%= render partial: 'naf/shared/auto_resize_width', locals: { div_class: '.scrollable-output' } %>
63
- <%= render partial: 'naf/log_viewer/log_display',
64
- locals: {
65
- logs_url: "#{http_protocol}#{::Logical::Naf::Machine.new(@machine).runner}#{naf.logs_log_parsers_path}",
66
- record_id: @machine.id,
67
- record_type: 'machine'
68
- } %>
69
61
 
70
62
  <% content_for :javascripts do %>
71
63
  <script type='text/javascript'>
@@ -76,9 +68,8 @@
76
68
  return false;
77
69
  }
78
70
  var id = <%= @machine.id %>;
79
- var url = '/job_system/machines/' + id;
80
71
  jQuery.ajax({
81
- url: url,
72
+ url: id,
82
73
  type: 'POST',
83
74
  dataType: 'json',
84
75
  data: { "machine[marked_down]": 1, "terminate": true, "_method": "put" },
@@ -60,7 +60,7 @@
60
60
 
61
61
  function updateRunnerCount() {
62
62
  jQuery.ajax({
63
- url: '/job_system/machine_runners/runner_count',
63
+ url: 'job_system/machine_runners/runner_count',
64
64
  type: 'GET',
65
65
  dataType: 'json',
66
66
  success:function (data) {
@@ -73,7 +73,7 @@
73
73
 
74
74
  function updateLastCheckedScheduleAt() {
75
75
  jQuery.ajax({
76
- url: '/job_system/machines/last_checked_schedule_at',
76
+ url: 'job_system/machines/last_checked_schedule_at',
77
77
  type: 'GET',
78
78
  dataType: 'json',
79
79
  success:function (data) {
@@ -12,15 +12,23 @@ then
12
12
  cp config/database-non_primary.yml config/database.yml
13
13
  cp app/models/other/base.rb.sample app/models/other/base.rb
14
14
  cp config/initializers/naf.rb.non_primary config/initializers/naf.rb
15
- $rake naf:install:migrations naf:isolate:migrations db:create:all naf:db:migrate naf:janitor:infrastructure naf:db:test:clone_structure
15
+ $rake naf:install:migrations
16
+ $rake naf:isolate:migrations
17
+ $rake db:create:all
18
+ $rake naf:db:migrate
19
+ $rake naf:janitor:infrastructure
20
+ $rake naf:db:test:clone_structure
16
21
  else
17
22
  echo 'Testing primary database install'
18
23
  cp config/database-primary.yml config/database.yml
19
24
  cp config/initializers/naf.rb.primary config/initializers/naf.rb
20
- $rake naf:install:migrations db:create db:migrate naf:janitor:infrastructure db:test:clone_structure
25
+ $rake naf:install:migrations
26
+ $rake db:create
27
+ $rake db:migrate
28
+ $rake naf:janitor:infrastructure
29
+ $rake db:test:clone_structure
21
30
  fi
22
31
 
23
32
  cd ../..
24
33
 
25
34
  $rake spec
26
-
@@ -1,3 +1,3 @@
1
1
  module Naf
2
- VERSION = '2.1.9'
2
+ VERSION = '2.1.10'
3
3
  end
@@ -5,29 +5,29 @@ require "naf/version"
5
5
 
6
6
  # Describe your gem and declare its dependencies:
7
7
  Gem::Specification.new do |s|
8
- s.name = "naf"
8
+ s.name = 'naf'
9
9
  s.version = Naf::VERSION
10
10
  s.license = 'New BSD License'
11
- s.date = '2014-03-25'
12
- s.summary = "Creates infrastructure for a customizable and robust Postgres-backed script scheduling/running"
13
- s.description = "A cloud based distributed cron, application framework and operations console. Naf works as a distributed script running " +
14
- "system that provides scheduling, logging, alarming, machine redundancy, and the ability to set constraint during script execution"
15
- s.authors = ["Keith Gabryelski", "Leonardo Meira"]
11
+ s.date = '2014-04-15'
12
+ s.summary = 'Creates infrastructure for a customizable and robust Postgres-backed script scheduling/running'
13
+ s.description = 'A cloud based distributed cron, application framework and operations console. Naf works as a distributed script running ' +
14
+ 'system that provides scheduling, logging, alarming, machine redundancy, and the ability to set constraint during script execution'
15
+ s.authors = ['Keith Gabryelski', 'Leonardo Meira']
16
16
  s.email = ['keith@fiksu.com', 'lmeira@fiksu.com']
17
17
  s.files = `git ls-files`.split("\n")
18
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
19
  s.homepage = 'http://github.com/fiksu/naf'
20
20
 
21
- s.add_dependency "rails", ">= 3.2"
22
- s.add_dependency "partitioned"
23
- s.add_dependency "log4r_remote_syslog_outputter", ">= 0.0.1"
24
- s.add_dependency "jquery-rails"
21
+ s.add_dependency 'rails', '>= 3.2'
22
+ s.add_dependency 'partitioned'
23
+ s.add_dependency 'log4r_remote_syslog_outputter', '>= 0.0.1'
24
+ s.add_dependency 'jquery-rails'
25
25
  s.add_dependency 'will_paginate'
26
- s.add_dependency 'facter'
27
- s.add_development_dependency "pg"
28
- s.add_development_dependency "rspec-rails"
29
- s.add_development_dependency "factory_girl_rails", "~> 4.0.0"
26
+ s.add_dependency 'facter', '~> 1.7.5'
27
+ s.add_development_dependency 'pg'
28
+ s.add_development_dependency 'rspec-rails'
29
+ s.add_development_dependency 'factory_girl_rails', '~> 4.0.0'
30
30
  s.add_development_dependency 'awesome_print'
31
31
 
32
- s.executables = ["naf"]
32
+ s.executables = ['naf']
33
33
  end
@@ -119,6 +119,19 @@ module Naf
119
119
  end
120
120
  end
121
121
 
122
+ context "when updating the machine" do
123
+ it "should not save when enabled and deleted are true" do
124
+ bad_machine = FactoryGirl.build(:machine, enabled: true, deleted: true)
125
+ bad_machine.save.should_not be_true
126
+ bad_machine.errors.messages[:enabled].should_not be_nil
127
+ end
128
+
129
+ it "should save when enabled is true and deleted is false" do
130
+ machine = FactoryGirl.build(:machine, enabled: true, deleted: false)
131
+ machine.save.should be_true
132
+ end
133
+ end
134
+
122
135
  #----------------------
123
136
  # *** Class Methods ***
124
137
  #++++++++++++++++++++++
@@ -126,7 +139,7 @@ module Naf
126
139
  describe "#enabled" do
127
140
  before do
128
141
  machine.update_attributes!(enabled: true)
129
- FactoryGirl.create(:machine_two, enabled: false)
142
+ FactoryGirl.create(:machine_two, enabled: false, deleted: true)
130
143
  end
131
144
 
132
145
  it "return the correct machine" do
@@ -1,10 +1,25 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  module Process::Naf
4
-
5
4
  describe Runner do
5
+ let!(:runner) { ::Process::Naf::Runner.new }
6
+
7
+ describe '#memory_available_to_spawn?' do
8
+ before do
9
+ Facter.should_receive(:memorysize_mb).and_return(100.0)
10
+ runner.instance_variable_set(:@minimum_memory_free, 15.0)
11
+ end
6
12
 
13
+ it 'return true when there is available memory' do
14
+ Facter.should_receive(:memoryfree_mb).and_return(20.0)
15
+ runner.memory_available_to_spawn?.should be_true
16
+ end
7
17
 
18
+ it 'return true when there is available memory' do
19
+ Facter.should_receive(:memoryfree_mb).and_return(10.0)
20
+ runner.memory_available_to_spawn?.should be_false
21
+ end
22
+ end
8
23
 
9
24
  end
10
25
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: naf
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.9
4
+ version: 2.1.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2014-03-25 00:00:00.000000000 Z
13
+ date: 2014-04-15 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rails
@@ -97,17 +97,17 @@ dependencies:
97
97
  requirement: !ruby/object:Gem::Requirement
98
98
  none: false
99
99
  requirements:
100
- - - ! '>='
100
+ - - ~>
101
101
  - !ruby/object:Gem::Version
102
- version: '0'
102
+ version: 1.7.5
103
103
  type: :runtime
104
104
  prerelease: false
105
105
  version_requirements: !ruby/object:Gem::Requirement
106
106
  none: false
107
107
  requirements:
108
- - - ! '>='
108
+ - - ~>
109
109
  - !ruby/object:Gem::Version
110
- version: '0'
110
+ version: 1.7.5
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: pg
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -278,7 +278,6 @@ files:
278
278
  - app/models/logical/naf/log_file.rb
279
279
  - app/models/logical/naf/log_parser/base.rb
280
280
  - app/models/logical/naf/log_parser/job.rb
281
- - app/models/logical/naf/log_parser/machine.rb
282
281
  - app/models/logical/naf/log_parser/runner.rb
283
282
  - app/models/logical/naf/log_reader.rb
284
283
  - app/models/logical/naf/machine.rb
@@ -371,7 +370,6 @@ files:
371
370
  - app/views/naf/log_viewer/_job_logs.html.erb
372
371
  - app/views/naf/log_viewer/_log_display.html.erb
373
372
  - app/views/naf/log_viewer/_log_layout.html.erb
374
- - app/views/naf/log_viewer/_machine_logs.html.erb
375
373
  - app/views/naf/log_viewer/_runner_logs.html.erb
376
374
  - app/views/naf/log_viewer/_search_options.html.erb
377
375
  - app/views/naf/log_viewer/_update_page_title.html.erb
@@ -1,64 +0,0 @@
1
- require 'yajl'
2
-
3
- module Logical::Naf
4
- module LogParser
5
- class Machine < Base
6
-
7
- def initialize(params)
8
- super(params)
9
- end
10
-
11
- def logs
12
- retrieve_logs
13
- end
14
-
15
- private
16
-
17
- def insert_log_line(elem)
18
- "&nbsp;&nbsp;<span>#{elem['output_time']} <font color='333399'><b>jid(#{elem['job_id']}):</b></font> #{elem['message']}</br></span>"
19
- end
20
-
21
- def sort_jsons
22
- # Sort log lines based on timestamp
23
- @jsons = jsons.sort { |x, y| Time.parse(x['output_time']) <=> Time.parse(y['output_time']) }
24
- end
25
-
26
- def parse_newest_log
27
- if newest_log.scan(/jid\(\d*\)\: /).present?
28
- newest_log.slice!(/jid\(\d*\)\: /)
29
- end
30
- newest_log
31
- end
32
-
33
- def retrieve_log_files_from_s3
34
- s3_log_reader.log_files
35
- end
36
-
37
- def get_files
38
- if log_type == 'old' && read_from_s3 == 'true'
39
- get_s3_files do
40
- @s3_log_reader = ::Logical::Naf::LogReader.new
41
- return retrieve_log_files_from_s3
42
- end
43
- else
44
- files = Dir["#{::Naf::PREFIX_PATH}/#{::Naf.schema_name}/jobs/*/*"]
45
- if files.present?
46
- # Sort log files based on time
47
- return files.sort { |x, y| Time.parse(y.scan(DATE_REGEX)[0][0]) <=> Time.parse(x.scan(DATE_REGEX)[0][0]) }
48
- else
49
- get_s3_files do
50
- @read_from_s3 = 'true'
51
- @s3_log_reader = ::Logical::Naf::LogReader.new
52
- return retrieve_log_files_from_s3
53
- end
54
- end
55
- end
56
- end
57
-
58
- def get_job_id(file)
59
- file.scan(/\d+_\d{8}/).first.split('_').first
60
- end
61
-
62
- end
63
- end
64
- end
@@ -1,62 +0,0 @@
1
- <div id='naf'>
2
- <div id="fluid">
3
- <div id='bd'>
4
- <div id="record">
5
- <FONT FACE= "Courier New">
6
- <div id="stdout" class="scrollable-output-expanded"></div>
7
- </br>
8
- <FONT FACE= "Arial">
9
-
10
- <div id="stdout_header">
11
- <div>
12
- <%= render partial: 'search_options' %>
13
- <div style="width: 100%; display: table;">
14
- <div style="display: table-row">
15
- <div style="width: 600px; display: table-cell;">
16
- <%= label_tag 'From:' %>
17
- <%= render partial: 'naf/shared/date_select', locals: { prefix: 'date_select_from', dropdown_width: 'width: 15%;' } %>
18
- </br>
19
- <%= label_tag 'To:' %>&nbsp;&nbsp;&nbsp;&nbsp;
20
- <%= render partial: 'naf/shared/date_select', locals: { prefix: 'date_select_to', dropdown_width: 'width: 15%;' } %>
21
- </div>
22
- <div style="display: table-cell;">
23
- <strong style="margin-left: 10%; size: 10%">Machine Information</strong>
24
- <table id='naf_table_show' style="margin-left: 10%; width: 75%">
25
- <thead>
26
- <tr>
27
- <td width="7%">ID</td>
28
- <td>Server</td>
29
- <td>Last Seen Alive At</td>
30
- </tr>
31
- </thead>
32
- <tbody>
33
- <tr>
34
- <td><%= @machine.id %></td>
35
- <td><%= @machine.hostname %></td>
36
- <td><%= @machine.last_seen_alive_at %></td>
37
- </tr>
38
- </tbody>
39
- </table>
40
- </div>
41
- </div>
42
- </div>
43
- </br>
44
-
45
- <%= submit_tag("Search the logs", id: 'log_search_submit') %>
46
- &nbsp;&nbsp;&nbsp;
47
- <%= link_to 'Back to Machine', { controller: 'machines', action: 'show', id: @machine.id } %>
48
- </div>
49
- </div>
50
- </div>
51
- </div>
52
- </div>
53
- </div>
54
-
55
- <%= render partial: 'update_page_title', locals: { title: "Machine(#{@machine.id}) Logs" } %>
56
- <%= render partial: 'naf/shared/auto_resize_width', locals: { div_class: '.scrollable-output-expanded' } %>
57
- <%= render partial: 'log_display',
58
- locals: {
59
- logs_url: "#{http_protocol}#{::Logical::Naf::Machine.new(@machine).runner}#{naf.logs_log_parsers_path}",
60
- record_id: @machine.id,
61
- record_type: 'machine'
62
- } %>