3 # Copyright 2012 GRNET S.A. All rights reserved.
5 # Redistribution and use in source and binary forms, with or
6 # without modification, are permitted provided that the following
9 # 1. Redistributions of source code must retain the above
10 # copyright notice, this list of conditions and the following
13 # 2. Redistributions in binary form must reproduce the above
14 # copyright notice, this list of conditions and the following
15 # disclaimer in the documentation and/or other materials
16 # provided with the distribution.
18 # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25 # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 # POSSIBILITY OF SUCH DAMAGE.
31 # The views and conclusions contained in the software and
32 # documentation are those of the authors and should not be
33 # interpreted as representing official policies, either expressed
34 # or implied, of GRNET S.A.
40 from struct import unpack
41 from binascii import hexlify
42 from ctypes import c_uint32, c_uint64
50 devices = os.listdir(os.path.join(XSEGBD_SYSFS, "devices/"))
52 if loaded_module(xsegbd):
53 raise Error("Cannot list %s/devices/" % XSEGBD_SYSFS)
59 d_id = open(XSEGBD_SYSFS + "devices/" + f + "/id")
60 d_id = d_id.read().strip()
61 target = open(XSEGBD_SYSFS + "devices/" + f + "/target")
62 target = target.read().strip()
63 mapped.append((d_id, target))
65 except Exception, reason:
74 print "No volumes mapped"
78 print "id\timage\t\tdevice"
80 print "%s\t%s\t%s" % (m[0], m[1], DEVICE_PREFIX + m[0])
85 def showmapped_wrapper(**kwargs):
89 def is_mapped(volume):
102 def create(name, size=None, snap=None, cont_addr=False, **kwargs):
104 raise Error("Name should have at least len 6")
105 if size is None and snap is None:
106 raise Error("At least one of the size/snap args must be provided")
116 xseg_ctx = Xseg_ctx(get_segment())
117 mport = peers['mapperd'].portno_start
118 req = Request.get_clone_request(xseg_ctx, mport, snap, clone=name,
119 clone_size=size, cont_addr=cont_addr)
126 raise Error("vlmc creation failed")
129 def snapshot(name, snap_name=None, cli=False, **kwargs):
131 raise Error("Name should have at least len 6")
133 xseg_ctx = Xseg_ctx(get_segment())
134 vport = peers['vlmcd'].portno_start
135 req = Request.get_snapshot_request(xseg_ctx, vport, name, snap=snap_name)
143 raise Error("vlmc snapshot failed")
145 sys.stdout.write("Snapshot name: %s\n" % snap_name)
147 def hash(name, cli=False, **kwargs):
149 raise Error("Name should have at least len 6")
151 xseg_ctx = Xseg_ctx(get_segment())
152 mport = peers['mapperd'].portno_start
153 req = Request.get_hash_request(xseg_ctx, mport, name)
158 xhash = req.get_data(xseg_reply_hash).contents
159 hash_name = ctypes.string_at(xhash.target, xhash.targetlen)
164 raise Error("vlmc hash failed")
166 sys.stdout.write("Hash name: %s\n" % hash_name)
169 def list_volumes(**kwargs):
170 if isinstance(peers['blockerm'], Sosd):
172 cluster = rados.Rados(conffile=config['CEPH_CONF_FILE'])
174 ioctx = cluster.open_ioctx(peers['blockerm'].pool)
175 oi = rados.ObjectIterator(ioctx)
178 if name.startswith(ARCHIP_PREFIX) and not name.endswith('_lock'):
179 print name[len(ARCHIP_PREFIX):]
180 elif config['STORAGE'] == "files":
181 raise Error("Vlmc list not supported for files yet")
183 raise Error("Invalid storage")
186 def remove(name, **kwargs):
187 device = is_mapped(name)
188 if device is not None:
189 raise Error("Volume %s mapped on device %s%s" % (name, DEVICE_PREFIX,
193 xseg_ctx = Xseg_ctx(get_segment())
194 mport = peers['mapperd'].portno_start
195 req = Request.get_delete_request(xseg_ctx, mport, name)
202 raise Error("vlmc removal failed")
206 def map_volume(name, **kwargs):
207 vport = peers['vlmcd'].portno_start
208 if not loaded_module(xsegbd):
209 raise Error("Xsegbd module not loaded")
211 device = is_mapped(name)
212 if device is not None:
213 raise Error("Volume %s already mapped on device %s%s" % (name,
214 DEVICE_PREFIX, device))
216 prev = config['XSEGBD_START']
218 result = [int(open(XSEGBD_SYSFS + "devices/" + f + "/srcport").read().
219 strip()) for f in os.listdir(XSEGBD_SYSFS + "devices/")]
229 if port > config['XSEGBD_END']:
230 raise Error("Max xsegbd devices reached")
231 fd = os.open(XSEGBD_SYSFS + "add", os.O_WRONLY)
232 print >> sys.stderr, "write to %s : %s %d:%d:%d" % (XSEGBD_SYSFS +
233 "add", name, port, port - config['XSEGBD_START'] +
235 os.write(fd, "%s %d:%d:%d" % (name, port, port - config['XSEGBD_START']
239 except Exception, reason:
240 raise Error(name + ': ' + str(reason))
244 def unmap_volume(name, **kwargs):
245 if not loaded_module(xsegbd):
246 raise Error("Xsegbd module not loaded")
249 for f in os.listdir(XSEGBD_SYSFS + "devices/"):
250 d_id = open(XSEGBD_SYSFS + "devices/" + f + "/id")
251 d_id = d_id.read().strip()
252 target = open(XSEGBD_SYSFS + "devices/" + f + "/target")
253 target = target.read().strip()
254 if device == DEVICE_PREFIX + d_id:
255 fd = os.open(XSEGBD_SYSFS + "remove", os.O_WRONLY)
259 raise Error("Device %s doesn't exist" % device)
260 except Exception, reason:
261 raise Error(device + ': ' + str(reason))
265 def resize(name, size, **kwargs):
266 if not loaded_module(xsegbd):
267 raise Error("Xsegbd module not loaded")
271 for f in os.listdir(XSEGBD_SYSFS + "devices/"):
272 d_id = open(XSEGBD_SYSFS + "devices/" + f + "/id")
273 d_id = d_id.read().strip()
274 target = open(XSEGBD_SYSFS + "devices/" + f + "/target")
275 target = target.read().strip()
277 fd = os.open(XSEGBD_SYSFS + "devices/" + d_id + "/refresh",
282 except Exception, reason:
283 raise Error(name + ': ' + str(reason))
286 def lock(name, cli=False, **kwargs):
288 raise Error("Name should have at least len 6")
290 name = ARCHIP_PREFIX + name
292 xseg_ctx = Xseg_ctx(get_segment())
293 mbport = peers['blockerm'].portno_start
294 req = Request.get_acquire_request(xseg_ctx, mbport, name)
300 raise Error("vlmc lock failed")
302 sys.stdout.write("Volume locked\n")
305 def unlock(name, force=False, cli=False, **kwargs):
307 raise Error("Name should have at least len 6")
309 name = ARCHIP_PREFIX + name
311 xseg_ctx = Xseg_ctx(get_segment())
312 mbport = peers['blockerm'].portno_start
313 req = Request.get_release_request(xseg_ctx, mbport, name, force=force)
319 raise Error("vlmc unlock failed")
321 sys.stdout.write("Volume unlocked\n")
324 def open_volume(name, cli=False, **kwargs):
326 raise Error("Name should have at least len 6")
329 xseg_ctx = Xseg_ctx(get_segment())
330 vport = peers['vlmcd'].portno_start
331 req = Request.get_open_request(xseg_ctx, vport, name)
337 raise Error("vlmc open failed")
339 sys.stdout.write("Volume opened\n")
342 def close_volume(name, cli=False, **kwargs):
344 raise Error("Name should have at least len 6")
347 xseg_ctx = Xseg_ctx(get_segment())
348 vport = peers['vlmcd'].portno_start
349 req = Request.get_close_request(xseg_ctx, vport, name)
355 raise Error("vlmc close failed")
357 sys.stdout.write("Volume closed\n")
360 def info(name, cli=False, **kwargs):
362 raise Error("Name should have at least len 6")
365 xseg_ctx = Xseg_ctx(get_segment())
366 mport = peers['mapperd'].portno_start
367 req = Request.get_info_request(xseg_ctx, mport, name)
372 size = req.get_data(xseg_reply_info).contents.size
375 raise Error("vlmc info failed")
377 sys.stdout.write("Volume %s: size: %d\n" % (name, size))
380 def mapinfo(name, verbose=False, **kwargs):
382 raise Error("Name should have at least len 6")
384 if config['STORAGE'] == "rados":
386 cluster = rados.Rados(conffile=config['CEPH_CONF_FILE'])
388 ioctx = cluster.open_ioctx(config['RADOS_POOL_MAPS'])
389 BLOCKSIZE = 4*1024*1024
391 mapdata = ioctx.read(ARCHIP_PREFIX + name, length=BLOCKSIZE)
393 raise Error("Cannot read map data")
395 raise Error("Cannot read map data")
397 size_uint32t = sizeof(c_uint32)
398 version = unpack("<L", mapdata[pos:pos+size_uint32t])[0]
400 size_uint64t = sizeof(c_uint64)
401 size = unpack("Q", mapdata[pos:pos+size_uint64t])[0]
403 blocks = size / BLOCKSIZE
406 print "Volume: " + name
407 print "Version: " + str(version)
408 print "Size: " + str(size)
409 for i in range(blocks):
410 exists = bool(unpack("B", mapdata[pos:pos+1])[0])
414 block = hexlify(mapdata[pos:pos+32])
418 print "Actual disk usage: " + str(nr_exists * BLOCKSIZE),
419 print '(' + str(nr_exists) + '/' + str(blocks) + ' blocks)'
421 elif STORAGE == "files":
422 raise Error("Mapinfo for file storage not supported")
424 raise Error("Invalid storage")