4 # Copyright 2012 GRNET S.A. All rights reserved.
6 # Redistribution and use in source and binary forms, with or
7 # without modification, are permitted provided that the following
10 # 1. Redistributions of source code must retain the above
11 # 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.
38 from xseg.xseg_api import *
39 from xseg.xprotocol import *
40 from ctypes import CFUNCTYPE, cast, c_void_p, addressof, string_at, memmove, \
41 create_string_buffer, pointer, sizeof, POINTER, c_char_p, c_char, byref
42 cb_null_ptrtype = CFUNCTYPE(None, uint32_t)
44 import os, sys, subprocess, argparse, time, psutil, signal, errno
45 from subprocess import call, check_call, Popen, PIPE
47 DEFAULTS='/etc/default/archipelago'
48 VLMC_LOCK_FILE='/tmp/vlmc.lock'
49 ARCHIP_PREFIX='archip_'
52 PIDFILE_PATH="/var/run/archipelago"
53 LOGS_PATH="/var/log/archipelago"
54 DEVICE_PREFIX="/dev/xsegbd"
55 XSEGBD_SYSFS="/sys/bus/xsegbd/"
57 CHARDEV_NAME="/dev/segdev"
63 FILE_BLOCKER='mt-pfiled'
64 RADOS_BLOCKER='mt-sosd'
69 available_storage = {'files': FILE_BLOCKER, 'rados': RADOS_BLOCKER}
72 modules = ["xseg", "segdev", "xseg_posix", "xseg_pthread", "xseg_segdev"]
86 SPEC="segdev:xsegbd:512:2048:12"
99 #mt-pfiled specific options
105 #mt-sosd specific options
109 FIRST_COLUMN_WIDTH = 23
110 SECOND_COLUMN_WIDTH = 23
113 return '\x1b[32m' + s + '\x1b[0m'
116 return '\x1b[31m' + s + '\x1b[0m'
119 return '\x1b[33m' + s + '\x1b[0m'
121 def pretty_print(cid, status):
122 sys.stdout.write(cid.ljust(FIRST_COLUMN_WIDTH))
123 sys.stdout.write(status.ljust(SECOND_COLUMN_WIDTH))
124 sys.stdout.write('\n')
128 def isExec(file_path):
129 return os.path.isfile(file_path) and os.access(file_path, os.X_OK)
131 def validExec(program):
132 for path in os.environ["PATH"].split(os.pathsep):
133 exe_file = os.path.join(path, program)
139 def validPort(port, limit, name):
141 if int(port) >= limit:
142 print red(str(port) + " >= " + limit)
145 print red("Invalid port "+name+" : " + str(port))
152 print red("LOGS_PATH is not set")
155 print red("PIDFILE_PATH is not set")
159 if not os.path.isdir(str(LOGS_PATH)):
160 print red("LOGS_PATH "+str(LOGS_PATH)+" does not exist")
163 print red("LOGS_PATH doesn't exist or is not a directory")
167 os.makedirs(str(PIDFILE_PATH))
169 if e.errno == errno.EEXIST:
170 if os.path.isdir(str(PIDFILE_PATH)):
173 print red(str(PIDFILE_PATH) + " is not a directory")
176 print red("Cannot create " + str(PIDFILE_PATH))
179 print red("PIDFILE_PATH is not set")
182 splitted_spec = str(SPEC).split(':')
183 if len(splitted_spec) < 5:
184 print red("Invalid spec")
187 xseg_type=splitted_spec[0]
188 xseg_name=splitted_spec[1]
189 xseg_ports=int(splitted_spec[2])
190 xseg_heapsize=int(splitted_spec[3])
191 xseg_align=int(splitted_spec[4])
193 if xseg_type != "segdev":
194 print red("Segment type not segdev")
196 if xseg_name != "xsegbd":
197 print red("Segment name not equal xsegbd")
200 print red("Wrong alignemt")
203 for v in [VERBOSITY_BLOCKERB, VERBOSITY_BLOCKERM, VERBOSITY_MAPPER,
206 print red("Verbosity missing")
208 if (int(v) > 3 or int(v) < 0):
209 print red("Invalid verbosity " + str(v))
212 print red("Invalid verbosity " + str(v))
215 for n in [NR_OPS_BLOCKERB, NR_OPS_BLOCKERM, NR_OPS_VLMC, NR_OPS_MAPPER]:
217 print red("Nr ops missing")
220 print red("Invalid nr_ops " + str(n))
223 print red("Invalid nr_ops " + str(n))
226 if not validPort(VTOOL, xseg_ports, "VTOOL"):
228 if not validPort(MPORT, xseg_ports, "MPORT"):
230 if not validPort(BPORT, xseg_ports, "BPORT"):
232 if not validPort(MBPORT, xseg_ports, "MBPORT"):
234 if not validPort(VPORT_START, xseg_ports, "VPORT_START"):
236 if not validPort(VPORT_END, xseg_ports, "VPORT_END"):
238 if not validPort(XSEGBD_START, xseg_ports, "XSEGBD_START"):
240 if not validPort(XSEGBD_END, xseg_ports, "XSEGBD_END"):
243 if not XSEGBD_START < XSEGBD_END:
244 print red("XSEGBD_START should be less than XSEGBD_END")
246 if not VPORT_START < VPORT_END:
247 print red("VPORT_START should be less than VPORT_END")
249 #TODO check than no other port is set in the above ranges
253 BLOCKER = available_storage[str(STORAGE)]
255 print red("Invalid storage " + str(STORAGE))
256 print "Available storage: \"" + ', "'.join(available_storage) + "\""
260 if FILED_IMAGES and not os.path.isdir(str(FILED_IMAGES)):
261 print red("FILED_IMAGES invalid")
263 if FILED_MAPS and not os.path.isdir(str(FILED_MAPS)):
264 print red("FILED_PATH invalid")
266 if PITHOS and not os.path.isdir(str(PITHOS)):
267 print red("PITHOS invalid ")
269 if PITHOSMAPS and not os.path.isdir(str(PITHOSMAPS)):
270 print red("PITHOSMAPS invalid")
273 for p in [BLOCKER, MAPPER, VLMC]:
275 print red(p + "is not a valid executable")
280 def construct_peers():
281 if BLOCKER == "pfiled":
282 peer_blockerb = [BLOCKER,
283 ["-p" , str(BPORT), "-g", str(SPEC), "-n", str(NR_OPS_BLOCKERB),
284 str(PITHOS), str(FILED_IMAGES), "-d",
285 "-f", os.path.join(PIDFILE_PATH, "blockerb.pid")],
287 peer_blockerm = [BLOCKER,
288 ["-p" , str(MBPORT), "-g", str(SPEC), "-n", str(NR_OPS_BLOCKERM),
289 str(PITHOSMAPS), str(FILED_MAPS), "-d",
290 "-f", os.path.join(PIDFILE_PATH, "blockerm.pid")],
292 elif BLOCKER == "mt-sosd":
293 peer_blockerb = [BLOCKER,
294 ["-p" , str(BPORT), "-g", str(SPEC), "-n", str(NR_OPS_BLOCKERB),
295 "--pool", str(RADOS_POOL_BLOCKS), "-v", str(VERBOSITY_BLOCKERB),
296 "-d", "--pidfile", os.path.join(PIDFILE_PATH, "blockerb.pid"),
297 "-l", os.path.join(str(LOGS_PATH), "blockerb.log"),
300 peer_blockerm = [BLOCKER,
301 ["-p" , str(MBPORT), "-g", str(SPEC), "-n", str(NR_OPS_BLOCKERM),
302 "--pool", str(RADOS_POOL_MAPS), "-v", str(VERBOSITY_BLOCKERM),
303 "-d", "--pidfile", os.path.join(PIDFILE_PATH, "blockerm.pid"),
304 "-l", os.path.join(str(LOGS_PATH), "blockerm.log"),
307 elif BLOCKER == "mt-pfiled":
308 peer_blockerb = [BLOCKER,
309 ["-p" , str(BPORT), "-g", str(SPEC), "-n", str(NR_OPS_BLOCKERB),
310 "--pithos", str(PITHOS), "--archip", str(FILED_IMAGES),
311 "-v", str(VERBOSITY_BLOCKERB),
312 "-d", "--pidfile", os.path.join(PIDFILE_PATH, "blockerb.pid"),
313 "-l", os.path.join(str(LOGS_PATH), "blockerb.log"),
314 "-t", str(NR_OPS_BLOCKERB), "--prefix", ARCHIP_PREFIX],
316 peer_blockerm = [BLOCKER,
317 ["-p" , str(MBPORT), "-g", str(SPEC), "-n", str(NR_OPS_BLOCKERM),
318 "--pithos", str(PITHOSMAPS), "--archip", str(FILED_MAPS),
319 "-v", str(VERBOSITY_BLOCKERM),
320 "-d", "--pidfile", os.path.join(PIDFILE_PATH, "blockerm.pid"),
321 "-l", os.path.join(str(LOGS_PATH), "blockerm.log"),
322 "-t", str(NR_OPS_BLOCKERM), "--prefix", ARCHIP_PREFIX],
328 ["-t" , "1", "-sp", str(VPORT_START), "-ep", str(VPORT_END),
329 "-g", str(SPEC), "-n", str(NR_OPS_VLMC), "-bp", str(BPORT),
330 "-mp", str(MPORT), "-d", "-v", str(VERBOSITY_VLMC),
331 "--pidfile", os.path.join(PIDFILE_PATH, "vlmcd.pid"),
332 "-l", os.path.join(str(LOGS_PATH), "vlmcd.log")
334 peer_mapperd = [MAPPER,
335 ["-t" , "1", "-p", str(MPORT), "-mbp", str(MBPORT),
336 "-g", str(SPEC), "-n", str(NR_OPS_MAPPER), "-bp", str(BPORT),
337 "--pidfile", os.path.join(PIDFILE_PATH, "mapperd.pid"),
338 "-v", str(VERBOSITY_MAPPER), "-d",
339 "-l", os.path.join(str(LOGS_PATH), "mapperd.log")
343 peers.append(peer_blockerb)
344 peers.append(peer_blockerm)
345 peers.append(peer_vlmcd)
346 peers.append(peer_mapperd)
352 def exclusive_args(args):
355 fd = os.open(VLMC_LOCK_FILE, os.O_CREAT|os.O_EXCL|os.O_WRONLY)
357 except OSError, (err, reason):
358 print >> sys.stderr, reason
359 if err == errno.EEXIST:
362 raise OSError(err, VLMC_LOCK_FILE + ' ' + reason)
367 os.unlink(VLMC_LOCK_FILE)
370 return exclusive_args
375 execfile(os.path.expanduser(DEFAULTS), globals())
377 execfile(rc, globals())
379 sys.stderr.write("Cannot read config file\n")
385 def loaded_modules():
386 lines = open("/proc/modules").read().split("\n")
387 modules = [f.split(" ")[0] for f in lines]
390 def loaded_module(name):
391 return name in loaded_modules()
393 def load_module(name, args):
394 s = "Loading %s " % name
395 sys.stdout.write(s.ljust(FIRST_COLUMN_WIDTH))
396 modules = loaded_modules()
398 sys.stdout.write(yellow("Already loaded".ljust(SECOND_COLUMN_WIDTH)))
399 sys.stdout.write("\n")
401 cmd = ["modprobe", "%s" % name]
404 cmd.extend(["%s=%s" % (arg)])
406 check_call(cmd, shell=False);
408 sys.stdout.write(red("FAILED".ljust(SECOND_COLUMN_WIDTH)))
409 sys.stdout.write("\n")
411 sys.stdout.write(green("OK".ljust(SECOND_COLUMN_WIDTH)))
412 sys.stdout.write("\n")
415 def unload_module(name):
416 s = "Unloading %s " % name
417 sys.stdout.write(s.ljust(FIRST_COLUMN_WIDTH))
418 modules = loaded_modules()
419 if name not in modules:
420 sys.stdout.write(yellow("Not loaded".ljust(SECOND_COLUMN_WIDTH)))
421 sys.stdout.write("\n")
423 cmd = ["modprobe -r %s" % name]
425 check_call(cmd, shell=True);
427 sys.stdout.write(red("FAILED".ljust(SECOND_COLUMN_WIDTH)))
428 sys.stdout.write("\n")
430 sys.stdout.write(green("OK".ljust(SECOND_COLUMN_WIDTH)))
431 sys.stdout.write("\n")
434 def create_segment():
436 cmd = ["xseg", str(SPEC), "create"]
438 check_call(cmd, shell=False);
440 sys.stderr.write(red("Cannot create segment. \n"))
444 def destroy_segment():
446 cmd = ["xseg", str(SPEC), "destroy"]
448 check_call(cmd, shell=False);
450 sys.stderr.write(red("Cannot destroy segment. \n"))
454 def check_running(name, pid = -1):
455 for p in psutil.process_iter():
464 def check_pidfile(name):
465 pidfile = os.path.join(PIDFILE_PATH, name + ".pid")
468 pf = open(pidfile, "r")
478 def start_peer(peer):
479 cmd = [peer[0]] + peer[1]
480 s = "Starting %s " % peer[2]
481 sys.stdout.write(s.ljust(FIRST_COLUMN_WIDTH))
483 check_call(cmd, shell=False);
485 sys.stdout.write(red("FAILED".ljust(SECOND_COLUMN_WIDTH)))
486 sys.stdout.write("\n")
488 sys.stdout.write(green("OK".ljust(SECOND_COLUMN_WIDTH)))
489 sys.stdout.write("\n")
493 pid = check_pidfile(peer[2])
495 pretty_print(peer[2], yellow("not running"))
498 s = "Stopping %s " % peer[2]
499 sys.stdout.write(s.ljust(FIRST_COLUMN_WIDTH))
500 os.kill(pid, signal.SIGTERM)
502 while check_running(peer[0], pid) > 0:
506 sys.stdout.write(red("FAILED".ljust(SECOND_COLUMN_WIDTH)))
507 sys.stdout.write("\n")
509 sys.stdout.write(green("OK".ljust(SECOND_COLUMN_WIDTH)))
510 sys.stdout.write("\n")
513 def peer_running(peer):
514 pid = check_pidfile(peer[2])
518 r = check_running(peer[0], pid)
520 pretty_print(peer[2], yellow("Has valid pidfile but does not seem to be active"))
526 os.stat(str(CHARDEV_NAME))
530 cmd = ["mknod", str(CHARDEV_NAME), "c", str(CHARDEV_MAJOR), str(CHARDEV_MINOR)]
533 check_call(cmd, shell=False);
535 sys.stderr.write(red("Segdev device creation failed.\n"))
541 os.stat(str(CHARDEV_NAME))
545 os.unlink(str(CHARDEV_NAME))
547 sys.stderr.write(red("Segdev device removal failed.\n"))
550 def start_peers(peers):
552 if not loaded_module(m):
553 print red("Cannot start userspace peers. " + m + " module not loaded")
556 if start_peer(p) < 0:
560 def stop_peers(peers):
561 for p in reversed(peers):
567 return start_peers(peers)
573 if load_module(m, None) < 0:
578 if make_segdev() < 0:
584 if create_segment() < 0:
590 if start_peers(peers) < 0:
595 if load_module(xsegbd, xsegbd_args) < 0:
602 return stop_peers(peers)
604 if vlmc_showmapped(args) > 0:
605 print "Cannot stop archipelago. Mapped volumes exist"
607 if unload_module(xsegbd):
615 for m in reversed(modules):
621 if vlmc_showmapped(args) >= 0:
623 if loaded_module(xsegbd):
624 pretty_print(xsegbd, green('Loaded'))
627 pretty_print(xsegbd, red('Not loaded'))
628 for m in reversed(modules):
630 pretty_print(m, green('Loaded'))
633 pretty_print(m, red('Not loaded'))
634 for p in reversed(peers):
635 if peer_running(p) < 0:
636 pretty_print(p[0], red('not running'))
638 pretty_print(p[0], green('running'))
648 class Xseg_ctx(object):
653 def __init__(self, spec, portno):
655 xconf = xseg_config()
656 xseg_parse_spec(spec, xconf)
657 ctx = xseg_join(xconf.type, xconf.name, "posix", cast(0, cb_null_ptrtype))
659 raise Exception("Cannot join segment")
660 port = xseg_bind_port(ctx, portno, c_void_p(0))
662 raise Exception("Cannot bind to port")
663 xseg_init_local_signal(ctx, portno)
674 raise Exception("No segment")
677 def __exit__(self, type_, value, traceback):
683 xseg_quit_local_signal(self.ctx, self.portno)
687 class Request(object):
691 def __init__(self, xseg_ctx, dst_portno, targetlen, datalen):
694 raise Exception("No context")
695 req = xseg_get_request(ctx, xseg_ctx.portno, dst_portno, X_ALLOC)
697 raise Exception("Cannot get request")
698 r = xseg_prep_request(ctx, req, targetlen, datalen)
700 xseg_put_request(ctx, req, xseg_ctx.portno)
701 raise Exception("Cannot prepare request")
702 # print hex(addressof(req.contents))
704 self.xseg_ctx = xseg_ctx
709 if xq_count(byref(self.req.contents.path)) == 0:
710 xseg_put_request(self.xseg_ctx.ctx, self.req, self.xseg_ctx.portno)
716 raise Exception("xseg request not set")
719 def __exit__(self, type_, value, traceback):
721 if xq_count(byref(self.req.contents.path)) == 0:
722 xseg_put_request(self.xseg_ctx.ctx, self.req, self.xseg_ctx.portno)
726 def set_op(self, op):
727 self.req.contents.op = op
730 return self.req.contents.op
732 def set_offset(self, offset):
733 self.req.contents.offset = offset
735 def get_offset(self):
736 return self.req.contents.offset
739 return self.req.contents.size
741 def set_size(self, size):
742 self.req.contents.size = size
744 def set_flags(self, flags):
745 self.req.contents.flags = flags
748 return self.req.contents.flags
750 def set_target(self, target):
751 """Sets the target of the request, respecting request's targetlen"""
752 if len(target) != self.req.contents.targetlen:
754 c_target = xseg_get_target_nonstatic(self.xseg_ctx.ctx, self.req)
755 p_target = create_string_buffer(target)
756 # print hex(addressof(c_target.contents))
757 memmove(c_target, p_target, len(target))
760 def get_target(self):
761 """Return a string to the target of the request"""
762 c_target = xseg_get_target_nonstatic(self.xseg_ctx.ctx, self.req)
763 # print "target_addr " + str(addressof(c_target.contents))
764 return string_at(c_target, self.req.contents.targetlen)
766 def set_data(self, data):
767 """Sets requests data. Data should be a xseg protocol structure"""
768 if sizeof(data) != self.req.contents.datalen:
770 c_data = xseg_get_data_nonstatic(self.xseg_ctx.ctx, self.req)
771 p_data = pointer(data)
772 memmove(c_data, p_data, self.req.contents.datalen)
776 def get_data(self, _type):
777 """return a pointer to the data buffer of the request, casted to the
779 # print "data addr " + str(addressof(xseg_get_data_nonstatic(self.xseg_ctx.ctx, self.req).contents))
780 # ret = cast(xseg_get_data_nonstatic(self.xseg_ctx.ctx, self.req), _type)
781 # print addressof(ret.contents)
784 return cast(xseg_get_data_nonstatic(self.xseg_ctx.ctx, self.req),\
787 return cast(xseg_get_data_nonstatic(self.xseg_ctx.ctx, self.req), \
791 """Submit the associated xseg_request"""
792 p = xseg_submit(self.xseg_ctx.ctx, self.req, self.xseg_ctx.portno, X_ALLOC)
795 xseg_signal(self.xseg_ctx.ctx, p)
798 """Wait until the associated xseg_request is responded, discarding any
799 other requests that may be received in the meantime"""
801 received = xseg_receive(self.xseg_ctx.ctx, self.xseg_ctx.portno, 0)
803 # print addressof(cast(self.req, c_void_p))
804 # print addressof(cast(received, c_void_p))
805 # print addressof(self.req.contents)
806 # print addressof(received.contents)
807 if addressof(received.contents) == addressof(self.req.contents):
808 # if addressof(cast(received, c_void_p)) == addressof(cast(self.req, c_void_p)):
811 p = xseg_respond(self.xseg_ctx.ctx, received, self.xseg_ctx.portno, X_ALLOC)
813 xseg_put_request(self.xseg_ctx.ctx, received,
814 self.xseg_ctx.portno)
816 xseg_signal(self.xseg_ctx.ctx, p)
818 xseg_prepare_wait(self.xseg_ctx.ctx, self.xseg_ctx.portno)
819 xseg_wait_signal(self.xseg_ctx.ctx, 10000000)
820 xseg_cancel_wait(self.xseg_ctx.ctx, self.xseg_ctx.portno)
824 return bool((self.req.contents.state & XS_SERVED) and not
825 (self.req.contents.state & XS_FAILED))
828 def vlmc_showmapped(args):
830 devices = os.listdir(os.path.join(XSEGBD_SYSFS, "devices/"))
834 print "id\tpool\timage\tsnap\tdevice"
836 print "No volumes mapped\n"
840 d_id = open(XSEGBD_SYSFS + "devices/" + f + "/id").read().strip()
841 target = open(XSEGBD_SYSFS + "devices/"+ f + "/target").read().strip()
843 print "%s\t%s\t%s\t%s\t%s" % (d_id, '-', target, '-', DEVICE_PREFIX +
845 except Exception, reason:
846 print >> sys.stderr, reason
850 def vlmc_showmapped_wrapper(args):
851 r = vlmc_showmapped(args)
858 def vlmc_create(args):
864 print >> sys.stderr, "Name should have at least len 6"
866 if size == None and snap == None:
867 print >> sys.stderr, "At least one of the size/snap args must be provided"
871 xseg_ctx = Xseg_ctx(SPEC, VTOOL)
872 with Request(xseg_ctx, MPORT, len(name), sizeof(xseg_request_clone)) as req:
874 req.set_size(sizeof(xseg_request_clone))
878 xclone = xseg_request_clone()
881 xclone.targetlen = len(snap)
886 xclone.size = size << 20
896 sys.stderr.write("vlmc creation failed\n")
900 def vlmc_snapshot(args):
905 print >> sys.stderr, "Name should have at least len 6"
909 xseg_ctx = Xseg_ctx(SPEC, VTOOL)
910 with Request(xseg_ctx, VPORT_START, len(name), sizeof(xseg_request_snapshot)) as req:
911 req.set_op(X_SNAPSHOT)
912 req.set_size(sizeof(xseg_request_snapshot))
916 xsnapshot = xseg_request_snapshot()
917 xsnapshot.target = ""
918 xsnapshot.targetlen = 0
919 req.set_data(xsnapshot)
923 reply = string_at(req.get_data(xseg_reply_snapshot).contents.target, 64)
926 sys.stderr.write("vlmc snapshot failed\n")
928 sys.stdout.write("Snapshot name: %s\n" % reply)
933 if STORAGE == "rados":
934 cmd = [ 'rados', '-p', '%s' % RADOS_POOL_MAPS, 'ls' ]
935 proc = Popen(cmd, stdout = PIPE)
936 while proc.poll() is None:
937 output = proc.stdout.readline()
938 if output.startswith(ARCHIP_PREFIX) and not output.endswith('_lock\n'):
939 print output.lstrip(ARCHIP_PREFIX),
940 elif STORAGE == "files":
941 print >> sys.stderr, "Vlmc list not supported for files yet"
944 print >> sys.stderr, "Invalid storage"
950 def vlmc_remove(args):
954 for f in os.listdir(XSEGBD_SYSFS + "devices/"):
955 d_id = open(XSEGBD_SYSFS + "devices/" + f + "/id").read().strip()
956 target = open(XSEGBD_SYSFS + "devices/"+ f + "/target").read().strip()
958 sys.stderr.write("Volume mapped on device %s%s\n" % (DEVICE_PREFIX,
962 except Exception, reason:
963 print >> sys.stderr, reason
967 xseg_ctx = Xseg_ctx(SPEC, VTOOL)
968 with Request(xseg_ctx, MPORT, len(name), 0) as req:
978 sys.stderr.write("vlmc removal failed\n")
984 if not loaded_module(xsegbd):
985 sys.stderr.write("Xsegbd module not loaded\n")
990 result = [int(open(XSEGBD_SYSFS + "devices/" + f + "/srcport").read().strip()) for f in os.listdir(XSEGBD_SYSFS + "devices/")]
1000 if port > XSEGBD_END:
1001 print >> sys.stderr, "Max xsegbd devices reached"
1003 fd = os.open(XSEGBD_SYSFS + "add", os.O_WRONLY)
1004 print >> sys.stderr, "write to %s : %s %d:%d:%d" %( XSEGBD_SYSFS +
1005 "add", name, port, port - XSEGBD_START + VPORT_START, REQS )
1006 os.write(fd, "%s %d:%d:%d" % (name, port, port - XSEGBD_START + VPORT_START, REQS))
1008 except Exception, reason:
1009 print >> sys.stderr, reason
1013 def vlmc_unmap(args):
1014 if not loaded_module(xsegbd):
1015 sys.stderr.write("Xsegbd module not loaded\n")
1017 device = args.name[0]
1019 for f in os.listdir(XSEGBD_SYSFS + "devices/"):
1020 d_id = open(XSEGBD_SYSFS + "devices/" + f + "/id").read().strip()
1021 name = open(XSEGBD_SYSFS + "devices/"+ f + "/target").read().strip()
1022 if device == DEVICE_PREFIX + d_id:
1023 fd = os.open(XSEGBD_SYSFS + "remove", os.O_WRONLY)
1028 print >> sys.stderr, "Device %s doesn't exist" % device
1030 except Exception, reason:
1031 print >> sys.stderr, reason
1035 def vlmc_resize(args):
1036 if not loaded_module(xsegbd):
1037 sys.stderr.write("Xsegbd module not loaded\n")
1045 for f in os.listdir(XSEGBD_SYSFS + "devices/"):
1046 d_id = open(XSEGBD_SYSFS + "devices/" + f + "/id").read().strip()
1047 d_name = open(XSEGBD_SYSFS + "devices/"+ f + "/name").read().strip()
1049 fd = os.open(XSEGBD_SYSFS + "devices/" + d_id +"/refresh", os.O_WRONLY)
1054 except Exception, reason:
1055 print >> sys.stderr, reason
1059 def vlmc_lock(args):
1063 print >> sys.stderr, "Name should have at least len 6"
1065 name = ARCHIP_PREFIX + name
1068 xseg_ctx = Xseg_ctx(SPEC, VTOOL)
1069 with Request(xseg_ctx, MBPORT, len(name), 0) as req:
1070 req.set_op(X_ACQUIRE)
1073 req.set_flags(XF_NOSYNC)
1074 req.set_target(name)
1080 sys.stderr.write("vlmc lock failed\n")
1083 sys.stdout.write("Volume locked\n")
1086 def vlmc_unlock(args):
1091 print >> sys.stderr, "Name should have at least len 6"
1093 name = ARCHIP_PREFIX + name
1096 xseg_ctx = Xseg_ctx(SPEC, VTOOL)
1097 with Request(xseg_ctx, MBPORT, len(name), 0) as req:
1098 req.set_op(X_RELEASE)
1101 req.set_target(name)
1103 req.set_flags(XF_NOSYNC|XF_FORCE)
1105 req.set_flags(XF_NOSYNC)
1111 sys.stderr.write("vlmc unlock failed\n")
1114 sys.stdout.write("Volume unlocked\n")
1117 def vlmc_open(args):
1121 print >> sys.stderr, "Name should have at least len 6"
1125 xseg_ctx = Xseg_ctx(SPEC, VTOOL)
1126 with Request(xseg_ctx, VPORT, len(name), 0) as req:
1130 req.set_target(name)
1136 sys.stderr.write("vlmc open failed\n")
1139 sys.stdout.write("Volume opened\n")
1142 def vlmc_close(args):
1146 print >> sys.stderr, "Name should have at least len 6"
1150 xseg_ctx = Xseg_ctx(SPEC, VTOOL)
1151 with Request(xseg_ctx, VPORT, len(name), 0) as req:
1155 req.set_target(name)
1161 sys.stderr.write("vlmc close failed\n")
1164 sys.stdout.write("Volume closed\n")
1167 parser = argparse.ArgumentParser(description='Archipelago tool')
1168 parser.add_argument('-c', '--config', type=str, nargs='?', help='config file')
1169 parser.add_argument('-u', '--user', action='store_true', default=False , help='affect only userspace peers')
1170 subparsers = parser.add_subparsers()
1172 start_parser = subparsers.add_parser('start', help='Start archipelago')
1173 start_parser.set_defaults(func=start)
1175 stop_parser = subparsers.add_parser('stop', help='Stop archipelago')
1176 stop_parser.set_defaults(func=stop)
1178 status_parser = subparsers.add_parser('status', help='Archipelago status')
1179 status_parser.set_defaults(func=status)
1181 restart_parser = subparsers.add_parser('restart', help='Restart archipelago')
1182 restart_parser.set_defaults(func=restart)
1187 parser = argparse.ArgumentParser(description='vlmc tool')
1188 parser.add_argument('-c', '--config', type=str, nargs='?', help='config file')
1189 subparsers = parser.add_subparsers()
1191 create_parser = subparsers.add_parser('create', help='Create volume')
1192 #group = create_parser.add_mutually_exclusive_group(required=True)
1193 create_parser.add_argument('-s', '--size', type=int, nargs='?', help='requested size in MB for create')
1194 create_parser.add_argument('--snap', type=str, nargs='?', help='create from snapshot')
1195 create_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
1196 create_parser.add_argument('name', type=str, nargs=1, help='volume/device name')
1197 create_parser.set_defaults(func=vlmc_create)
1199 remove_parser = subparsers.add_parser('remove', help='Delete volume')
1200 remove_parser.add_argument('name', type=str, nargs=1, help='volume/device name')
1201 remove_parser.set_defaults(func=vlmc_remove)
1202 remove_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
1204 rm_parser = subparsers.add_parser('rm', help='Delete volume')
1205 rm_parser.add_argument('name', type=str, nargs=1, help='volume/device name')
1206 rm_parser.set_defaults(func=vlmc_remove)
1207 rm_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
1209 map_parser = subparsers.add_parser('map', help='Map volume')
1210 map_parser.add_argument('name', type=str, nargs=1, help='volume/device name')
1211 map_parser.set_defaults(func=vlmc_map)
1212 map_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
1214 unmap_parser = subparsers.add_parser('unmap', help='Unmap volume')
1215 unmap_parser.add_argument('name', type=str, nargs=1, help='volume/device name')
1216 unmap_parser.set_defaults(func=vlmc_unmap)
1217 unmap_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
1219 showmapped_parser = subparsers.add_parser('showmapped', help='Show mapped volumes')
1220 showmapped_parser.set_defaults(func=vlmc_showmapped_wrapper)
1221 showmapped_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
1223 list_parser = subparsers.add_parser('list', help='List volumes')
1224 list_parser.set_defaults(func=vlmc_list)
1225 list_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
1227 snapshot_parser = subparsers.add_parser('snapshot', help='snapshot volume')
1228 #group = snapshot_parser.add_mutually_exclusive_group(required=True)
1229 snapshot_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
1230 snapshot_parser.add_argument('name', type=str, nargs=1, help='volume/device name')
1231 snapshot_parser.set_defaults(func=vlmc_snapshot)
1233 ls_parser = subparsers.add_parser('ls', help='List volumes')
1234 ls_parser.set_defaults(func=vlmc_list)
1235 ls_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
1237 resize_parser = subparsers.add_parser('resize', help='Resize volume')
1238 resize_parser.add_argument('-s', '--size', type=int, nargs=1, help='requested size in MB for resize')
1239 resize_parser.add_argument('name', type=str, nargs=1, help='volume/device name')
1240 resize_parser.set_defaults(func=vlmc_resize)
1241 resize_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
1243 open_parser = subparsers.add_parser('open', help='open volume')
1244 open_parser.add_argument('name', type=str, nargs=1, help='volume/device name')
1245 open_parser.set_defaults(func=vlmc_open)
1246 open_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
1248 close_parser = subparsers.add_parser('close', help='close volume')
1249 close_parser.add_argument('name', type=str, nargs=1, help='volume/device name')
1250 close_parser.set_defaults(func=vlmc_close)
1251 close_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
1253 lock_parser = subparsers.add_parser('lock', help='lock volume')
1254 lock_parser.add_argument('name', type=str, nargs=1, help='volume/device name')
1255 lock_parser.set_defaults(func=vlmc_lock)
1256 lock_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
1258 unlock_parser = subparsers.add_parser('unlock', help='unlock volume')
1259 unlock_parser.add_argument('name', type=str, nargs=1, help='volume/device name')
1260 unlock_parser.add_argument('-f', '--force', action='store_true', default=False , help='break lock')
1261 unlock_parser.set_defaults(func=vlmc_unlock)
1262 unlock_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
1266 if __name__ == "__main__":
1267 # parse arguments and discpatch to the correct func
1270 'archipelago' : archipelago,
1272 }[os.path.basename(sys.argv[0])]
1273 parser = parser_func()
1274 except Exception as e:
1275 sys.stderr.write("Invalid basename\n")
1278 args = parser.parse_args()
1280 if parser_func == archipelago:
1281 peers = construct_peers()
1282 xsegbd_args = [('start_portno', str(XSEGBD_START)), ('end_portno',
1285 sys.exit(args.func(args))