bookie_accounting 2.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/Rakefile +0 -7
- data/TODO +13 -0
- data/bookie_accounting.gemspec +1 -9
- data/lib/bookie/database.rb +17 -19
- data/lib/bookie/database/group.rb +3 -3
- data/lib/bookie/database/job.rb +21 -18
- data/lib/bookie/database/job_summary.rb +26 -29
- data/lib/bookie/database/lock.rb +4 -4
- data/lib/bookie/database/system_type.rb +6 -6
- data/lib/bookie/database/user.rb +5 -5
- data/lib/bookie/formatters/stdout.rb +9 -7
- data/lib/bookie/version.rb +1 -1
- data/spec/config_spec.rb +21 -21
- data/spec/database/group_spec.rb +13 -14
- data/spec/database/job_spec.rb +62 -63
- data/spec/database/job_summary_spec.rb +60 -62
- data/spec/database/lock_spec.rb +11 -12
- data/spec/database/system_spec.rb +49 -50
- data/spec/database/system_type_spec.rb +14 -15
- data/spec/database/user_spec.rb +25 -26
- data/spec/extensions_spec.rb +11 -11
- data/spec/formatter_spec.rb +15 -15
- data/spec/formatters/comma_dump_spec.rb +8 -8
- data/spec/formatters/spreadsheet_spec.rb +9 -9
- data/spec/formatters/stdout_spec.rb +8 -8
- data/spec/sender_spec.rb +44 -46
- data/spec/senders/standalone_spec.rb +9 -11
- data/spec/senders/torque_cluster_spec.rb +31 -31
- metadata +14 -43
- data/todo.txt +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c891f54836ddb4da00b36831ab8a62dcea1b8cb
|
4
|
+
data.tar.gz: 5afc39ea463dcf38dfee8d4526e83185b160b697
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ad6f4d440ef1c1537a584aa99937bcee203227b0d233805405210e92398dd87c00b7f870fedaefb04ed6de3d39961b682b3c32df2453154389ffbfe1a320c99
|
7
|
+
data.tar.gz: e28d51f6afa886edc644e8a526473efd2b9dd26db271e82b543a4c289bc251ab4e4721af5eb3fe2682cfd1598a458031b8287825198d2976b987b07ed3e08b87
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -10,13 +10,6 @@ task :default => :spec
|
|
10
10
|
desc "Run specs"
|
11
11
|
RSpec::Core::RakeTask.new(:spec) do |task|
|
12
12
|
task.rspec_opts =%w{--color --order rand --format progress}
|
13
|
-
paths = []
|
14
|
-
Find.find('spec') do |path|
|
15
|
-
if File.directory?(path)
|
16
|
-
paths << "#{path}/*_spec.rb"
|
17
|
-
end
|
18
|
-
end
|
19
|
-
task.pattern = paths.join(" ")
|
20
13
|
end
|
21
14
|
|
22
15
|
task :rdoc do
|
data/TODO
CHANGED
@@ -1 +1,14 @@
|
|
1
|
+
Use bulk inserts?
|
2
|
+
Replace by_* methods with a "find_all_by()" method? (or just "where"...)
|
3
|
+
Allow configuration of date boundary to midnight in local time zone?
|
4
|
+
Make sure all source files have the required "require"s
|
5
|
+
Use "let" in RSpect tests?
|
6
|
+
Replace 3600 with 2.hours, etc.
|
7
|
+
Also clear out other "magic" numbers.
|
8
|
+
Split some tests up.
|
9
|
+
Validate uniqueness?
|
10
|
+
Unit test uniqueness constraints?
|
11
|
+
Use optimistic concurrency control?
|
12
|
+
Make units more independent.
|
13
|
+
Make unit test success more independent.
|
1
14
|
|
data/bookie_accounting.gemspec
CHANGED
@@ -15,18 +15,10 @@ Gem::Specification.new do |gem|
|
|
15
15
|
gem.name = "bookie_accounting"
|
16
16
|
gem.require_paths = ["lib"]
|
17
17
|
gem.version = Bookie::VERSION
|
18
|
-
|
18
|
+
|
19
19
|
gem.add_dependency('activerecord')
|
20
20
|
gem.add_dependency('json')
|
21
|
-
#We need this because Bundler has no concept of optional dependencies
|
22
|
-
#and complains about using non-dependency gems.
|
23
|
-
#TODO: figure out how to remove
|
24
|
-
gem.add_dependency('mysql2')
|
25
21
|
gem.add_dependency('pacct')
|
26
|
-
#Introduces the old ActiveRecord mass assignment security methods
|
27
|
-
#(until I update the database code for the new methods)
|
28
|
-
#TODO: get rid of this.
|
29
|
-
gem.add_dependency('protected_attributes')
|
30
22
|
gem.add_dependency('spreadsheet')
|
31
23
|
end
|
32
24
|
|
data/lib/bookie/database.rb
CHANGED
@@ -2,8 +2,6 @@ require 'bookie/config'
|
|
2
2
|
require 'bookie/extensions'
|
3
3
|
|
4
4
|
require 'active_record'
|
5
|
-
#TODO: remove when code is updated.
|
6
|
-
require 'protected_attributes'
|
7
5
|
|
8
6
|
require 'bookie/database/job'
|
9
7
|
require 'bookie/database/job_summary'
|
@@ -21,7 +19,7 @@ module Bookie
|
|
21
19
|
#- <tt>:avg => 1</tt>
|
22
20
|
#- <tt>:max => 2</tt>
|
23
21
|
#
|
24
|
-
|
22
|
+
|
25
23
|
##
|
26
24
|
#Database migrations
|
27
25
|
module Migration
|
@@ -35,12 +33,12 @@ module Bookie
|
|
35
33
|
t.index [:name, :group_id], :unique => true
|
36
34
|
end
|
37
35
|
end
|
38
|
-
|
36
|
+
|
39
37
|
def down
|
40
38
|
drop_table :users
|
41
39
|
end
|
42
40
|
end
|
43
|
-
|
41
|
+
|
44
42
|
class CreateGroups < ActiveRecord::Migration
|
45
43
|
def up
|
46
44
|
create_table :groups do |t|
|
@@ -50,12 +48,12 @@ module Bookie
|
|
50
48
|
t.index :name, :unique => true
|
51
49
|
end
|
52
50
|
end
|
53
|
-
|
51
|
+
|
54
52
|
def down
|
55
53
|
drop_table :groups
|
56
54
|
end
|
57
55
|
end
|
58
|
-
|
56
|
+
|
59
57
|
class CreateSystems < ActiveRecord::Migration
|
60
58
|
def up
|
61
59
|
create_table :systems do |t|
|
@@ -73,12 +71,12 @@ module Bookie
|
|
73
71
|
t.index :system_type_id
|
74
72
|
end
|
75
73
|
end
|
76
|
-
|
74
|
+
|
77
75
|
def down
|
78
76
|
drop_table :systems
|
79
77
|
end
|
80
78
|
end
|
81
|
-
|
79
|
+
|
82
80
|
class CreateSystemTypes < ActiveRecord::Migration
|
83
81
|
def up
|
84
82
|
create_table :system_types do |t|
|
@@ -89,12 +87,12 @@ module Bookie
|
|
89
87
|
t.index :name, :unique => true
|
90
88
|
end
|
91
89
|
end
|
92
|
-
|
90
|
+
|
93
91
|
def down
|
94
92
|
drop_table :system_types
|
95
93
|
end
|
96
94
|
end
|
97
|
-
|
95
|
+
|
98
96
|
class CreateJobs < ActiveRecord::Migration
|
99
97
|
def up
|
100
98
|
create_table :jobs do |t|
|
@@ -118,12 +116,12 @@ module Bookie
|
|
118
116
|
t.index :exit_code
|
119
117
|
end
|
120
118
|
end
|
121
|
-
|
119
|
+
|
122
120
|
def down
|
123
121
|
drop_table :jobs
|
124
122
|
end
|
125
123
|
end
|
126
|
-
|
124
|
+
|
127
125
|
class CreateJobSummaries < ActiveRecord::Migration
|
128
126
|
def up
|
129
127
|
create_table :job_summaries do |t|
|
@@ -140,12 +138,12 @@ module Bookie
|
|
140
138
|
t.index :date
|
141
139
|
end
|
142
140
|
end
|
143
|
-
|
141
|
+
|
144
142
|
def down
|
145
143
|
drop_table :job_summaries
|
146
144
|
end
|
147
145
|
end
|
148
|
-
|
146
|
+
|
149
147
|
class CreateLocks < ActiveRecord::Migration
|
150
148
|
def up
|
151
149
|
create_table :locks do |t|
|
@@ -154,17 +152,17 @@ module Bookie
|
|
154
152
|
change_table :locks do |t|
|
155
153
|
t.index :name, :unique => true
|
156
154
|
end
|
157
|
-
|
155
|
+
|
158
156
|
['users', 'groups', 'systems', 'system_types', 'job_summaries'].each do |name|
|
159
157
|
Lock.create!(:name => name)
|
160
158
|
end
|
161
159
|
end
|
162
|
-
|
160
|
+
|
163
161
|
def down
|
164
162
|
drop_table :locks
|
165
163
|
end
|
166
164
|
end
|
167
|
-
|
165
|
+
|
168
166
|
class << self;
|
169
167
|
##
|
170
168
|
#Brings up all migrations
|
@@ -178,7 +176,7 @@ module Bookie
|
|
178
176
|
CreateJobSummaries.new.up
|
179
177
|
CreateLocks.new.up
|
180
178
|
end
|
181
|
-
|
179
|
+
|
182
180
|
##
|
183
181
|
#Brings down all migrations
|
184
182
|
#
|
@@ -19,14 +19,14 @@ module Bookie
|
|
19
19
|
group = known_groups[name] if known_groups
|
20
20
|
unless group
|
21
21
|
Lock[:groups].synchronize do
|
22
|
-
group =
|
23
|
-
group ||= create!(:
|
22
|
+
group = find_by(name: name)
|
23
|
+
group ||= create!(name: name)
|
24
24
|
end
|
25
25
|
known_groups[name] = group if known_groups
|
26
26
|
end
|
27
27
|
group
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
validates_presence_of :name
|
31
31
|
end
|
32
32
|
end
|
data/lib/bookie/database/job.rb
CHANGED
@@ -21,7 +21,7 @@ module Bookie
|
|
21
21
|
belongs_to :system
|
22
22
|
has_one :group, :through => :user
|
23
23
|
has_one :system_type, :through => :system
|
24
|
-
|
24
|
+
|
25
25
|
##
|
26
26
|
#The time at which the job ended
|
27
27
|
def end_time
|
@@ -33,17 +33,17 @@ module Bookie
|
|
33
33
|
end
|
34
34
|
|
35
35
|
#To consider: disable #end_time= ?
|
36
|
-
|
36
|
+
|
37
37
|
def self.by_user(user)
|
38
38
|
where('jobs.user_id = ?', user.id)
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
##
|
42
42
|
#Filters by user name
|
43
43
|
def self.by_user_name(user_name)
|
44
44
|
joins(:user).where('users.name = ?', user_name)
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
def self.by_system(system)
|
48
48
|
where('jobs.system_id = ?', system.id)
|
49
49
|
end
|
@@ -53,27 +53,30 @@ module Bookie
|
|
53
53
|
def self.by_system_name(system_name)
|
54
54
|
joins(:system).where('systems.name = ?', system_name)
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
##
|
58
58
|
#Filters by group name
|
59
59
|
def self.by_group_name(group_name)
|
60
|
-
group = Group.
|
61
|
-
|
62
|
-
|
60
|
+
group = Group.find_by(name: group_name)
|
61
|
+
if group then
|
62
|
+
joins(:user).where('users.group_id = ?', group.id)
|
63
|
+
else
|
64
|
+
self.none
|
65
|
+
end
|
63
66
|
end
|
64
|
-
|
67
|
+
|
65
68
|
##
|
66
69
|
#Filters by system type
|
67
70
|
def self.by_system_type(system_type)
|
68
71
|
joins(:system).where('systems.system_type_id = ?', system_type.id)
|
69
72
|
end
|
70
|
-
|
73
|
+
|
71
74
|
##
|
72
75
|
#Filters by command name
|
73
76
|
def self.by_command_name(c_name)
|
74
77
|
where('jobs.command_name = ?', c_name)
|
75
78
|
end
|
76
|
-
|
79
|
+
|
77
80
|
##
|
78
81
|
#Finds all jobs that were running at some point in a given time range
|
79
82
|
def self.by_time_range(time_range)
|
@@ -100,7 +103,7 @@ module Bookie
|
|
100
103
|
where('? <= jobs.start_time AND jobs.end_time <= ?', time_range.begin, time_range.end)
|
101
104
|
end
|
102
105
|
end
|
103
|
-
|
106
|
+
|
104
107
|
##
|
105
108
|
#Finds all jobs that overlap the edges of the given time range
|
106
109
|
def self.overlapping_edges(time_range)
|
@@ -112,7 +115,7 @@ module Bookie
|
|
112
115
|
where(query_str, {:begin => time_range.begin, :end => time_range.end})
|
113
116
|
end
|
114
117
|
end
|
115
|
-
|
118
|
+
|
116
119
|
##
|
117
120
|
#Produces a summary of the jobs in the given time interval
|
118
121
|
#
|
@@ -177,22 +180,22 @@ module Bookie
|
|
177
180
|
:memory_time => memory_time,
|
178
181
|
}
|
179
182
|
end
|
180
|
-
|
183
|
+
|
181
184
|
before_save do
|
182
185
|
write_attribute(:end_time, end_time)
|
183
186
|
end
|
184
|
-
|
187
|
+
|
185
188
|
before_update do
|
186
189
|
write_attribute(:end_time, end_time)
|
187
190
|
end
|
188
|
-
|
191
|
+
|
189
192
|
validates_presence_of :user, :system, :cpu_time,
|
190
193
|
:start_time, :wall_time, :memory, :exit_code
|
191
|
-
|
194
|
+
|
192
195
|
validates_each :command_name do |record, attr, value|
|
193
196
|
record.errors.add(attr, 'must not be nil') if value == nil
|
194
197
|
end
|
195
|
-
|
198
|
+
|
196
199
|
validates_each :cpu_time, :wall_time, :memory do |record, attr, value|
|
197
200
|
record.errors.add(attr, 'must be a non-negative integer') unless value && value >= 0
|
198
201
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'active_record'
|
2
|
-
require 'protected_attributes'
|
3
2
|
|
4
3
|
require 'bookie/database/job'
|
5
4
|
require 'bookie/database/system'
|
@@ -13,12 +12,10 @@ module Bookie
|
|
13
12
|
#Most summary operations should be performed through this class to improve efficiency.
|
14
13
|
class JobSummary < ActiveRecord::Base
|
15
14
|
self.table_name = :job_summaries
|
16
|
-
|
15
|
+
|
17
16
|
belongs_to :user
|
18
17
|
belongs_to :system
|
19
18
|
|
20
|
-
attr_accessible :date, :user, :user_id, :system, :system_id, :command_name, :cpu_time, :memory_time
|
21
|
-
|
22
19
|
##
|
23
20
|
#Filters by date
|
24
21
|
def self.by_date(date)
|
@@ -35,25 +32,25 @@ module Bookie
|
|
35
32
|
where('? <= job_summaries.date AND job_summaries.date <= ?', range.begin, range.end)
|
36
33
|
end
|
37
34
|
end
|
38
|
-
|
35
|
+
|
39
36
|
##
|
40
37
|
#Filters by user
|
41
38
|
def self.by_user(user)
|
42
39
|
where('job_summaries.user_id = ?', user.id)
|
43
40
|
end
|
44
|
-
|
41
|
+
|
45
42
|
##
|
46
43
|
#Filters by user name
|
47
44
|
def self.by_user_name(name)
|
48
45
|
joins(:user).where('users.name = ?', name)
|
49
46
|
end
|
50
|
-
|
47
|
+
|
51
48
|
##
|
52
49
|
#Filters by group
|
53
50
|
def self.by_group(group)
|
54
51
|
joins(:user).where('users.group_id = ?', group.id)
|
55
52
|
end
|
56
|
-
|
53
|
+
|
57
54
|
##
|
58
55
|
#Filters by group name
|
59
56
|
def self.by_group_name(name)
|
@@ -64,31 +61,31 @@ module Bookie
|
|
64
61
|
self.none
|
65
62
|
end
|
66
63
|
end
|
67
|
-
|
64
|
+
|
68
65
|
##
|
69
66
|
#Filters by system
|
70
67
|
def self.by_system(system)
|
71
68
|
where('job_summaries.system_id = ?', system.id)
|
72
69
|
end
|
73
|
-
|
70
|
+
|
74
71
|
##
|
75
72
|
#Filters by system name
|
76
73
|
def self.by_system_name(name)
|
77
74
|
joins(:system).where('systems.name = ?', name)
|
78
75
|
end
|
79
|
-
|
76
|
+
|
80
77
|
##
|
81
78
|
#Filters by system type
|
82
79
|
def self.by_system_type(type)
|
83
80
|
joins(:system).where('systems.system_type_id = ?', type.id)
|
84
81
|
end
|
85
|
-
|
82
|
+
|
86
83
|
##
|
87
84
|
#Filters by command name
|
88
85
|
def self.by_command_name(cmd)
|
89
86
|
where('job_summaries.command_name = ?', cmd)
|
90
87
|
end
|
91
|
-
|
88
|
+
|
92
89
|
##
|
93
90
|
#Create cached summaries for the given date
|
94
91
|
#
|
@@ -100,12 +97,12 @@ module Bookie
|
|
100
97
|
def self.summarize(date)
|
101
98
|
jobs = Job
|
102
99
|
unscoped = self.unscoped
|
103
|
-
time_min = date.to_utc_time
|
100
|
+
time_min = date.to_utc_time
|
104
101
|
time_range = time_min ... time_min + 1.days
|
105
102
|
day_jobs = jobs.by_time_range(time_range)
|
106
103
|
|
107
104
|
#Find the unique combinations of values for some of the jobs' attributes.
|
108
|
-
value_sets = day_jobs.
|
105
|
+
value_sets = day_jobs.uniq.pluck(:user_id, :system_id, :command_name)
|
109
106
|
if value_sets.empty?
|
110
107
|
#There are no jobs, so create a dummy summary.
|
111
108
|
user = User.select(:id).first
|
@@ -128,17 +125,17 @@ module Bookie
|
|
128
125
|
else
|
129
126
|
value_sets.each do |set|
|
130
127
|
summary_jobs = jobs.where(
|
131
|
-
:user_id => set
|
132
|
-
:system_id => set
|
133
|
-
:command_name => set
|
128
|
+
:user_id => set[0],
|
129
|
+
:system_id => set[1],
|
130
|
+
:command_name => set[2]
|
134
131
|
)
|
135
132
|
summary = summary_jobs.summary(time_range)
|
136
133
|
Lock[:job_summaries].synchronize do
|
137
134
|
sum = unscoped.find_or_initialize_by(
|
138
135
|
:date => date,
|
139
|
-
:user_id => set
|
140
|
-
:system_id => set
|
141
|
-
:command_name => set
|
136
|
+
:user_id => set[0],
|
137
|
+
:system_id => set[1],
|
138
|
+
:command_name => set[2]
|
142
139
|
)
|
143
140
|
sum.cpu_time = summary[:cpu_time]
|
144
141
|
sum.memory_time = summary[:memory_time]
|
@@ -147,7 +144,7 @@ module Bookie
|
|
147
144
|
end
|
148
145
|
end
|
149
146
|
end
|
150
|
-
|
147
|
+
|
151
148
|
##
|
152
149
|
#Returns a summary of jobs in the database
|
153
150
|
#
|
@@ -178,7 +175,7 @@ module Bookie
|
|
178
175
|
end
|
179
176
|
|
180
177
|
time_range = time_range.normalized
|
181
|
-
|
178
|
+
|
182
179
|
date_begin = time_range.begin.utc.to_date
|
183
180
|
rounded_date_begin = false
|
184
181
|
#Round date_begin up.
|
@@ -199,7 +196,7 @@ module Bookie
|
|
199
196
|
successful = jobs_in_range.where('jobs.exit_code = 0').count
|
200
197
|
cpu_time = 0
|
201
198
|
memory_time = 0
|
202
|
-
|
199
|
+
|
203
200
|
#To consider: check if num_jobs is zero so we can skip all this?
|
204
201
|
if rounded_date_begin
|
205
202
|
#We need to get a summary for the chunk up to the first whole day.
|
@@ -218,7 +215,7 @@ module Bookie
|
|
218
215
|
end
|
219
216
|
|
220
217
|
date_range = date_begin ... date_end
|
221
|
-
|
218
|
+
|
222
219
|
#Now we can process the cached summaries.
|
223
220
|
unscoped = self.unscoped
|
224
221
|
summaries = by_date_range(date_range).order(:date).to_a
|
@@ -245,7 +242,7 @@ module Bookie
|
|
245
242
|
end
|
246
243
|
index = new_index
|
247
244
|
end
|
248
|
-
|
245
|
+
|
249
246
|
{
|
250
247
|
:num_jobs => num_jobs,
|
251
248
|
:successful => successful,
|
@@ -253,13 +250,13 @@ module Bookie
|
|
253
250
|
:memory_time => memory_time,
|
254
251
|
}
|
255
252
|
end
|
256
|
-
|
253
|
+
|
257
254
|
validates_presence_of :user_id, :system_id, :date, :cpu_time, :memory_time
|
258
|
-
|
255
|
+
|
259
256
|
validates_each :command_name do |record, attr, value|
|
260
257
|
record.errors.add(attr, 'must not be nil') if value == nil
|
261
258
|
end
|
262
|
-
|
259
|
+
|
263
260
|
validates_each :cpu_time, :memory_time do |record, attr, value|
|
264
261
|
record.errors.add(attr, 'must be a non-negative integer') unless value && value >= 0
|
265
262
|
end
|