From fdac145632222218728ba660f6c6471196ba9514 Mon Sep 17 00:00:00 2001 From: NerdyNick Date: Wed, 5 Jan 2011 16:13:53 -0700 Subject: [PATCH 1/8] Added TODO to remeber to add support for URL's in Session Model, Added to requirements list that zkpython is required, Added ignores for .project & .pydevproject --- .gitignore | 2 ++ README.textile | 1 + zkadmin/models.py | 1 + 3 files changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 6b55238..c2d1521 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ *.py[co] cli_log.txt +.project +.pydevproject diff --git a/README.textile b/README.textile index 7fa708c..2f85ca4 100644 --- a/README.textile +++ b/README.textile @@ -30,6 +30,7 @@ This project is licensed under the Apache License Version 2.0 h2. Requirements * Django 1.0+ +* zkpython 3.3.1+ h2. Usage diff --git a/zkadmin/models.py b/zkadmin/models.py index 592e169..b5a29f7 100644 --- a/zkadmin/models.py +++ b/zkadmin/models.py @@ -9,6 +9,7 @@ class Session(object): def __init__(self, session): + #TODO: Support URLs, Not just IPs m = re.search('/(\d+\.\d+\.\d+\.\d+):(\d+)\[(\d+)\]\((.*)\)', session) self.host = m.group(1) self.port = m.group(2) From 2310076c6d7b8d3fc0ee0f26838f22a97e1fcbfd Mon Sep 17 00:00:00 2001 From: NerdyNick Date: Thu, 6 Jan 2011 14:59:57 -0700 Subject: [PATCH 2/8] Fixed issue with Flume being connectioned to ZK and ZK reporting 0:0:0:0:0:0:0:1 as an IP of an active session. --- zkadmin/models.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zkadmin/models.py b/zkadmin/models.py index b5a29f7..52fba23 100644 --- a/zkadmin/models.py +++ b/zkadmin/models.py @@ -11,6 +11,8 @@ class Session(object): def __init__(self, session): #TODO: Support URLs, Not just IPs m = re.search('/(\d+\.\d+\.\d+\.\d+):(\d+)\[(\d+)\]\((.*)\)', session) + if not m: + m = re.search('/(0:0:0:0:0:0:0:1):(\d+)\[(\d+)\]\((.*)\)', session) self.host = m.group(1) self.port = m.group(2) self.interest_ops = m.group(3) @@ -34,6 +36,7 @@ def __init__(self, server): line = sio.readline() m = re.search('.*: (\d+\.\d+\.\d+)-.*', line) self.version = m.group(1) + #Skip the clients line sio.readline() self.sessions = [] for line in sio: From 7c0fcbc1c218dcc388723d1afe97c51eb7b58cbd Mon Sep 17 00:00:00 2001 From: NerdyNick Date: Fri, 7 Jan 2011 11:28:11 -0700 Subject: [PATCH 3/8] Starts of UI Cleanup, Enhancements, Formating --- css/blueprint/screen.css | 12 +- zkadmin/templates/zkadmin/detail.html | 145 +++++++++++------- zkadmin/templates/zkadmin/index.html | 113 +++++++------- zktree/templates/zktree/index.html | 202 +++++++++++++++----------- 4 files changed, 276 insertions(+), 196 deletions(-) diff --git a/css/blueprint/screen.css b/css/blueprint/screen.css index 2c2b328..ef38e1e 100644 --- a/css/blueprint/screen.css +++ b/css/blueprint/screen.css @@ -23,10 +23,10 @@ a img {border:none;} /* typography.css */ html {font-size:100.01%;} -body {font-size:75%;color:#222;background:#fff;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;} +body {font-size:75%;color:#222;background:#fff;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;padding:8px;} h1, h2, h3, h4, h5, h6 {font-weight:normal;color:#111;} -h1 {font-size:3em;line-height:1;margin-bottom:0.5em;} -h2 {font-size:2em;margin-bottom:0.75em;} +h1 {font-size:3em;line-height:1;margin-bottom:0.5em;border-bottom:1px #ddd solid;} +h2 {font-size:2em;margin-bottom:0.75em;border-bottom:1px #ddd solid;} h3 {font-size:1.5em;line-height:1;margin-bottom:1em;} h4 {font-size:1.2em;line-height:1.25;margin-bottom:1.25em;} h5 {font-size:1em;font-weight:bold;margin-bottom:1.5em;} @@ -254,4 +254,8 @@ hr {background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:.1em;marg hr.space {background:#fff;color:#fff;visibility:hidden;} .clearfix:after, .container:after {content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden;} .clearfix, .container {display:block;} -.clear {clear:both;} \ No newline at end of file +.clear {clear:both;} + +div.section{ + padding:8px 0px; +} \ No newline at end of file diff --git a/zkadmin/templates/zkadmin/detail.html b/zkadmin/templates/zkadmin/detail.html index b359533..293b6bd 100644 --- a/zkadmin/templates/zkadmin/detail.html +++ b/zkadmin/templates/zkadmin/detail.html @@ -1,60 +1,93 @@ - - - - - + + + + + - -ZooKeeper Server {{server_data.id}} - + + ZooKeeper Server {{server_data.id}} + + +
+

