priteau-vizir 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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 for now.
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
- Configure Growl to accept notifications. Go to the Growl preference panel, and in the Network options enable "Listen for incoming notifications" and "Allow remote application registration". Don't forget to setup a password.
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 it in the background, using the <tt>--login</tt> switch with your Grid'5000 login name and the <tt>--password</tt> switch with your Growl password.
24
+ Run Vizir in the background, using the <tt>--login</tt> switch with your Grid'5000 login name.
23
25
 
24
- $ vizir --login priteau --password mygrowlpassword &
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.2
1
+ 0.2.0
data/bin/vizir CHANGED
@@ -1,16 +1,22 @@
1
- #!/usr/bin/env ruby -w
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 'ruby-growl'
11
+ require 'vizir'
8
12
 
9
- ALERT_TIME = 600
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 ] [ -p | --password mygrowlpassword ]'
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 notify_via_growl(jobid, site_name, time, time_unit)
42
- g = Growl.new("localhost", "Vizir", ["Job ending soon"], nil, $password)
43
- g.notify("Job ending soon", "OAR job terminating soon", "Job #{jobid} in #{site_name} ending in #{time} #{time_unit}.")
47
+ def setup_growl
48
+ $growl = Growl::Notifier.sharedInstance
49
+ $growl.register('Vizir', ['Job ending soon'])
44
50
  end
45
51
 
46
- def get_remaining_time(starttime, walltime)
47
- remaining_sec = (Time.at(starttime + walltime) - Time.now).round
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 humanize_time(time)
51
- if time > 60 then
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 or $password == 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
- sites = get(api, '/sites')
77
- if sites == nil then
78
- exit 1
79
- end
80
- sites.each do |site|
81
- site_name = site['site']
82
- unless IGNORE_SITES.include?(site_name)
83
- jobs = get(api, "#{site['uri']}/jobs")
84
- if jobs == nil then
85
- break
86
- end
87
- jobs.each do |job|
88
- if job['owner'] == $login then
89
- job_details = get(api, "#{job['uri']}")
90
- if job_details == nil then
91
- break
92
- end
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
@@ -1,6 +1,5 @@
1
1
  require 'rubygems'
2
2
  require 'test/unit'
3
- require 'shoulda'
4
3
 
5
4
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
5
  $LOAD_PATH.unshift(File.dirname(__FILE__))
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
- should "probably rename this file and start testing for real" do
5
- flunk "hey buddy, you should probably rename this file and start testing for real"
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.1.2"
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-05-29}
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.1.2
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-05-29 00:00:00 -07:00
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