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 +81 -1
- data/lib/xp5k/config.rb +1 -1
- data/lib/xp5k/exceptions.rb +7 -0
- data/lib/xp5k/role.rb +23 -0
- data/lib/xp5k/version.rb +1 -1
- data/lib/xp5k/xp.rb +41 -14
- data/lib/xp5k.rb +2 -0
- data/xp5k.gemspec +1 -0
- metadata +6 -3
data/README.md
CHANGED
@@ -1,2 +1,82 @@
|
|
1
|
-
|
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?
|
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
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
|
-
@
|
20
|
-
@
|
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
|
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
|
-
|
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
|
-
|
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.
|
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
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.
|
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:
|
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:
|