ZooKeeper Dashboard

+
+ + + + +
Server ID{{server_data.id}}
Server Address{{server_data.host}}:{{server_data.port}}
Server Mode{{server_data.mode|capfirst}}
+
+ +
+

Summary

+ + + + + + + + + + + + + + +
Host{{server_data.host}}
Client Port{{server_data.port}}
Mode{{server_data.mode|capfirst}}
Zxid{{server_data.zxid}}
Node Count{{server_data.node_count}}
Connection Count{{server_data.sessions|length}}
Received{{server_data.received}}
Sent{{server_data.sent}}
Outstanding{{server_data.outstanding}}
Max Latency{{server_data.max_latency}}
Avg Latency{{server_data.avg_latency}}
Min Latency{{server_data.min_latency}}
+
+ +
+

Connections (Clients)

- -
-

ZooKeeper Server {{server_data.host}}:{{server_data.port}}

-
-
-

Summary

- - - - - - - - - - - - - - -
Host{{server_data.host}}
Client port{{server_data.port}}
Mode{{server_data.mode|capfirst}}
Zxid{{server_data.zxid}}
Node count{{server_data.node_count}}
Connection count{{server_data.sessions|length}}
Received{{server_data.received}}
Sent{{server_data.sent}}
Outstanding{{server_data.outstanding}}
Max Latency{{server_data.max_latency}}
Avg Latency{{server_data.avg_latency}}
Min Latency{{server_data.min_latency}}
-
-
-
-

Connections (clients)

- - - -{% for s in server_data.sessions %} - -{% endfor %} -
hostportinterest opsqueued#recved#sent#
{{s.host}}{{s.port}}{{s.interest_ops}}{{s.queued}}{{s.recved}}{{s.sent}}
-
-
-
-

Environment

- - - -{% for e in server_data.envi %} - -{% endfor %} -
AttributeValue
{{e.0}}{{e.1}}
-
-
-
- - + + + + + + + + + + + + + {% for s in server_data.sessions %} + + + + + + + + + {% endfor %} + +
HostPortInterest OpsQueued #Recved #Sent #
{{s.host}}{{s.port}}{{s.interest_ops}}{{s.queued}}{{s.recved}}{{s.sent}}
+
+ +
+

Environment

+ + + + + + + + + + {% for e in server_data.envi %} + + + + + {% endfor %} + +
AttributeValue
{{e.0}}{{e.1}}
+
+
+ + diff --git a/zkadmin/templates/zkadmin/index.html b/zkadmin/templates/zkadmin/index.html index dc4d246..2c4d68c 100644 --- a/zkadmin/templates/zkadmin/index.html +++ b/zkadmin/templates/zkadmin/index.html @@ -1,55 +1,62 @@ - - - - - - - -ZooKeeper Dashboard - - - -
-

ZooKeeper Dashboard

-
-
-

Cluster Information

- - - - {% for sd in server_data %} - - {% endfor %} -
servermode#connversion
{{ sd.host }}:{{ sd.port }} {% ifequal sd.mode "leader" %}{% endifequal %} {{sd.mode|capfirst}} {% ifequal sd.mode "leader" %}{% endifequal %} {{ sd.sessions|length }} {{ sd.version }}
-

-

- -
- -
-

ZNode Tree

- -Root ZNode of the cluster -

-

-
-
-

Quota Definition

- -Information on the current quota configuration - -Quota -

-

-
-
-
-zookeeper_dashboard was created by -Patrick Hunt and is hosted at GitHub -
-
-
- - + + + + + + + + ZooKeeper Dashboard + + +
+

ZooKeeper Dashboard

+ +
+

Cluster Information

+ + + + + + + + + + + + {% for sd in server_data %} + + + + + + + {% endfor %} + +
ServerMode#ConnVersion
{{ sd.host }}:{{ sd.port }} {% ifequal sd.mode "leader" %}{% endifequal %} {{sd.mode|capfirst}} {% ifequal sd.mode "leader" %}{% endifequal %} {{ sd.sessions|length }} {{ sd.version }}
+
+ +
+

ZNode Tree

+ + Root ZNode of the cluster +
+ +
+

Quota Definition

+ + View Quota - + Information on the current quota configuration. +
+ +
+
+ zookeeper_dashboard was created by + Patrick Hunt and is hosted at GitHub +
+
+
+ + diff --git a/zktree/templates/zktree/index.html b/zktree/templates/zktree/index.html index 082ea3f..5a42818 100644 --- a/zktree/templates/zktree/index.html +++ b/zktree/templates/zktree/index.html @@ -1,88 +1,124 @@ - - - - - + + + + + - -ZooKeeper ZNode {{znode.path}} - + + ZooKeeper ZNode {{znode.path}} + + +
+

ZooKeeper Dashboard

+ +
+

Path: {{znode.path}}

+ Data({{znode.datatype}}): + {% if znode.data %} +
{{znode.data}}
+ {% else %} +
No Data + {% endif %} +
+ +
+

Stat Information

- -
-

ZooKeeper ZNode {{znode.path}}

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {% ifnotequal znode.stat.ephemeralOwner 0 %} + + + + + {% endifnotequal %} + + + + + + + + +
czxid0x{{znode.stat.czxid|stringformat:"x"}}
mzxid0x{{znode.stat.mzxid|stringformat:"x"}}
ctime{{znode.stat.ctime|date}} {{znode.stat.ctime|time}} ({{znode.stat.ctime|timesince}} ago)
mtime{{znode.stat.mtime|date}} {{znode.stat.mtime|time}} ({{znode.stat.mtime|timesince}} ago)
version{{znode.stat.version}}
cversion{{znode.stat.cversion}}
aversion{{znode.stat.aversion}}
ephemeralOwner0x{{znode.stat.ephemeralOwner|stringformat:"x"}}
dataLength{{znode.stat.dataLength}}
pzxid0x{{znode.stat.pzxid|stringformat:"x"}}
+ + Details on Stat fields +
+ +
+

ACL Information({{znode.acls|length}})

-
-
-Path : {{znode.path}} -

- -Data({{znode.datatype}}) : {{znode.data}} -

- -

-
-
-

Stat Information

