xp5k 0.0.1 → 0.0.4

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.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: