ToDo | 4 --
scripts/cfs_add_directory.py | 18 +++++++++----
scripts/cfs_add_node.py | 7 ++++-
scripts/cfs_add_tenant.py | 15 ++++++++---
scripts/cfs_add_volume.py | 14 ++++++----
scripts/cfs_delete_tenant.py | 15 ++++++++---
scripts/cfs_enable_tenant.py | 17 +++++++++---
scripts/cfs_list_tenants.py | 14 ++++++++++
scripts/cfs_list_vols.py | 16 +++++++++++
scripts/cfs_paths.py | 6 ++--
scripts/cfs_rm_volume.py | 55 +++++++++++++++++++++++++++++++++++++++++
scripts/cfs_start_volume.py | 30 +++++++++++++++++-----
scripts/cfs_stop_volume.py | 14 +++++++++-
scripts/cfs_utils.py | 9 +++++-
scripts/cloudfsd.py | 9 ++++++
scripts/views/rm_vol_done.html | 15 +++++++++++
scripts/views/volumes.html | 3 +-
17 files changed, 223 insertions(+), 38 deletions(-)
New commits:
commit 04d9caaab692c3ca819e1b3038099c81eee058a5
Author: Jeff Darcy <jdarcy(a)redhat.com>
Date: Thu May 12 15:42:11 2011 -0400
Added CLI programs to list volumes/tenants.
diff --git a/ToDo b/ToDo
index 696245b..2fbbcb9 100644
--- a/ToDo
+++ b/ToDo
@@ -1,5 +1,5 @@
= High Priority =
-Add CLI equivalents to list nodes/volumes/tenants
+(nothing left)
= Medium Priority =
SSL
diff --git a/scripts/cfs_list_tenants.py b/scripts/cfs_list_tenants.py
new file mode 100755
index 0000000..3446418
--- /dev/null
+++ b/scripts/cfs_list_tenants.py
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+
+import cfs_utils
+
+db_obj = cfs_utils.open_db()
+
+for tenant in [t for t in db_obj.keys() if t.startswith("tv_")]:
+ print "%s:" % t[3:]
+ vol_list = db_obj[tenant]
+ if vol_list == "":
+ print " (no volumes enabled)"
+ else:
+ for vol in vol_list.split(","):
+ print " %s enabled" % vol
diff --git a/scripts/cfs_list_vols.py b/scripts/cfs_list_vols.py
new file mode 100755
index 0000000..f26f3b8
--- /dev/null
+++ b/scripts/cfs_list_vols.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+import cfs_utils
+
+brick_list = cfs_utils.get_bricks()
+vol_list = brick_list.keys()[:]
+vol_list.sort()
+db_obj = cfs_utils.open_db()
+
+for vol in vol_list:
+ if db_obj.has_key("vt_"+vol):
+ print "Volume %s (CloudFS):" % vol
+ else:
+ print "Volume %s (GlusterFS):" % vol
+ for brick in brick_list[vol]:
+ print " %s" % brick
commit 6a1ba723db3dee6496350f5a9e6f59741645ee6b
Author: Jeff Darcy <jdarcy(a)redhat.com>
Date: Thu May 12 15:26:18 2011 -0400
Fixed CLI versions of most functions.
diff --git a/ToDo b/ToDo
index fec4353..696245b 100644
--- a/ToDo
+++ b/ToDo
@@ -1,5 +1,5 @@
= High Priority =
-Make sure CLI equivalents work
+Add CLI equivalents to list nodes/volumes/tenants
= Medium Priority =
SSL
diff --git a/scripts/cfs_add_directory.py b/scripts/cfs_add_directory.py
old mode 100644
new mode 100755
index 508f501..1c9f0b9
--- a/scripts/cfs_add_directory.py
+++ b/scripts/cfs_add_directory.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
import os
import re
@@ -78,12 +79,16 @@ def add_local (path):
xp_list = []
paths_by_node[k[3:]] = set(xp_list)
# Add the user's paths.
+ members = cfs_utils.get_members()
for p in expand(path):
parts = string.split(p,":")
if len(parts) != 2:
- return "add_local(%s) rejected %s on %s" %(
+ return "add_local(%s) rejected %s on %s (no node)" %(
path, p, socket.gethostname())
node, dir = parts
+ if node not in members:
+ return "add_local(%s) rejected %s on %s (bad node)" %(
+ path, p, socket.gethostname())
if paths_by_node.has_key(node):
paths_by_node[node].add(dir)
else:
@@ -108,13 +113,16 @@ def run_common (path):
for line in url_obj:
scratch[1].append(line)
blob.append(scratch)
- return template("add_dir_done.html",path=path,blob=blob);
+ return blob
def run_www ():
path = request.forms.get("path")
- return run_common(path)
+ blob = run_common(path)
+ return template("add_dir_done.html",path=path,blob=blob);
if __name__ == "__main__":
path = sys.argv[1]
- #run_common(tn_name,tn_pw)
- print add_local(path)
+ blob = run_common(path)
+ print "Directory %s added." % path
+ cfs_utils.print_blob(blob)
+
diff --git a/scripts/cfs_add_node.py b/scripts/cfs_add_node.py
old mode 100644
new mode 100755
index 497db36..b9bb7c4
--- a/scripts/cfs_add_node.py
+++ b/scripts/cfs_add_node.py
@@ -50,4 +50,9 @@ def run_www ():
return run_common(node_name)
if __name__ == "__main__":
- run_common(sys.argv[1])
+ if len(sys.argv) != 2:
+ print >> sys.stderr, "Usage: %s node_name_or_addr" % sys.argv[0]
+ sys.exit(1)
+ name = sys.argv[1]
+ run_common(name)
+ print "Node %s added." % name
diff --git a/scripts/cfs_add_tenant.py b/scripts/cfs_add_tenant.py
old mode 100644
new mode 100755
index d36837e..d460367
--- a/scripts/cfs_add_tenant.py
+++ b/scripts/cfs_add_tenant.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
import os
import re
@@ -34,15 +35,21 @@ def run_common (tn_name, tn_pw):
for line in url_obj:
scratch[1].append(line)
blob.append(scratch)
- return template("tn_act_done.html",name=tn_name,action="added",
- blob=blob);
+ return blob
def run_www ():
tn_name = request.forms.get("tn_name")
tn_pw = request.forms.get("tn_pw")
- return run_common(tn_name,tn_pw)
+ blob = run_common(tn_name,tn_pw)
+ return template("tn_act_done.html",name=tn_name,action="added",
+ blob=blob);
if __name__ == "__main__":
+ if len(sys.argv) != 3:
+ print >> sys.stderr, "Usage: %s name password" % sys.argv[0]
+ sys.exit(1)
tn_name = sys.argv[1]
tn_pw = sys.argv[2]
- run_common(tn_name,tn_pw)
+ blob = run_common(tn_name,tn_pw)
+ print "Tenant %s added." % tn_name
+ cfs_utils.print_blob(blob)
diff --git a/scripts/cfs_add_volume.py b/scripts/cfs_add_volume.py
old mode 100644
new mode 100755
index 4af663b..32bdc60
--- a/scripts/cfs_add_volume.py
+++ b/scripts/cfs_add_volume.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
import os
import re
@@ -23,10 +24,10 @@ def run_common (vname, vtype, vcount, bricks):
if vtype != "plain":
cmd = "%s %s %s" % (cmd, vtype, vcount)
cmd = "%s %s" % (cmd, string.join(bricks))
+ print cmd
sts = cfs_utils.run_cmd("gluster",cmd).wait()
if sts:
- return template("add_vol_fail.html", name=vname,
- action="gluster", status=sts)
+ return [["gluster",["command failed with %d"%sts]]]
blob = []
for node in cfs_utils.get_nodes_for_vol(vname):
scratch = [node,[]]
@@ -40,7 +41,7 @@ def run_common (vname, vtype, vcount, bricks):
for line in url_obj:
scratch[1].append(line)
blob.append(scratch)
- return template("add_vol_done.html",name=vname,blob=blob);
+ return blob
def run_www ():
volume_id = request.forms.get("VOLUMEID")
@@ -50,12 +51,15 @@ def run_www ():
for prop in request.forms.iterkeys():
if prop.startswith("VOLUME_"):
brick_list.append(prop[7:])
- return run_common(volume_id,volume_type,replica_or_stripe_count,
+ blob = run_common(volume_id,volume_type,replica_or_stripe_count,
brick_list)
+ return template("add_vol_done.html",name=volume_id,blob=blob);
if __name__ == "__main__":
volume_id = sys.argv[1]
volume_type = sys.argv[2]
replica_or_stripe_count = sys.argv[3]
brick_list = sys.argv[4:]
- run_common(volume_id,volume_type,replica_or_stripe_count,brick_list)
+ blob = run_common(volume_id,volume_type,replica_or_stripe_count,brick_list)
+ print "Volume %s added." % volume_id
+ cfs_utils.print_blob(blob)
diff --git a/scripts/cfs_delete_tenant.py b/scripts/cfs_delete_tenant.py
old mode 100644
new mode 100755
index ebbd35d..92c11d7
--- a/scripts/cfs_delete_tenant.py
+++ b/scripts/cfs_delete_tenant.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
import os
import re
@@ -31,12 +32,18 @@ def run_common (tn_name):
for line in url_obj:
scratch[1].append(line)
blob.append(scratch)
- return template("tn_act_done.html",name=tn_name,action="deleted",
- blob=blob);
+ return blob
def run_www (tn_name):
- return run_common(tn_name)
+ blob = run_common(tn_name)
+ return template("tn_act_done.html",name=tn_name,action="deleted",
+ blob=blob);
if __name__ == "__main__":
+ if len(sys.argv) != 2:
+ print >> sys.stderr, "Usage: %s name" % sys.argv[0]
+ sys.exit(1)
tn_name = sys.argv[1]
- run_common(tn_name)
+ blob = run_common(tn_name)
+ print "Tenant %s deleted." % tn_name
+ cfs_utils.print_blob(blob)
diff --git a/scripts/cfs_enable_tenant.py b/scripts/cfs_enable_tenant.py
old mode 100644
new mode 100755
index 3855546..146c785
--- a/scripts/cfs_enable_tenant.py
+++ b/scripts/cfs_enable_tenant.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
import os
import re
@@ -48,8 +49,7 @@ def run_common (tn_name, vol_list):
for line in url_obj:
scratch[1].append(line)
blob.append(scratch)
- return template("tn_act_done.html",name=tn_name,action="enabled",
- blob=blob)
+ return blob
def run_www (tn_name):
vol_list = []
@@ -57,8 +57,17 @@ def run_www (tn_name):
print prop
if prop.startswith("VOLUME_"):
vol_list.append(prop[7:])
- return run_common(tn_name,vol_list)
+ blob = run_common(tn_name,vol_list)
+ return template("tn_act_done.html",name=tn_name,action="enabled",
+ blob=blob)
if __name__ == "__main__":
- run_common(sys.argv[1],sys.argv[2:])
+ if len(sys.argv) < 2:
+ print >> sys.stderr, "Usage: %s name [volume...]" % sys.argv[0]
+ sys.exit(1)
+ name = sys.argv[1]
+ vols = sys.argv[2:]
+ blob = run_common(name,vols)
+ print "Volumes %s enabled for %s." % (string.join(vols,","), name)
+ cfs_utils.print_blob(blob)
diff --git a/scripts/cfs_paths.py b/scripts/cfs_paths.py
index c497fe7..bf47ebd 100644
--- a/scripts/cfs_paths.py
+++ b/scripts/cfs_paths.py
@@ -8,6 +8,6 @@ log_dir = "/var/log/cloudfs"
pid_dir = "/var/run/cloudfs"
idle_subdir = os.path.join(pid_dir,".idle_ports")
used_subdir = os.path.join(pid_dir,".used_ports")
-volfile_re = re.compile("[^.]+\.(.*)\.bricks-")
+volfile_re =
re.compile("(?P<vol>[^.]+)\.(?P<node>.+)\.(?P<path>[^.]+)\.vol")
CLOUDFSD_PORT = 8080
diff --git a/scripts/cfs_rm_volume.py b/scripts/cfs_rm_volume.py
old mode 100644
new mode 100755
index c871f65..bfab9b2
--- a/scripts/cfs_rm_volume.py
+++ b/scripts/cfs_rm_volume.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
import os
import re
@@ -17,7 +18,7 @@ def rm_local (vname):
db_obj["vt_"+vname] = ""
return "rm_local(%s) OK on %s" % (vname, socket.gethostname())
-def run_www (vname):
+def run_common (vname):
# TBD: all sorts of input-validity checking
nodes_for_vol = cfs_utils.get_nodes_for_vol(vname)
cmd = "volume delete %s" % vname
@@ -37,9 +38,18 @@ def run_www (vname):
for line in url_obj:
scratch[1].append(line)
blob.append(scratch)
+ return blob
+
+def run_www (vname):
+ blob = run_common(vname)
return template("rm_vol_done.html",name=vname,blob=blob);
if __name__ == "__main__":
+ if len(sys.argv) != 2:
+ print >> sys.stderr, "Usage: %s volume_name" % sys.argv[0]
+ sys.exit(0)
name = sys.argv[1]
- run_www(name)
+ blob = run_common(name)
+ print "Volume %s removed." % name
+ cfs_utils.print_blob(blob)
diff --git a/scripts/cfs_start_volume.py b/scripts/cfs_start_volume.py
old mode 100644
new mode 100755
index 031735a..11c992b
--- a/scripts/cfs_start_volume.py
+++ b/scripts/cfs_start_volume.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
import glob
import os
@@ -54,7 +55,7 @@ def scan_gfs_volfiles(vol_name):
for vf in glob.iglob(my_glob):
m = cfs_paths.volfile_re.match(os.path.basename(vf))
if m:
- this_host = m.groups(1)[0]
+ this_host = m.group("node")
this_addr = socket.getaddrinfo(this_host, 0)[0][4][0]
for addr in my_addrs:
if this_addr == addr[4][0]:
@@ -167,7 +168,7 @@ def start_local (vol_name):
return "start_local(%s) returned %d on %s\n" % (
vol_name, retcode, socket.gethostname())
-def run_www (vol_name):
+def run_common (vol_name):
node_list = cfs_utils.get_nodes_for_vol(vol_name)
blob = []
for node in node_list:
@@ -181,7 +182,18 @@ def run_www (vol_name):
for line in url_obj:
scratch[1].append(line)
blob.append(scratch)
+ return blob
+
+def run_www (vol_name):
+ blob = run_common(vol_name)
return template("start_done.html",name=vol_name,blob=blob)
if __name__ == "__main__":
- run_www(sys.argv[1])
+ if len(sys.argv) != 2:
+ print >> sys.stderr, "Usage: %s volume_name" % sys.argv[0]
+ sys.exit(1)
+ name = sys.argv[1]
+ blob = run_common(name)
+ print "Volume %s started." % name
+ cfs_utils.print_blob(blob)
+
diff --git a/scripts/cfs_stop_volume.py b/scripts/cfs_stop_volume.py
old mode 100644
new mode 100755
index 0851d6b..b93b438
--- a/scripts/cfs_stop_volume.py
+++ b/scripts/cfs_stop_volume.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
import fileinput
import glob
@@ -42,7 +43,7 @@ def stop_local (vol_name):
vol_name, retcode, socket.gethostname())
-def run_www (vol_name):
+def run_common (vol_name):
node_list = cfs_utils.get_nodes_for_vol(vol_name)
blob = []
for node in node_list:
@@ -56,7 +57,18 @@ def run_www (vol_name):
for line in url_obj:
scratch[1].append(line)
blob.append(scratch)
+ return blob
+
+def run_www (vol_name):
+ blob = run_common(vol_name)
return template("stop_done.html",name=vol_name,blob=blob)
if __name__ == "__main__":
+ if len(sys.argv) != 2:
+ print >> sys.stderr, "Usage: %s volume_name" % sys.argv[0]
+ sys.exit(1)
+ name = sys.argv[1]
+ blob = run_common(name)
+ print "Volume %s stopped." % name
+ cfs_utils.print_blob(blob)
run_www(sys.argv[1])
diff --git a/scripts/cfs_utils.py b/scripts/cfs_utils.py
index 9655b58..39a36e0 100644
--- a/scripts/cfs_utils.py
+++ b/scripts/cfs_utils.py
@@ -151,7 +151,7 @@ def get_nodes_for_vol (vol_name):
for vf in glob.iglob(my_glob):
m = cfs_paths.volfile_re.match(os.path.basename(vf))
if m:
- node_list.add(m.groups(1)[0])
+ node_list.add(m.group("node"))
return node_list
# Open our configuration database.
@@ -161,3 +161,10 @@ def get_nodes_for_vol (vol_name):
def open_db ():
db_path = os.path.join(cfs_paths.info_dir,"config.db")
return dbm.open(db_path,"c",0600)
+
+# Print a "blob" of [node, [line1, line2]] tuples/lists for CLI/debugging.
+def print_blob (blob):
+ for node, text in blob:
+ print "= %s =" % node
+ for line in text:
+ print line
commit dae24a26c655bdb57a38f95f72d7b92ccdb88b6d
Author: Jeff Darcy <jdarcy(a)redhat.com>
Date: Thu May 12 14:12:51 2011 -0400
Interface to remove volumes.
diff --git a/ToDo b/ToDo
index 24fa991..fec4353 100644
--- a/ToDo
+++ b/ToDo
@@ -1,5 +1,4 @@
= High Priority =
-Interface to remove volumes
Make sure CLI equivalents work
= Medium Priority =
diff --git a/scripts/cfs_rm_volume.py b/scripts/cfs_rm_volume.py
new file mode 100644
index 0000000..c871f65
--- /dev/null
+++ b/scripts/cfs_rm_volume.py
@@ -0,0 +1,45 @@
+
+import os
+import re
+import socket
+import string
+import sys
+import urllib
+import urllib2
+
+from bottle import request, template
+import cfs_paths
+import cfs_utils
+
+def rm_local (vname):
+ db_obj = cfs_utils.open_db()
+ # Can't actually delete, but clearing is functionally equivalent.
+ db_obj["vt_"+vname] = ""
+ return "rm_local(%s) OK on %s" % (vname, socket.gethostname())
+
+def run_www (vname):
+ # TBD: all sorts of input-validity checking
+ nodes_for_vol = cfs_utils.get_nodes_for_vol(vname)
+ cmd = "volume delete %s" % vname
+ kid = cfs_utils.run_cmd("gluster",cmd)
+ blob = [["gluster",kid.communicate("y\n")]]
+ sts = kid.wait()
+ if sts:
+ return template("rm_vol_done.html", name=vname, blob=blob)
+ for node in nodes_for_vol:
+ scratch = [node,[]]
+ if socket.gethostbyname(node) in cfs_utils.local_addrs:
+ url_obj = [rm_local(vname)]
+ else:
+ url = "http://%s:%d/volumes/%s/rm_local" % (
+ node, cfs_paths.CLOUDFSD_PORT, vname)
+ url_obj = urllib2.urlopen(url)
+ for line in url_obj:
+ scratch[1].append(line)
+ blob.append(scratch)
+ return template("rm_vol_done.html",name=vname,blob=blob);
+
+if __name__ == "__main__":
+ name = sys.argv[1]
+ run_www(name)
+
diff --git a/scripts/cloudfsd.py b/scripts/cloudfsd.py
index 2cc7259..8255a44 100755
--- a/scripts/cloudfsd.py
+++ b/scripts/cloudfsd.py
@@ -13,6 +13,7 @@ import cfs_utils
import cfs_add_node
import cfs_add_directory
import cfs_add_volume
+import cfs_rm_volume
import cfs_start_volume
import cfs_stop_volume
import cfs_add_tenant
@@ -68,6 +69,14 @@ def add_vol_local ():
vname = request.forms.get("vname")
return cfs_add_volume.add_local(vname)
+@route("volumes/:name/remove")
+def rm_volume (name):
+ return cfs_rm_volume.run_www(name)
+
+@route("/volumes/:name/rm_local")
+def rm_vol_local (name):
+ return cfs_rm_volume.rm_local(name)
+
@route("/volumes/:vol_name/start")
def start_volume(vol_name):
return cfs_start_volume.run_www(vol_name)
diff --git a/scripts/views/rm_vol_done.html b/scripts/views/rm_vol_done.html
new file mode 100644
index 0000000..cede10d
--- /dev/null
+++ b/scripts/views/rm_vol_done.html
@@ -0,0 +1,15 @@
+<html><head>
+<meta http-equiv="pragma" content="no-cache">
+</head><body>
+%for node, output in blob:
+ <p><b>{{node}}</b></p>
+ <pre>
+ %for line in output:
+ {{line}}
+ %end
+ </pre>
+%end
+<p>Volume {{name}} deleted.</p>
+<p><a href="/volumes">Back to volume
configuration</a></p>
+<p><a href="/cfgmain">Back to main menu</a></p>
+</body></html>
diff --git a/scripts/views/volumes.html b/scripts/views/volumes.html
index 7595052..cc54f92 100644
--- a/scripts/views/volumes.html
+++ b/scripts/views/volumes.html
@@ -14,7 +14,8 @@
<p><b>{{vol_name}}</b>
<a href="/volumes/{{vol_name}}/tenants">tenants</a>
<a href="/volumes/{{vol_name}}/start">start</a>
- <a href="/volumes/{{vol_name}}/stop">stop</a></p>
+ <a href="/volumes/{{vol_name}}/stop">stop</a>
+ <a href="/volumes/{{vol_name}}/remove">remove</a></p>
<ul>
%for brick in brick_list:
<li>{{brick}}</li>
commit 81fc70f17bddfa72c77487351927aae382075a6c
Author: Jeff Darcy <jdarcy(a)redhat.com>
Date: Thu May 12 13:35:26 2011 -0400
Move log/pid/port directories.
diff --git a/ToDo b/ToDo
index db4cf21..24fa991 100644
--- a/ToDo
+++ b/ToDo
@@ -1,5 +1,4 @@
= High Priority =
-Create log/pid directories, move port links to /var/run
Interface to remove volumes
Make sure CLI equivalents work
diff --git a/scripts/cfs_paths.py b/scripts/cfs_paths.py
index 27e11b0..c497fe7 100644
--- a/scripts/cfs_paths.py
+++ b/scripts/cfs_paths.py
@@ -4,10 +4,10 @@ import os
gfs_dir = "/var/lib/glusterd"
info_dir = "/var/lib/cloudfs"
-idle_subdir = os.path.join(info_dir,".idle_ports")
-used_subdir = os.path.join(info_dir,".used_ports")
log_dir = "/var/log/cloudfs"
pid_dir = "/var/run/cloudfs"
+idle_subdir = os.path.join(pid_dir,".idle_ports")
+used_subdir = os.path.join(pid_dir,".used_ports")
volfile_re = re.compile("[^.]+\.(.*)\.bricks-")
CLOUDFSD_PORT = 8080
diff --git a/scripts/cfs_start_volume.py b/scripts/cfs_start_volume.py
index c0b8ce7..031735a 100644
--- a/scripts/cfs_start_volume.py
+++ b/scripts/cfs_start_volume.py
@@ -17,12 +17,18 @@ import cfs_utils
# Make sure the volume directory exists and has the right stuff in it.
def check_volume_directory(vol_name):
if not os.path.exists(cfs_paths.info_dir):
- os.mkdir(cfs_paths.info_dir)
- os.mkdir(cfs_paths.idle_subdir)
+ os.mkdir(cfs_paths.info_dir,0700)
+ if not os.path.exists(cfs_paths.log_dir):
+ os.mkdir(cfs_paths.log_dir,0700)
+ if not os.path.exists(cfs_paths.pid_dir):
+ os.mkdir(cfs_paths.pid_dir,0700)
+ if not os.path.exists(cfs_paths.idle_subdir):
+ os.mkdir(cfs_paths.idle_subdir,0700)
for i in range(24010, 24030):
fp = open("%s/%d" % (cfs_paths.idle_subdir, i), "w")
fp.close()
- os.mkdir(cfs_paths.used_subdir)
+ if not os.path.exists(cfs_paths.used_subdir):
+ os.mkdir(cfs_paths.used_subdir,0700)
vol_dir = "%s/%s" % (cfs_paths.info_dir, vol_name)
if not os.path.exists(vol_dir):