- - - - - - - - - -{% ifnotequal znode.stat.ephemeralOwner 0 %} - -{% endifnotequal %} - - -
czxid0x{{znode.stat.czxid|stringformat:"x"}}
mzxid0x{{znode.stat.mzxid|stringformat:"x"}}
ctime{{znode.stat.ctime|date}} {{znode.stat.ctime|time}} ({{znode.stat.ctime|timesince}} ago)
mtime{{znode.stat.mtime|date}} {{znode.stat.mtime|time}} ({{znode.stat.mtime|timesince}} ago)
version{{znode.stat.version}}
cversion{{znode.stat.cversion}}
aversion{{znode.stat.aversion}}
ephemeralOwner0x{{znode.stat.ephemeralOwner|stringformat:"x"}}
dataLength{{znode.stat.dataLength}}
pzxid0x{{znode.stat.pzxid|stringformat:"x"}}
-Details on Stat fields - -

-

-
-
-

ACL Information

- -{% if znode.acls %} -ACLs ({{znode.acls|length}}) - - - {% for acl in znode.acls %} - -{% endfor %} -
schemeidperms
{{acl.scheme}}{{acl.id}} - {% for perm in acl.perm_list %} - {% if not forloop.first %}, {% endif %} - {{perm}} - {% endfor %} -
-Details on ACLs -{% else %} -No ACLs exist for this znode -{% endif %} - -

-

-
-
-

Children ({{znode.stat.numChildren}})

- -{% if znode.children %} - - {% for child in znode.children %} - -{% endfor %} -
{{child}}
-{% else %} -No Children exist for this znode -{% endif %} -
-
- - + {% if znode.acls %} + + + + + + + + + + {% for acl in znode.acls %} + + + + + + {% endfor %} + +
SchemeIDPerms
{{acl.scheme}}{{acl.id}} + {% for perm in acl.perm_list %} + {% if not forloop.first %}, {% endif %} + {{perm}} + {% endfor %} +
+ Details on ACLs + {% else %} + No ACLs exist for this znode + {% endif %} +
+ +
+

Children ({{znode.stat.numChildren}})

+ {% if znode.children %} + + {% for child in znode.children %} + + {% endfor %} +
{{child}}
+ {% else %} + No Children exist for this znode + {% endif %} +
+
+ + From bcc5bf22b974d05fe373f339fb9f030021b39dc2 Mon Sep 17 00:00:00 2001 From: NerdyNick Date: Fri, 7 Jan 2011 12:05:16 -0700 Subject: [PATCH 4/8] Added support for deleting ZNodes --- zktree/models.py | 10 ++++++++++ zktree/templates/zktree/index.html | 9 ++++++++- zktree/urls.py | 1 + zktree/views.py | 23 +++++++++++++++++++++-- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/zktree/models.py b/zktree/models.py index 275e91a..5d58842 100644 --- a/zktree/models.py +++ b/zktree/models.py @@ -50,6 +50,9 @@ def get_children(self, path, watcher=None): def get_acls(self, path): return zookeeper.get_acl(self.handle, path) + + def delete(self, path): + return zookeeper.delete(self.handle, path) ZOOKEEPER_SERVERS = getattr(settings,'ZOOKEEPER_SERVERS') @@ -81,3 +84,10 @@ def __init__(self, path="/"): acl['perm_list'] = perms_list finally: zk.close() + + def delete(self): + zk = ZKClient(ZOOKEEPER_SERVERS, TIMEOUT) + try: + zk.delete(self.path) + finally: + zk.close() diff --git a/zktree/templates/zktree/index.html b/zktree/templates/zktree/index.html index 5a42818..5b20275 100644 --- a/zktree/templates/zktree/index.html +++ b/zktree/templates/zktree/index.html @@ -112,7 +112,14 @@

Children ({{znode.stat.numChildren}})

