xp5k 0.0.1 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,2 +1,82 @@
1
- Work in progress.
1
+ ## Capistrano sample
2
+
3
+ require 'xp5k'
4
+
5
+ XP5K::Config.load
6
+
7
+ @myxp = XP5K::XP.new(:logger => logger)
8
+
9
+ @myxp.define_job({
10
+ :resources => "nodes=2,walltime=1",
11
+ :site => XP5K::Config[:site] || 'rennes',
12
+ :types => ["deploy"],
13
+ :name => "job1",
14
+ :command => "sleep 86400"
15
+ })
16
+
17
+ @myxp.define_job({
18
+ :resources => "nodes=6,walltime=1",
19
+ :site => XP5K::Config[:site] || 'rennes',
20
+ :types => ["deploy"],
21
+ :name => "job2",
22
+ :roles => [
23
+ XP5K::Role.new({ :name => 'server', :size => 1 }),
24
+ XP5K::Role.new({ :name => 'nodes', :size => 5 })
25
+ ]
26
+ :command => "sleep 86400"
27
+ })
28
+
29
+ @myxp.define_deployment({
30
+ :site => XP5K::Config[:site] || 'rennes',
31
+ :environment => "squeeze-x64-nfs",
32
+ :jobs => %w{ job1 },
33
+ :roles => %w{ server }
34
+ :key => File.read(XP5K::Config[:public_key])
35
+ })
36
+
37
+ role :job1 do
38
+ @myxp.job_with_name('job1')['assigned_nodes'].first
39
+ end
40
+
41
+ role :job2 do
42
+ @myxp.job_with_name('job2')['assigned_nodes'].first
43
+ end
44
+
45
+ role :nodes do
46
+ @myxp.role_with_name('nodes').servers
47
+ end
48
+
49
+ desc 'Submit jobs'
50
+ task :submit do
51
+ @myxp.submit
52
+ end
53
+
54
+ desc 'Deploy with Kadeplopy'
55
+ task :deploy do
56
+ @myxp.deploy
57
+ end
58
+
59
+ desc 'Status'
60
+ task :status do
61
+ @myxp.status
62
+ end
63
+
64
+ desc 'Remove all running jobs'
65
+ task :clean do
66
+ logger.debug "Clean all Grid'5000 running jobs..."
67
+ @myxp.clean
68
+ end
69
+
70
+ desc 'Run date command'
71
+ task :date, :roles => [:job1, :job2] do
72
+ set :user, 'root'
73
+ run 'date'
74
+ end
75
+
76
+
77
+ ## _xp.conf_ sample file
78
+
79
+ site 'rennes'
80
+ public_key '/Users/pmorillon/.ssh/id_rsa_g5k.pub'
81
+
2
82
 
data/lib/xp5k/config.rb CHANGED
@@ -14,8 +14,8 @@ module XP5K
14
14
  if File.exist?(File.expand_path(File.join(Dir.pwd, 'xp.conf')))
15
15
  file_path = File.expand_path(File.join(Dir.pwd, 'xp.conf'))
16
16
  self.instance_eval(IO.read(file_path),file_path, 1)
17
+ @@config[:loaded] = true
17
18
  end
18
- @@config[:loaded] = true
19
19
  end # def:: self.load
20
20
 
21
21
  def self.loaded?
@@ -0,0 +1,7 @@
1
+ module XP5K
2
+ class Exceptions
3
+ class Role < RuntimeError; end
4
+ class Config < RuntimeError; end
5
+ end
6
+ end
7
+
data/lib/xp5k/role.rb ADDED
@@ -0,0 +1,23 @@
1
+ class XP5K::Role
2
+
3
+ attr_accessor :name, :size, :desc, :servers, :jobid
4
+
5
+ def initialize(options = {})
6
+ # Required parameters
7
+ @name = ""
8
+ @size = 0
9
+ %w{ name size }.each do |param|
10
+ if options[param.to_sym].nil?
11
+ raise XP5K::Exceptions::Role, "#{self.to_s}: #{param.to_sym} needed at initialization"
12
+ else
13
+ instance_variable_set("@#{param}", options[param.to_sym])
14
+ end
15
+ end
16
+
17
+ # Optional parameters
18
+ %w{ desc servers }.each do |param|
19
+ instance_variable_set("@#{param}", options[param.to_sym])
20
+ end
21
+ end
22
+
23
+ end
data/lib/xp5k/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module XP5K
2
- VERSION='0.0.1'
2
+ VERSION='0.0.4'
3
3
  end
