Repository navigation
Expand file tree
/
Copy pathrbdManaged
More file actions
executable file
·242 lines (199 loc) · 9.38 KB
/
Copy pathrbdManaged
File metadata and controls
executable file
·242 lines (199 loc) · 9.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
#!/usr/bin/env ruby
# Copyright (c) 2015-16 Anirvan BASU, INRIA Rennes - Bretagne Atlantique
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'cute'
require 'logger'
require 'cute/taktuk'
require 'net/sftp'
require 'erb'
require 'socket'
require 'trollop'
require 'json'
require "net/http"
require "uri"
g5k = Cute::G5K::API.new()
user = g5k.g5k_user
if (["--def-conf", "-d"].include?(ARGV[0]) && !ARGV[1].empty? )
configFile = ARGV[1] # assign file location to variable configFile
ARGV.delete_at(0) # clean up ARGV array
ARGV.delete_at(0)
else
configFile = "ceph5k/config/defaults.yml" # default config file is used.
end # if (["--def-conf", "-d"])
# Populate the hash with default parameters from YAML file.
defaults = begin
YAML.load(File.open(configFile))
rescue ArgumentError => e
puts "Could not parse YAML: #{e.message}"
end
# banner for script
opts = Trollop::options do
version "ceph5k 0.0.4 (c) 2015-16 Anirvan BASU, INRIA RBA"
banner <<-EOS
rbdManaged.rb is a script for creating RBD and FS on deployed Ceph and production Ceph.
Usage:
rbdManaged.rb [options]
where [options] are:
EOS
opt :ignore, "Ignore incorrect values"
opt :site, "Grid 5000 site for deploying Ceph cluster", :type => String, :default => defaults["site"]
opt :'job-name', "Name of Grid'5000 job if already created", :type => String, :default => defaults["job-name"]
opt :'pool-name', "Name of pool to create on Ceph clusters", :type => String, :default => defaults["pool-name"]
opt :'pool-size', "Size of pool to create on Ceph clusters", :default => defaults["poolSize"]
opt :'rbd-name', "Name of rbd to create inside Ceph pool", :type => String, :default => defaults["rbd-name"]
opt :'rbd-size', "Size of rbd to create inside Ceph pool", :default => defaults["rbd-size"]
opt :'file-system', "File System to be formatted on created RBDs", :type => String, :default => defaults["file-system"]
opt :'mnt-prod', "Mount point for RBD on production cluster", :type => String, :default => defaults["mnt-prod"]
end
# Move CLI arguments into variables. Later change to class attributes.
argSite = opts[:site] # site name.
argJobName = opts[:'job-name'] # Grid'5000 ndoes reservation job.
argPoolName = "#{user}_" + opts[:'pool-name'] # Name of pool to create on clusters.
argPoolSize = opts[:'pool-size'] # Size of pool to create on clusters.
argRBDName = "#{user}_" + opts[:'rbd-name'] # Name of pool to create on clusters.
argRBDSize = opts[:'rbd-size'] # Size of pool to create on clusters.
argFileSystem = opts[:'file-system'] # File System to be formatted on created RBDs.
argMntProd = opts[:'mnt-prod'] # Mount point for RBD on production cluster.
# Get all jobs submitted in a cluster
jobs = g5k.get_my_jobs(argSite)
# get the job with name "cephCluster"
jobCephCluster = nil
jobs.each do |job|
if job["name"] == argJobName # if job exists already, refresh the deployment
jobCephCluster = job
end
end
# Abort script if no deployed Ceph cluster
abort("No deployed Ceph cluster found. First deploy Ceph cluster, then run script.") if jobCephCluster.nil?
# At this point job details were fetched
puts "Ceph deployment job details recovered." + "\n"
# Get the client for the deployed Ceph cluster
client = jobCephCluster["assigned_nodes"][1]
# Remind where is the Ceph client
puts "Ceph client on: #{client}" + "\n"
# Prepare ceph.conf file for production Ceph cluster
configFile = File.open("ceph5k/prod/ceph.conf", "w") do |file|
file.puts("[global]")
file.puts(" mon initial members = ceph0")
file.puts(" mon host = 172.16.111.30,172.16.111.31,172.16.111.32")
end
# Then put ceph.conf file to all clients
Cute::TakTuk.start([client], :user => "root") do |tak|
tak.exec!("rm -rf prod/")
tak.exec!("mkdir prod/ && touch prod/ceph.conf")
tak.put("ceph5k/prod/ceph.conf", "/root/prod/ceph.conf")
tak.put("/tmp/ceph.client.#{user}.keyring", "/etc/ceph/ceph.client.#{user}.keyring")
tak.loop()
end
# Created & pushed config file for Ceph production cluster.
puts "Created & pushed config file for Ceph production cluster to all clients." + "\n"
# Creating Ceph pools on production cluster.
puts "Creating Ceph pool on production cluster ..."
poolsList = []
userPool = ""
userPoolMatch = ""
userRBD = ""
prodCluster = false
abortFlag = false
# Create Ceph pools & RBD
Cute::TakTuk.start([client], :user => "root") do |tak|
tak.exec!("modprobe rbd")
# Create RBD on production cluster
result = tak.exec!("rados -c /root/prod/ceph.conf --id #{user} lspools")
poolsList = result[client][:output].split("\n")
poolCount = 0
poolsList.each do |pool| # logic: it will take the alphabetic-last pool from user
userRBD = ""
if pool.include? "#{user}"
userPool = pool
poolCount += 1
userPoolMatch = pool if pool.include? "#{argPoolName}" # Perfect match of pool name
# Check if RBD is already created, may contain data
resultPool = tak.exec!("rbd -c /root/prod/ceph.conf --id #{user} --pool #{userPool} ls")
unless resultPool[client][:output].nil? # means no rbd in userPool
if resultPool[client][:output].include? "#{argRBDName}"
userRBD = argRBDName # There is an rbd with name argRBDName already
end # if resultPool[client][:output].include?
end # unless resultPool[client][:output].nil?
end # if pool.include? "#{user}"
end # poolsList.each do
unless userPool.empty?
# If multiple pools from user, then confused, so exit.
abort("Script exited - multiple Ceph pools for #{user}") if poolCount > 1 && userPoolMatch.empty?
if userRBD.empty? # There was no rbd created for the user. So create it.
result = tak.exec!("rbd -c /root/prod/ceph.conf --id #{user} --pool #{userPool} create #{argRBDName} --size #{argRBDSize} -k /etc/ceph/ceph.client.#{user}.keyring")
end # if userRBD.empty?
else # There is no pool created on managed Ceph
# Following command cannot be done at CLI on Ceph client
# tak.exec!("rbd -c /root/prod/ceph.conf --id #{user} mkpool #{argPoolName} --keyfile /etc/ceph/ceph.client.#{user}.keyring")
puts "Create at least one RBD pool from the Ceph managed frontend\n\n"
puts "Use this link to create pool: https://api.grid5000.fr/sid/storage/ceph/ui/"
puts "Then rerun this script.\n"
abortFlag = true
break
end # if userRBD.empty?
tak.loop()
end
# Abort script if no pool in managed Ceph
abort("Script exited") if abortFlag
# Created Pool & RBD for Ceph cluster.
unless userPool.empty?
puts "Created Ceph pool on managed cluster as follows :" + "\n"
puts "On production cluster:\n"
puts "Pool name: #{userPool} , RBD Name: #{argRBDName} , RBD Size: #{argRBDSize} " + "\n"
end # unless userPool.empty?
# Map RBD and create File Systems.
puts "Mapping RBD in managed Ceph clusters ..."
Cute::TakTuk.start([client], :user => "root") do |tak|
# Map RBD & create FS on deployed cluster
result = tak.exec!("rbd map #{argRBDName} --pool #{argPoolName}")
tak.exec!("mkfs.#{argFileSystem} -m0 /dev/rbd/#{argPoolName}/#{argRBDName}")
if result[client][:status] == 0
puts "Mapped RBD #{argRBDName} on deployed Ceph." + "\n"
end
myRBDName = ""
# Map RBD & create FS on production cluster
tak.exec!("rbd -c /root/prod/ceph.conf --id #{user} --pool #{userPool} map #{argRBDName} -k /etc/ceph/ceph.client.#{user}.keyring")
if userRBD.empty? # Do it only the first time when the RBD is created.
tak.exec!("mkfs.#{argFileSystem} -m0 /dev/rbd/#{userPool}/#{argRBDName}")
myRBDName = argRBDName
else # This case is when RBD is already created earlier.
myRBDName = userRBD
end # if userRBD.empty?
if result[client][:status] == 0
puts "Mapped RBD #{myRBDName} on managed Ceph." + "\n"
end
tak.loop()
end
# Mount RBDs as File Systems.
puts "Mounting RBD as File Systems in managed Ceph clusters ..."
Cute::TakTuk.start([client], :user => "root") do |tak|
result = nil
# mount RBD from production cluster
if userRBD.empty? # Do it only the first time when the RBD is created.
tak.exec!("umount /dev/rbd/#{userPool}/#{argRBDName} /mnt/#{argMntProd}")
tak.exec!("rmdir /mnt/#{argMntProd}")
tak.exec!("mkdir /mnt/#{argMntProd}")
result = tak.exec!("mount /dev/rbd/#{userPool}/#{argRBDName} /mnt/#{argMntProd}")
else # This case is when RBD is already created earlier.
tak.exec!("umount /dev/rbd/#{userPool}/#{userRBD} /mnt/#{argMntProd}")
tak.exec!("rmdir /mnt/#{argMntProd}")
tak.exec!("mkdir /mnt/#{argMntProd}")
result = tak.exec!("mount /dev/rbd/#{userPool}/#{userRBD} /mnt/#{argMntProd}")
end # if userRBD.empty?
if result[client][:status] == 0
puts "Mounted RBD as File System on managed Ceph." + "\n"
end
tak.loop()
end