{% if znode.children %} {% for child in znode.children %} - + + + + {% endfor %}
{{child}}
{{child}} + {% if child != "zookeeper" and not isZKPath %} + Delete + {% endif %} +
{% else %} diff --git a/zktree/urls.py b/zktree/urls.py index 6f2bab3..464cc75 100644 --- a/zktree/urls.py +++ b/zktree/urls.py @@ -3,4 +3,5 @@ urlpatterns = patterns('zookeeper_dashboard.zktree.views', (r'^(?P.*)/$','index'), (r'^$','index'), + (r'^delete$','delete'), ) diff --git a/zktree/views.py b/zktree/views.py index a6a8f31..7526f82 100644 --- a/zktree/views.py +++ b/zktree/views.py @@ -1,4 +1,4 @@ -from django.shortcuts import render_to_response +from django.shortcuts import render_to_response, redirect import string from zookeeper_dashboard.zktree.models import ZNode @@ -22,7 +22,26 @@ def index(request, path=""): znode.datatype = "str" return render_to_response('zktree/index.html', - {'znode':znode}) + {'znode':znode, + 'isZKPath':str(znode.path).startswith("/zookeeper")}) except Exception as err: return render_to_response('zktree/error.html', {'error':str(err)}) + +def delete(request): + path = request.GET['path'] + path = str(path).replace("//", '/') + try: + znode = ZNode(path) + znode.delete() + + sPath = path.split('/')[:-1] + toPath = '/'.join(sPath) + toPath = "/tree"+toPath + return redirect(toPath) + except Exception as err: + return render_to_response('zktree/error.html', + {'error':str(err)}) + + + From f4c11115ece4294ade270e969b1594957d5052ca Mon Sep 17 00:00:00 2001 From: NerdyNick Date: Wed, 16 Feb 2011 16:00:32 -0700 Subject: [PATCH 5/8] Updates to UI & Models to add more content to ZNode Tree --- zktree/models.py | 13 ++++++++ zktree/templates/zktree/error.html | 31 ++++++++++-------- zktree/templates/zktree/index.html | 52 +++++++++++++++++++----------- zktree/views.py | 8 +++-- 4 files changed, 70 insertions(+), 34 deletions(-) diff --git a/zktree/models.py b/zktree/models.py index 5d58842..1c5d7e0 100644 --- a/zktree/models.py +++ b/zktree/models.py @@ -59,6 +59,7 @@ def delete(self, path): class ZNode(object): def __init__(self, path="/"): self.path = path + self.name = path.split('/')[-1] zk = ZKClient(ZOOKEEPER_SERVERS, TIMEOUT) try: self.data, self.stat = zk.get(path) @@ -91,3 +92,15 @@ def delete(self): zk.delete(self.path) finally: zk.close() + + def getExtendedChildren(self): + basePath = self.path + if basePath != "/": + basePath += "/" + + + children = [] + for child in self.children: + child = ZNode(basePath+child) + children.append(child) + return children diff --git a/zktree/templates/zktree/error.html b/zktree/templates/zktree/error.html index cf79f5f..3e8e847 100644 --- a/zktree/templates/zktree/error.html +++ b/zktree/templates/zktree/error.html @@ -1,19 +1,24 @@ - - - - - - -Error Accessing ZooKeeper Cluster + + + + + + + Error Accessing ZooKeeper Cluster -
-

Error Accessing ZooKeeper Cluster

- -Failed due to '{{error}}' -
- +
+

Error Accessing ZooKeeper Cluster

+ + Failed due to '{{error}}' + + Traceback +
{{traceback}}
+		
+
+ + \ No newline at end of file diff --git a/zktree/templates/zktree/index.html b/zktree/templates/zktree/index.html index 5b20275..a2c216d 100644 --- a/zktree/templates/zktree/index.html +++ b/zktree/templates/zktree/index.html @@ -28,41 +28,41 @@

Stat Information

- + - + - + - + - + - + - + {% ifnotequal znode.stat.ephemeralOwner 0 %} - + {% endifnotequal %} - + @@ -111,16 +111,30 @@

ACL Information({{znode.acls|length}})

Children ({{znode.stat.numChildren}})

