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 +1 -1
- data/RELEASE_NOTES.rdoc +11 -0
- data/app/assets/javascripts/dataTablesTemplates/applications.js +2 -2
- data/app/assets/javascripts/dataTablesTemplates/jobs.js +8 -8
- data/app/assets/javascripts/dataTablesTemplates/machine_runners.js +1 -1
- data/app/assets/javascripts/dataTablesTemplates/machines.js +8 -8
- data/app/controllers/naf/log_viewer_controller.rb +0 -3
- data/app/models/logical/naf/log_parser/base.rb +0 -2
- data/app/models/logical/naf/log_parser/runner.rb +3 -1
- data/app/models/logical/naf/log_reader.rb +12 -11
- data/app/models/naf/machine.rb +10 -0
- data/app/models/process/naf/log_archiver.rb +23 -13
- data/app/models/process/naf/runner.rb +18 -1
- data/app/views/naf/historical_jobs/show.html.erb +1 -2
- data/app/views/naf/janitorial_assignments/index.html.erb +1 -1
- data/app/views/naf/log_viewer/_log_display.html.erb +1 -4
- data/app/views/naf/machine_runners/index.html.erb +3 -1
- data/app/views/naf/machine_runners/show.html.erb +3 -2
- data/app/views/naf/machines/index.json.erb +1 -10
- data/app/views/naf/machines/show.html.erb +1 -10
- data/app/views/naf/shared/_select_per_page.html.erb +2 -2
- data/ci/travis.sh +11 -3
- data/lib/naf/version.rb +1 -1
- data/naf.gemspec +15 -15
- data/spec/models/naf/machine_spec.rb +14 -1
- data/spec/models/process/naf/runner_spec.rb +16 -1
- metadata +6 -8
- data/app/models/logical/naf/log_parser/machine.rb +0 -64
- data/app/views/naf/log_viewer/_machine_logs.html.erb +0 -62
data/Gemfile
CHANGED
data/RELEASE_NOTES.rdoc
CHANGED
@@ -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="
|
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[
|
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 = '
|
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
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
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="
|
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
|
|
@@ -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 = '
|
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
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
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="
|
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[
|
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=\"
|
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(
|
11
|
-
directories = tree.children.select(&:branch?).collect(&:
|
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(
|
25
|
-
directories = tree.children.select(&:branch?).collect(&:
|
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
|
-
|
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
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
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)
|
data/app/models/naf/machine.rb
CHANGED
@@ -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
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
18
|
-
|
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
|
-
|
34
|
+
end
|
35
35
|
|
36
|
-
|
36
|
+
private
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
-
|
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:
|
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 = '
|
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 %>' == '
|
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
|
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
|
107
|
-
|
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('
|
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] << " ".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:
|
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: '
|
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: '
|
76
|
+
url: 'job_system/machines/last_checked_schedule_at',
|
77
77
|
type: 'GET',
|
78
78
|
dataType: 'json',
|
79
79
|
success:function (data) {
|
data/ci/travis.sh
CHANGED
@@ -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
|
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
|
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
|
-
|
data/lib/naf/version.rb
CHANGED
data/naf.gemspec
CHANGED
@@ -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 =
|
8
|
+
s.name = 'naf'
|
9
9
|
s.version = Naf::VERSION
|
10
10
|
s.license = 'New BSD License'
|
11
|
-
s.date = '2014-
|
12
|
-
s.summary =
|
13
|
-
s.description =
|
14
|
-
|
15
|
-
s.authors = [
|
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
|
22
|
-
s.add_dependency
|
23
|
-
s.add_dependency
|
24
|
-
s.add_dependency
|
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
|
28
|
-
s.add_development_dependency
|
29
|
-
s.add_development_dependency
|
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 = [
|
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.
|
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-
|
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:
|
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:
|
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
|
-
" <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:' %>
|
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
|
-
|
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
|
-
} %>
|