naf 2.1.9 → 2.1.10
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.
- 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
|
-
} %>
|