{% if znode.children %}
czxidCreation ID (czxid) 0x{{znode.stat.czxid|stringformat:"x"}}
mzxidModified ID (mzxid) 0x{{znode.stat.mzxid|stringformat:"x"}}
ctimeCreated (ctime) {{znode.stat.ctime|date}} {{znode.stat.ctime|time}} ({{znode.stat.ctime|timesince}} ago)
mtimeModified (mtime) {{znode.stat.mtime|date}} {{znode.stat.mtime|time}} ({{znode.stat.mtime|timesince}} ago)
versionData Version (version) {{znode.stat.version}}
cversionChild Version (cversion) {{znode.stat.cversion}}
aversionACL Version (aversion) {{znode.stat.aversion}}
ephemeralOwnerOwner Session ID (ephemeralOwner) 0x{{znode.stat.ephemeralOwner|stringformat:"x"}}
dataLengthData Length {{znode.stat.dataLength}}
- {% for child in znode.children %} - - - - - {% endfor %} + + + + + + + + + + + {% for child in zchildren %} + + + + + + + + {% endfor %} +
{{child}} - {% if child != "zookeeper" and not isZKPath %} - Delete - {% endif %} -
ZNodeSizeCreatedModified--
{{child.name}}{{child.stat.dataLength}}{{child.stat.ctime|date:"Y-m-d H:i"}}{{child.stat.ctime|date:"Y-m-d H:i"}} + {% if child != "zookeeper" and not isZKPath %} + Delete + {% endif %} +
{% else %} No Children exist for this znode diff --git a/zktree/views.py b/zktree/views.py index 7526f82..0190313 100644 --- a/zktree/views.py +++ b/zktree/views.py @@ -1,5 +1,6 @@ from django.shortcuts import render_to_response, redirect import string +import traceback from zookeeper_dashboard.zktree.models import ZNode @@ -23,10 +24,13 @@ def index(request, path=""): return render_to_response('zktree/index.html', {'znode':znode, - 'isZKPath':str(znode.path).startswith("/zookeeper")}) + 'isZKPath':str(znode.path).startswith("/zookeeper"), + 'zchildren':znode.getExtendedChildren()}) except Exception as err: + tback = traceback.format_exc(err) return render_to_response('zktree/error.html', - {'error':str(err)}) + {'error':str(err), + 'traceback':tback}) def delete(request): path = request.GET['path'] From e9cc70a9b39c09c2ecb3c7d119f6b36a10be74ce Mon Sep 17 00:00:00 2001 From: NerdyNick Date: Wed, 16 Feb 2011 16:18:25 -0700 Subject: [PATCH 6/8] Added Root Dir list to main index --- zkadmin/templates/zkadmin/index.html | 45 ++++++++++++++++++++++++++-- zkadmin/views.py | 10 ++++++- zktree/templates/zktree/index.html | 2 ++ 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/zkadmin/templates/zkadmin/index.html b/zkadmin/templates/zkadmin/index.html index 2c4d68c..969008a 100644 --- a/zkadmin/templates/zkadmin/index.html +++ b/zkadmin/templates/zkadmin/index.html @@ -41,14 +41,53 @@

Cluster Information

ZNode Tree

- Root ZNode of the cluster + + + + + + + + + + + + + + + + + + + + + {% for child in children %} + + + + + + + + + {% endfor %} + +
ZNodeChildrenSizeCreatedModified--
/{{rootNode.children|length}}{{rootNode.stat.dataLength}}{{rootNode.stat.ctime|date:"Y-m-d H:i"}}{{rootNode.stat.ctime|date:"Y-m-d H:i"}} 
    {{child.path}}{{child.children|length}}{{child.stat.dataLength}}{{child.stat.ctime|date:"Y-m-d H:i"}}{{child.stat.ctime|date:"Y-m-d H:i"}} + {% if child != "zookeeper" and not isZKPath %} + Delete + {% endif %} +

Quota Definition

+ {% if quotaNode.data %} +
{{quotaNode.data}}
+ {% else %} +

No Quota Defined