data/lib/xp5k/xp.rb CHANGED
@@ -8,22 +8,23 @@ module XP5K
8
8
 
9
9
  include Term::ANSIColor
10
10
 
11
- attr_accessor :jobs, :jobs2submit, :deployments, :todeploy, :connection
11
+ attr_accessor :jobs, :jobs2submit, :deployments, :todeploy, :connection, :roles
12
12
  attr_reader :starttime
13
13
 
14
14
  def initialize(options = {})
15
- @jobs = []
15
+ @jobs = []
16
16
  @jobs2submit = []
17
17
  @deployments = []
18
- @todeploy = []
19
- @starttime = Time.now
20
- @logger = options[:logger] || Logger.new(STDOUT)
18
+ @todeploy = []
19
+ @roles = []
20
+ @starttime = Time.now
21
+ @logger = options[:logger] || Logger.new(STDOUT)
21
22
  XP5K::Config.load unless XP5K::Config.loaded?
22
23
 
23
24
  @connection = Restfully::Session.new(
24
25
  :configuration_file => "~/.restfully/api.grid5000.fr.yml",
25
26
  :logger => begin
26
- tmplogger = ::Logger.new(STDERR)
27
+ tmplogger = ::Logger.new(STDERR)
27
28
  tmplogger.level = ::Logger::WARN
28
29
  tmplogger
29
30
  end
@@ -35,6 +36,8 @@ module XP5K
35
36
  end
36
37
 
37
38
  def define_deployment(deployment_hash)
39
+ deployment_hash[:jobs] ||= []
40
+ deployment_hash[:roles] ||= []
38
41
  self.todeploy << deployment_hash
39
42
  end
40
43
 
@@ -46,16 +49,19 @@ module XP5K
46
49
  job = self.job_with_name(jobname)
47
50
  x[:nodes] += job["assigned_nodes"]
48
51
  end
52
+ x[:roles].each do |rolename|
53
+ x[:nodes] += role_with_name(rolename).servers
54
+ end
49
55
  deployment = @connection.root.sites[x[:site].to_sym].deployments.submit(x)
50
56
  self.deployments << { :uid => deployment["uid"], :site => deployment["site_uid"] }
51
- update_cache
57
+ #update_cache
52
58
  puts "Waiting for the deployment ##{deployment['uid']} to be terminated..."
53
59
  while deployment.reload['status'] == 'processing'
54
60
  print(".")
55
61
  sleep 10
56
62
  end
57
63
  print(" [#{green("OK")}]\n")
58
- update_cache
64
+ #update_cache
59
65
  end
60
66
  end
61
67
 
@@ -68,9 +74,10 @@ module XP5K
68
74
  uid = datas["jobs"].select { |x| x["name"] == job_hash[:name] }.first["uid"]
69
75
  unless uid.nil?
70
76
  job = @connection.root.sites[job_hash[:site].to_sym].jobs["#{uid}".to_sym]
71
- unless (job.nil? or job["state"] != "running")
77
+ if (not job.nil? or job["state"] == "running")
72
78
  j = job.reload
73
79
  self.jobs << j
80
+ create_roles(j, job_hash) unless job_hash[:roles].nil?
74
81
  end
75
82
  end
76
83
  end
@@ -81,23 +88,45 @@ module XP5K
81
88
  job = self.job_with_name(job2submit[:name])
82
89
  if job.nil?
83
90
  job = @connection.root.sites[job2submit[:site].to_sym].jobs.submit(job2submit)
84
- self.jobs << job
91
+ self.jobs << { :uid => job.properties['uid'], :name => job.properties['name'] }
85
92
  update_cache
86
93
  logger.info "Waiting for the job #{job["name"]} ##{job['uid']} to be running at #{job2submit[:site]}..."
87
94
  while job.reload["state"] != "running"
88
95
  print(".")
89
96
  sleep 3
90
97
  end
98
+ create_roles(job, job2submit) unless job2submit[:roles].nil?
91
99
  print(" [#{green("OK")}]\n")
92
- update_cache
100
+ else
101
+ logger.info "Job #{job["name"]} already submitted ##{job["uid"]}"
93
102
  end
94
103
  end
95
104
  end
96
105
 
106
+ def create_roles(job, job_definition)
107
+ count_needed_nodes = 0
108
+ job_definition[:roles].each { |role| count_needed_nodes += role.size }
109
+ if job['assigned_nodes'].length < count_needed_nodes
110
+ self.clean
111
+ raise "Job ##{job['uid']} require more nodes for required roles"
112
+ end
113
+ available_nodes = job['assigned_nodes'].sort
114
+ job_definition[:roles].each do |role|
115
+ role.servers = available_nodes[0..(role.size - 1)]
116
+ available_nodes -= role.servers
117
+ role.jobid = job['uid']
118
+ self.roles << role
119
+ end
120
+ end
121
+
97
122
  def job_with_name(name)
98
123
  self.jobs.select { |x| x["name"] == name }.first
99
124
  end
100
125
 
126
+ def role_with_name(name)
127
+ self.roles.select { |x| x.name == name}.first
128
+ end
129
+
101
130
  def status
102
131
  # self.jobs2submit.each do |job2submit|
103
132
  # job = self.job_with_name(job2submit[:name])
@@ -125,9 +154,7 @@ module XP5K
125
154
  end
126
155
 
127
156
  def update_cache
128
- cache = { :jobs => self.jobs.collect { |x| x.properties },
129
- :deployments => self.deployments
130
- }
157
+ cache = { :jobs => self.jobs.map { |x| { :uid => x[:uid], :name => x[:name] } } }
131
158
  open(".xp_cache", "w") do |f|
132
159
  f.puts cache.to_json
133
160
  end
data/lib/xp5k.rb CHANGED
@@ -1,5 +1,7 @@
1
+ require 'xp5k/exceptions'
1
2
  require 'xp5k/config'
2
3
  require 'xp5k/xp'
4
+ require 'xp5k/role'
3
5
 
4
6
  module XP5K
5
7
  Config.load
data/xp5k.gemspec CHANGED
@@ -8,6 +8,7 @@ Gem::Specification.new do |s|
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ['Pascal Morillon']
10
10
  s.email = ['pascal.morillon@irisa.fr']
11
+ s.license = 'MIT'
11
12
  s.homepage = 'https://github.com/pmorillon/xp5k'
12
13
  s.summary = %q{A small Grid'5000 helper to submit jobs and deploy environments via REST API}
13
14
  s.description = %q{A small Grid'5000 helper to submit jobs and deploy environments via REST API}
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xp5k
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-04 00:00:00.000000000 Z
12
+ date: 2013-08-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: restfully
@@ -90,11 +90,14 @@ files:
90
90
  - README.md
91
91
  - lib/xp5k.rb
92
92
  - lib/xp5k/config.rb
93
+ - lib/xp5k/exceptions.rb
94
+ - lib/xp5k/role.rb
93
95
  - lib/xp5k/version.rb
94
96
  - lib/xp5k/xp.rb
95
97
  - xp5k.gemspec
96
98
  homepage: https://github.com/pmorillon/xp5k
97
- licenses: []
99
+ licenses:
100
+ - MIT
98
101
  post_install_message:
99
102
  rdoc_options: []
100
103
  require_paths: