5 import os, sys, subprocess, argparse, time, psutil, signal, errno
6 from subprocess import call, check_call
8 DEFAULTS='/etc/default/archipelago'
11 PIDFILE_PATH="/var/run/archipelago"
12 LOGS_PATH="/var/log/archipelago"
13 DEVICE_PREFIX="/dev/xsegbd"
14 XSEGBD_SYSFS="/sys/bus/xsegbd/"
16 CHARDEV_NAME="/dev/segdev"
20 FILE_BLOCKER='mt-pfiled'
21 RADOS_BLOCKER='mt-sosd'
26 available_storage = {'files': FILE_BLOCKER, 'rados': RADOS_BLOCKER}
29 modules = ["xseg", "segdev", "xseg_posix", "xseg_pthread", "xseg_segdev"]
40 SPEC="segdev:xsegbd:512:1024:12"
53 #mt-pfiled specific options
59 #mt-sosd specific options
66 def isExec(file_path):
67 return os.path.isfile(file_path) and os.access(file_path, os.X_OK)
69 def validExec(program):
70 for path in os.environ["PATH"].split(os.pathsep):
71 exe_file = os.path.join(path, program)
77 def validPort(port, limit, name):
79 if int(port) >= limit:
80 print str(port) + " >= " + limit
83 print "Invalid port "+name+" : " + str(port)
90 print "LOGS_PATH is not set"
93 print "PIDFILE_PATH is not set"
97 if not os.path.isdir(str(LOGS_PATH)):
98 print "LOGS_PATH "+str(LOGS_PATH)+" does not exist"
101 print "LOGS_PATH doesn't exist or is not a directory"
105 os.makedirs(str(PIDFILE_PATH))
107 if e.errno == errno.EEXIST:
108 if os.path.isdir(str(PIDFILE_PATH)):
111 print str(PIDFILE_PATH) + " is not a directory"
114 print "Cannot create " + str(PIDFILE_PATH)
117 print "PIDFILE_PATH is not set"
120 splitted_spec = str(SPEC).split(':')
121 if len(splitted_spec) < 5:
125 xseg_type=splitted_spec[0]
126 xseg_name=splitted_spec[1]
127 xseg_ports=int(splitted_spec[2])
128 xseg_heapsize=int(splitted_spec[3])
129 xseg_align=int(splitted_spec[4])
131 if xseg_type != "segdev":
132 print "Segment type not segdev"
134 if xseg_name != "xsegbd":
135 print "Segment name not equal xsegbd"
138 print "Wrong alignemt"
141 for v in [VERBOSITY_BLOCKERB, VERBOSITY_BLOCKERM, VERBOSITY_MAPPER,
144 print "Verbosity missing"
146 if (int(v) > 3 or int(v) < 0):
147 print "Invalid verbosity " + str(v)
150 print "Invalid verbosity " + str(v)
153 for n in [NR_OPS_BLOCKERB, NR_OPS_BLOCKERM, NR_OPS_VLMC, NR_OPS_MAPPER]:
155 print "Nr ops missing"
158 print "Invalid nr_ops " + str(n)
161 print "Invalid nr_ops " + str(n)
164 if not validPort(VTOOL, xseg_ports, "VTOOL"):
166 if not validPort(MPORT, xseg_ports, "MPORT"):
168 if not validPort(BPORT, xseg_ports, "BPORT"):
170 if not validPort(MBPORT, xseg_ports, "MBPORT"):
172 if not validPort(VPORT_START, xseg_ports, "VPORT_START"):
174 if not validPort(VPORT_END, xseg_ports, "VPORT_END"):
179 BLOCKER = available_storage[str(STORAGE)]
181 print "Invalid storage " + str(STORAGE)
182 print "Available storage: \"" + ', "'.join(available_storage) + "\""
186 if FILED_IMAGES and not os.path.isdir(str(FILED_IMAGES)):
187 print "FILED_IMAGES invalid"
189 if FILED_MAPS and not os.path.isdir(str(FILED_MAPS)):
190 print "FILED_PATH invalid"
192 if PITHOS and not os.path.isdir(str(PITHOS)):
193 print "PITHOS invalid "
195 if PITHOSMAPS and not os.path.isdir(str(PITHOSMAPS)):
196 print "PITHOSMAPS invalid"
199 for p in [BLOCKER, MAPPER, VLMC]:
201 print p + "is not a valid executable"
206 def construct_peers():
207 if BLOCKER == "pfiled":
208 peer_blockerb = [BLOCKER,
209 ["-p" , str(BPORT), "-g", str(SPEC), "-n", str(NR_OPS_BLOCKERB),
210 str(PITHOS), str(FILED_IMAGES), "-d",
211 "-f", os.path.join(PIDFILE_PATH, "blockerb.pid")],
213 peer_blockerm = [BLOCKER,
214 ["-p" , str(MBPORT), "-g", str(SPEC), "-n", str(NR_OPS_BLOCKERM),
215 str(PITHOSMAPS), str(FILED_MAPS), "-d",
216 "-f", os.path.join(PIDFILE_PATH, "blockerm.pid")],
218 elif BLOCKER == "mt-sosd":
219 peer_blockerb = [BLOCKER,
220 ["-p" , str(BPORT), "-g", str(SPEC), "-n", str(NR_OPS_BLOCKERB),
221 "--pool", str(RADOS_POOL_BLOCKS), "-v", str(VERBOSITY_BLOCKERB),
222 "-d", "--pidfile", os.path.join(PIDFILE_PATH, "blockerb.pid"),
223 "-l", os.path.join(str(LOGS_PATH), "blockerb.log"),
226 peer_blockerm = [BLOCKER,
227 ["-p" , str(MBPORT), "-g", str(SPEC), "-n", str(NR_OPS_BLOCKERM),
228 "--pool", str(RADOS_POOL_MAPS), "-v", str(VERBOSITY_BLOCKERM),
229 "-d", "--pidfile", os.path.join(PIDFILE_PATH, "blockerm.pid"),
230 "-l", os.path.join(str(LOGS_PATH), "blockerm.log"),
233 elif BLOCKER == "mt-pfiled":
234 peer_blockerb = [BLOCKER,
235 ["-p" , str(BPORT), "-g", str(SPEC), "-n", str(NR_OPS_BLOCKERB),
236 "--pithos", str(PITHOS), "--archip", str(FILED_IMAGES),
237 "-v", str(VERBOSITY_BLOCKERB),
238 "-d", "--pidfile", os.path.join(PIDFILE_PATH, "blockerb.pid"),
239 "-l", os.path.join(str(LOGS_PATH), "blockerb.log"),
240 "-t", str(NR_OPS_BLOCKERB), "--prefix", "archip_"],
242 peer_blockerm = [BLOCKER,
243 ["-p" , str(MBPORT), "-g", str(SPEC), "-n", str(NR_OPS_BLOCKERM),
244 "--pithos", str(PITHOSMAPS), "--archip", str(FILED_MAPS),
245 "-v", str(VERBOSITY_BLOCKERM),
246 "-d", "--pidfile", os.path.join(PIDFILE_PATH, "blockerm.pid"),
247 "-l", os.path.join(str(LOGS_PATH), "blockerm.log"),
248 "-t", str(NR_OPS_BLOCKERM), "--prefix", "archip_"],
254 ["-t" , "1", "-sp", str(VPORT_START), "-ep", str(VPORT_END),
255 "-g", str(SPEC), "-n", str(NR_OPS_VLMC), "-bp", str(BPORT),
256 "-mp", str(MPORT), "-d", "-v", str(VERBOSITY_VLMC),
257 "--pidfile", os.path.join(PIDFILE_PATH, "vlmcd.pid"),
258 "-l", os.path.join(str(LOGS_PATH), "vlmcd.log")
260 peer_mapperd = [MAPPER,
261 ["-t" , "1", "-p", str(MPORT), "-mbp", str(MBPORT),
262 "-g", str(SPEC), "-n", str(NR_OPS_MAPPER), "-bp", str(BPORT),
263 "--pidfile", os.path.join(PIDFILE_PATH, "mapperd.pid"),
264 "-v", str(VERBOSITY_MAPPER), "-d",
265 "-l", os.path.join(str(LOGS_PATH), "mapperd.log")
269 peers.append(peer_blockerb)
270 peers.append(peer_blockerm)
271 peers.append(peer_vlmcd)
272 peers.append(peer_mapperd)
278 def exclusive_args(args):
279 file = "/tmp/vlmc_map.lock"
282 fd = os.open(file, os.O_CREAT|os.O_EXCL|os.O_WRONLY)
284 except Exception, reason:
285 print >> sys.stderr, reason
294 return exclusive_args
297 def vlmc_showmapped(args):
299 devices = os.listdir(os.path.join(XSEGBD_SYSFS, "devices/"))
305 print "id\tpool\timage\tsnap\tdevice"
308 d_id = open(XSEGBD_SYSFS + "devices/" + f + "/id").read().strip()
309 target = open(XSEGBD_SYSFS + "devices/"+ f + "/target").read().strip()
311 print "%s\t%s\t%s\t%s\t%s" % (d_id, '-', target, '-', DEVICE_PREFIX +
313 except Exception, reason:
314 print >> sys.stderr, reason
321 execfile(os.path.expanduser(DEFAULTS), globals())
323 execfile(rc, globals())
325 print "Cannot read config file"
331 def loaded_modules():
332 lines = open("/proc/modules").read().split("\n")
333 modules = [f.split(" ")[0] for f in lines]
336 def loaded_module(name):
337 return name in loaded_modules()
339 def load_module(name):
340 modules = loaded_modules()
343 cmd = ["modprobe -v %s" % name]
345 check_call(cmd, shell=True);
347 sys.stderr.write("Module %s failed to load. \n" % name)
351 def unload_module(name):
352 modules = loaded_modules()
353 if name not in modules:
355 cmd = ["modprobe -rv %s" % name]
358 check_call(cmd, shell=True);
360 sys.stderr.write("Module %s failed to unload. \n" % name)
364 def create_segment():
366 cmd = ["xseg", str(SPEC), "create"]
368 check_call(cmd, shell=False);
370 sys.stderr.write("Cannot create segment. \n")
374 def destroy_segment():
376 cmd = ["xseg", str(SPEC), "destroy"]
378 check_call(cmd, shell=False);
380 sys.stderr.write("Cannot destroy segment. \n")
384 def check_running(name, pid = -1):
385 for p in psutil.process_iter():
394 def check_pidfile(name):
395 pidfile = os.path.join(PIDFILE_PATH, name + ".pid")
398 pf = open(pidfile, "r")
408 def start_peer(peer):
409 cmd = [peer[0]] + peer[1]
411 check_call(cmd, shell=False);
413 sys.stderr.write("Peer %s start failed.\n" % peer[0])
418 pid = check_pidfile(peer[2])
420 print " process not running"
423 os.kill(pid, signal.SIGTERM)
425 while check_running(peer[0], pid) > 0:
429 print "process did not die in 15 secs"
433 def peer_running(peer):
434 pid = check_pidfile(peer[2])
438 r = check_running(peer[0], pid)
440 print "Peer " + peer[2] + " has valid pidfile but does not seem to be active"
446 os.stat(str(CHARDEV_NAME))
450 cmd = ["mknod", str(CHARDEV_NAME), "c", str(CHARDEV_MAJOR), str(CHARDEV_MINOR)]
453 check_call(cmd, shell=False);
455 sys.stderr.write("Segdev device creation failed. \n")
461 os.stat(str(CHARDEV_NAME))
465 os.unlink(str(CHARDEV_NAME))
467 sys.stderr.write("Segdev device removal failed. \n")
476 if load_module(m) < 0:
481 if make_segdev() < 0:
487 if create_segment() < 0:
494 if start_peer(p) < 0:
499 if load_module(xsegbd) < 0:
506 if vlmc_showmapped(args) > 0:
507 print "Cannot stop archipelago. Mapped volumes exist"
509 if unload_module(xsegbd):
512 for p in reversed(peers):
517 for m in reversed(modules):
523 if vlmc_showmapped(args) >= 0:
525 if loaded_module(xsegbd):
526 print "Xsegbd loaded"
529 print "Xsegbd not loaded"
530 for m in reversed(modules):
535 print m + " not loaded"
536 for p in reversed(peers):
537 if peer_running(p) < 0:
538 print p[0] + " not running"
540 print p[0] + " running"
550 if __name__ == "__main__":
551 # parse arguments and discpatch to the correct func
552 parser = argparse.ArgumentParser(description='Archipelago tool')
553 parser.add_argument('-c', '--config', type=str, nargs='?', help='config file')
554 subparsers = parser.add_subparsers()
556 start_parser = subparsers.add_parser('start', help='Start archipelago')
557 start_parser.set_defaults(func=start)
559 stop_parser = subparsers.add_parser('stop', help='Stop archipelago')
560 stop_parser.set_defaults(func=stop)
562 status_parser = subparsers.add_parser('status', help='Archipelago status')
563 status_parser.set_defaults(func=status)
565 restart_parser = subparsers.add_parser('restart', help='Restart archipelago')
566 restart_parser.set_defaults(func=restart)
568 args = parser.parse_args()
570 peers = construct_peers()
571 sys.exit(args.func(args))