+ {% endif %} - View Quota - - Information on the current quota configuration. + More Information on the current quota configuration.
diff --git a/zkadmin/views.py b/zkadmin/views.py index a878210..ad5df21 100644 --- a/zkadmin/views.py +++ b/zkadmin/views.py @@ -2,6 +2,7 @@ from django.conf import settings from zookeeper_dashboard.zkadmin.models import ZKServer +from zookeeper_dashboard.zktree.models import ZNode ZOOKEEPER_SERVERS = getattr(settings,'ZOOKEEPER_SERVERS').split(',') @@ -11,10 +12,17 @@ def index(request): zkserver = ZKServer(server) zkserver.id = i server_data.append(zkserver) + + rootNode = ZNode() + children = rootNode.getExtendedChildren() + quotaNode = ZNode("/zookeeper/quota") return render_to_response('zkadmin/index.html', {'ZOOKEEPER_SERVERS':ZOOKEEPER_SERVERS, - 'server_data':server_data}) + 'server_data':server_data, + 'rootNode':rootNode, + 'children':children, + 'quotaNode':quotaNode}) def detail(request, server_id): server_data = ZKServer(ZOOKEEPER_SERVERS[int(server_id)]) diff --git a/zktree/templates/zktree/index.html b/zktree/templates/zktree/index.html index a2c216d..6811036 100644 --- a/zktree/templates/zktree/index.html +++ b/zktree/templates/zktree/index.html @@ -114,6 +114,7 @@

Children ({{znode.stat.numChildren}})

ZNode + Children Size Created Modified @@ -124,6 +125,7 @@

Children ({{znode.stat.numChildren}})

{% for child in zchildren %} {{child.name}} + {{child.children|length}} {{child.stat.dataLength}} {{child.stat.ctime|date:"Y-m-d H:i"}} {{child.stat.ctime|date:"Y-m-d H:i"}} From b887ad481f8ee4e285ebd5ca983118c83193f219 Mon Sep 17 00:00:00 2001 From: NerdyNick Date: Wed, 16 Feb 2011 16:21:32 -0700 Subject: [PATCH 7/8] Fixed bug with allowing a user to delete /zookeeper/* --- zkadmin/templates/zkadmin/index.html | 2 +- zktree/templates/zktree/index.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zkadmin/templates/zkadmin/index.html b/zkadmin/templates/zkadmin/index.html index 969008a..2a127a5 100644 --- a/zkadmin/templates/zkadmin/index.html +++ b/zkadmin/templates/zkadmin/index.html @@ -69,7 +69,7 @@

ZNode Tree

{{child.stat.ctime|date:"Y-m-d H:i"}} {{child.stat.ctime|date:"Y-m-d H:i"}} - {% if child != "zookeeper" and not isZKPath %} + {% if child.path != "/zookeeper" and not isZKPath %} Delete {% endif %} diff --git a/zktree/templates/zktree/index.html b/zktree/templates/zktree/index.html index 6811036..616487e 100644 --- a/zktree/templates/zktree/index.html +++ b/zktree/templates/zktree/index.html @@ -130,7 +130,7 @@

Children ({{znode.stat.numChildren}})

{{child.stat.ctime|date:"Y-m-d H:i"}} {{child.stat.ctime|date:"Y-m-d H:i"}} - {% if child != "zookeeper" and not isZKPath %} + {% if child.path != "zookeeper" and not isZKPath %} Delete {% endif %} From 5a730269d8d6abb5a3ff4a2abdc7d5c251526e28 Mon Sep 17 00:00:00 2001 From: NerdyNick Date: Wed, 16 Feb 2011 16:34:58 -0700 Subject: [PATCH 8/8] Added support for cascading delete of ZNodes --- zktree/models.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zktree/models.py b/zktree/models.py index 1c5d7e0..2611c64 100644 --- a/zktree/models.py +++ b/zktree/models.py @@ -87,6 +87,10 @@ def __init__(self, path="/"): zk.close() def delete(self): + if len(self.children) > 0: + for child in self.getExtendedChildren(): + child.delete() + zk = ZKClient(ZOOKEEPER_SERVERS, TIMEOUT) try: zk.delete(self.path)