priteau-vizir 0.1.2 → 0.2.0
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/README.rdoc +6 -4
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/bin/vizir +74 -43
- data/lib/vizir.rb +29 -0
- data/test/test_helper.rb +0 -1
- data/test/vizir_test.rb +12 -2
- data/vizir.gemspec +5 -2
- metadata +12 -2
data/README.rdoc
CHANGED
@@ -7,21 +7,23 @@ Ever been disconnected from Grid'5000 machines with a message like this, losing
|
|
7
7
|
Vizir is a simple Ruby script that monitors your interactive jobs on Grid'5000[http://www.grid5000.fr/].
|
8
8
|
It triggers Growl[http://growl.info/] notifications when your reservations are going to terminate, allowing you to save your work and/or your deployed environments.
|
9
9
|
|
10
|
-
Vizir only supports Mac OS X
|
10
|
+
Vizir only supports Mac OS X.
|
11
11
|
|
12
12
|
== Getting Started
|
13
13
|
|
14
14
|
Run the following if you haven't already:
|
15
|
+
|
15
16
|
$ gem sources -a http://gems.github.com
|
16
17
|
|
17
18
|
Install the gem:
|
19
|
+
|
18
20
|
$ sudo gem install priteau-vizir
|
19
21
|
|
20
|
-
|
22
|
+
Vizir uses HotCocoa to trigger Growl notifications. HotCocoa is shipped with Mac OS X 10.5, so it should work out of the box on Leopard.
|
21
23
|
|
22
|
-
Run
|
24
|
+
Run Vizir in the background, using the <tt>--login</tt> switch with your Grid'5000 login name.
|
23
25
|
|
24
|
-
$ vizir --login priteau
|
26
|
+
$ vizir --login priteau &
|
25
27
|
|
26
28
|
== Getting the source
|
27
29
|
|
data/Rakefile
CHANGED
@@ -9,6 +9,7 @@ begin
|
|
9
9
|
gem.email = "pierre.riteau@gmail.com"
|
10
10
|
gem.homepage = "http://github.com/priteau/vizir"
|
11
11
|
gem.authors = ["Pierre Riteau"]
|
12
|
+
gem.add_dependency "eventmachine"
|
12
13
|
gem.add_dependency "json"
|
13
14
|
gem.add_dependency "net-ssh-gateway"
|
14
15
|
gem.add_dependency "rest-client"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/bin/vizir
CHANGED
@@ -1,16 +1,22 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
1
|
+
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
4
|
+
|
5
|
+
require 'eventmachine'
|
6
|
+
require 'growl'
|
3
7
|
require 'json'
|
4
8
|
require 'net/ssh/gateway'
|
5
9
|
require 'optparse'
|
6
10
|
require 'rest_client'
|
7
|
-
require '
|
11
|
+
require 'vizir'
|
8
12
|
|
9
|
-
|
13
|
+
FIRST_ALERT_TIME = 600
|
14
|
+
ALERT_PERIOD = 60
|
15
|
+
REFRESH_TIME = 3600
|
10
16
|
IGNORE_SITES = ['grenoble-exp', 'grenoble-ext', 'grenoble-obs', 'luxembourg', 'portoalegre']
|
11
17
|
|
12
18
|
def usage
|
13
|
-
puts 'usage: vizir [ -h | --help ] [ -l | --login login_name ]
|
19
|
+
puts 'usage: vizir [ -h | --help ] [ -l | --login login_name ]'
|
14
20
|
exit 1
|
15
21
|
end
|
16
22
|
|
@@ -38,63 +44,50 @@ def apiuri(port)
|
|
38
44
|
return "https://localhost:#{port}/oargridapi"
|
39
45
|
end
|
40
46
|
|
41
|
-
def
|
42
|
-
|
43
|
-
|
47
|
+
def setup_growl
|
48
|
+
$growl = Growl::Notifier.sharedInstance
|
49
|
+
$growl.register('Vizir', ['Job ending soon'])
|
44
50
|
end
|
45
51
|
|
46
|
-
def
|
47
|
-
|
52
|
+
def notify_via_growl(jobid, site_name, time, time_unit)
|
53
|
+
$growl.notify('Job ending soon', 'OAR job terminating soon', "Job #{jobid} in #{site_name} ending in #{time} #{time_unit}.")
|
48
54
|
end
|
49
55
|
|
50
|
-
def
|
51
|
-
|
52
|
-
remaining_time = time / 60
|
53
|
-
remaining_time_unit = "minutes"
|
54
|
-
else
|
55
|
-
remaining_time = time
|
56
|
-
remaining_time_unit = "seconds"
|
57
|
-
end
|
58
|
-
return remaining_time, remaining_time_unit
|
56
|
+
def get_remaining_time(time)
|
57
|
+
return (time - Time.now).round
|
59
58
|
end
|
60
59
|
|
61
60
|
$login = nil
|
62
|
-
$password = nil
|
63
61
|
opts = OptionParser.new
|
64
62
|
opts.on('-h', '--help') { usage }
|
65
63
|
opts.on('-l', '--login STRING', String) { |str| $login = str }
|
66
|
-
opts.on('-p', '--password STRING', String) { |str| $password = str }
|
67
64
|
opts.parse(ARGV)
|
68
65
|
|
69
|
-
if $login == nil
|
66
|
+
if $login == nil
|
70
67
|
usage
|
71
68
|
end
|
72
69
|
|
73
70
|
gateway, port = setup_ssh_tunnel
|
74
71
|
api = RestClient::Resource.new(apiuri(port))
|
72
|
+
setup_growl
|
75
73
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
if job_details['jobType'] == 'INTERACTIVE' then
|
94
|
-
remaining_sec = get_remaining_time(Integer(job_details['startTime']), Integer(job_details['walltime']))
|
95
|
-
if remaining_sec < ALERT_TIME then
|
96
|
-
remaining_time, remaining_time_unit = humanize_time(remaining_sec)
|
97
|
-
notify_via_growl(job_details['Job_Id'], site_name.capitalize, remaining_time, remaining_time_unit)
|
74
|
+
def learn_new_jobs(api)
|
75
|
+
$sites.each do |site|
|
76
|
+
site_name = site['site']
|
77
|
+
unless IGNORE_SITES.include?(site_name)
|
78
|
+
jobs = get(api, "#{site['uri']}/jobs")
|
79
|
+
break if jobs == nil
|
80
|
+
jobs.each do |job|
|
81
|
+
if job['owner'] == $login
|
82
|
+
job_details = get(api, "#{job['uri']}")
|
83
|
+
break if job_details == nil
|
84
|
+
if job_details['jobType'] == 'INTERACTIVE'
|
85
|
+
jobid = job_details['Job_Id']
|
86
|
+
|
87
|
+
# If we don't yet know the job, record it in $jobs
|
88
|
+
if $jobs[jobid].nil?
|
89
|
+
$jobs[jobid] = Vizir::Job.new(jobid, Time.at(Integer(job_details['startTime']) + Integer(job_details['walltime'])), site_name.capitalize)
|
90
|
+
end
|
98
91
|
end
|
99
92
|
end
|
100
93
|
end
|
@@ -102,4 +95,42 @@ sites.each do |site|
|
|
102
95
|
end
|
103
96
|
end
|
104
97
|
|
98
|
+
def first_ending_job
|
99
|
+
$jobs.sort{|a,b| a[1].end_time <=> b[1].end_time}.first
|
100
|
+
end
|
101
|
+
|
102
|
+
def alert_jobs(api)
|
103
|
+
$jobs.each do |jobid, job|
|
104
|
+
remaining_sec = get_remaining_time(job.end_time)
|
105
|
+
if remaining_sec < FIRST_ALERT_TIME
|
106
|
+
# Check if the job still exists before sending a notification
|
107
|
+
updatedjob = get(api, "/sites/#{job.site_name.downcase}/jobs/#{job.id}")
|
108
|
+
if updatedjob['state'] != 'Running'
|
109
|
+
# Job is not running anymore, remove it from the hash
|
110
|
+
$jobs.delete(jobid)
|
111
|
+
next
|
112
|
+
end
|
113
|
+
if remaining_sec < 0
|
114
|
+
$stderr.puts "Error: negative time"
|
115
|
+
next
|
116
|
+
end
|
117
|
+
remaining_time, remaining_time_unit = Vizir.humanize_time(remaining_sec)
|
118
|
+
notify_via_growl(jobid, job.site_name, remaining_time, remaining_time_unit)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Learn the Grid'5000 sites
|
124
|
+
$jobs = Hash.new
|
125
|
+
$sites = get(api, '/sites')
|
126
|
+
exit 1 if $sites == nil
|
127
|
+
|
128
|
+
learn_new_jobs(api)
|
129
|
+
alert_jobs(api)
|
130
|
+
|
131
|
+
EventMachine::run {
|
132
|
+
EventMachine::PeriodicTimer.new(REFRESH_TIME) { learn_new_jobs(api) }
|
133
|
+
EventMachine::PeriodicTimer.new(ALERT_PERIOD) { alert_jobs(api) }
|
134
|
+
}
|
135
|
+
|
105
136
|
gateway.shutdown!
|
data/lib/vizir.rb
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
module Vizir
|
2
|
+
def Vizir.humanize_time(time)
|
3
|
+
fail "Can't humanize negative period" if time < 0
|
4
|
+
|
5
|
+
if time >= 60
|
6
|
+
remaining_time = time / 60
|
7
|
+
remaining_time_unit = "minute"
|
8
|
+
else
|
9
|
+
remaining_time = time
|
10
|
+
remaining_time_unit = "second"
|
11
|
+
end
|
12
|
+
|
13
|
+
if remaining_time > 1
|
14
|
+
remaining_time_unit += "s"
|
15
|
+
end
|
16
|
+
|
17
|
+
return remaining_time, remaining_time_unit
|
18
|
+
end
|
19
|
+
|
20
|
+
class Job
|
21
|
+
attr_reader :id, :end_time, :site_name
|
22
|
+
|
23
|
+
def initialize(id, end_time, site_name)
|
24
|
+
@id = id
|
25
|
+
@end_time = end_time
|
26
|
+
@site_name = site_name
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/test/test_helper.rb
CHANGED
data/test/vizir_test.rb
CHANGED
@@ -1,7 +1,17 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class VizirTest < Test::Unit::TestCase
|
4
|
-
|
5
|
-
|
4
|
+
TIMES = [
|
5
|
+
[1, [1, "second"]],
|
6
|
+
[30, [30, "seconds"]],
|
7
|
+
[59, [59, "seconds"]],
|
8
|
+
[60, [1, "minute"]],
|
9
|
+
[120, [2, "minutes"]]
|
10
|
+
]
|
11
|
+
def test_humanize_time
|
12
|
+
TIMES.each do |seconds, result|
|
13
|
+
assert_equal(result, Vizir.humanize_time(seconds))
|
14
|
+
end
|
15
|
+
assert_raise(RuntimeError) { Vizir.humanize_time(-1) }
|
6
16
|
end
|
7
17
|
end
|
data/vizir.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{vizir}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.2.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Pierre Riteau"]
|
9
|
-
s.date = %q{2009-
|
9
|
+
s.date = %q{2009-06-01}
|
10
10
|
s.default_executable = %q{vizir}
|
11
11
|
s.email = %q{pierre.riteau@gmail.com}
|
12
12
|
s.executables = ["vizir"]
|
@@ -43,17 +43,20 @@ Gem::Specification.new do |s|
|
|
43
43
|
s.specification_version = 2
|
44
44
|
|
45
45
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
46
|
+
s.add_runtime_dependency(%q<eventmachine>, [">= 0"])
|
46
47
|
s.add_runtime_dependency(%q<json>, [">= 0"])
|
47
48
|
s.add_runtime_dependency(%q<net-ssh-gateway>, [">= 0"])
|
48
49
|
s.add_runtime_dependency(%q<rest-client>, [">= 0"])
|
49
50
|
s.add_runtime_dependency(%q<ruby-growl>, [">= 0"])
|
50
51
|
else
|
52
|
+
s.add_dependency(%q<eventmachine>, [">= 0"])
|
51
53
|
s.add_dependency(%q<json>, [">= 0"])
|
52
54
|
s.add_dependency(%q<net-ssh-gateway>, [">= 0"])
|
53
55
|
s.add_dependency(%q<rest-client>, [">= 0"])
|
54
56
|
s.add_dependency(%q<ruby-growl>, [">= 0"])
|
55
57
|
end
|
56
58
|
else
|
59
|
+
s.add_dependency(%q<eventmachine>, [">= 0"])
|
57
60
|
s.add_dependency(%q<json>, [">= 0"])
|
58
61
|
s.add_dependency(%q<net-ssh-gateway>, [">= 0"])
|
59
62
|
s.add_dependency(%q<rest-client>, [">= 0"])
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: priteau-vizir
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pierre Riteau
|
@@ -9,9 +9,19 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-06-01 00:00:00 -07:00
|
13
13
|
default_executable: vizir
|
14
14
|
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: eventmachine
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
15
25
|
- !ruby/object:Gem::Dependency
|
16
26
|
name: json
|
17
27
|
type: :runtime
|