hadoop-zookeeper-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ph...@apache.org
Subject svn commit: r986569 - in /hadoop/zookeeper/trunk: ./ src/contrib/huebrowser/ src/contrib/huebrowser/zkui/ src/contrib/huebrowser/zkui/src/ src/contrib/huebrowser/zkui/src/zkui/ src/contrib/huebrowser/zkui/src/zkui/static/ src/contrib/huebrowser/zkui/sr...
Date Wed, 18 Aug 2010 05:47:53 GMT
Author: phunt
Date: Wed Aug 18 05:47:51 2010
New Revision: 986569

URL: http://svn.apache.org/viewvc?rev=986569&view=rev
Log:
ZOOKEEPER-808. Web-based Administrative Interface

Added:
    hadoop/zookeeper/trunk/src/contrib/huebrowser/
    hadoop/zookeeper/trunk/src/contrib/huebrowser/README
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/Makefile
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/setup.py
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/__init__.py
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/forms.py
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/models.py
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/rest.py
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/settings.py
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/art/
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/art/line_icons.png   (with props)
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/art/zkui.png   (with props)
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/bootstrap.js
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/css/
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/css/zkui.css
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/help/
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/help/index.html
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/js/
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/js/Source/
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/js/Source/Zkui/
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/js/Source/Zkui/Zkui.js
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/js/package.yml
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/stats.py
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/clients.mako
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/create.mako
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/edit.mako
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/index.mako
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/shared_components.mako
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/tree.mako
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/view.mako
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/urls.py
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/utils.py
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/views.py
    hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/windmilltests.py
Modified:
    hadoop/zookeeper/trunk/CHANGES.txt

Modified: hadoop/zookeeper/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/CHANGES.txt?rev=986569&r1=986568&r2=986569&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/CHANGES.txt (original)
+++ hadoop/zookeeper/trunk/CHANGES.txt Wed Aug 18 05:47:51 2010
@@ -125,6 +125,8 @@ NEW FEATURES:
   ZOOKEEPER-799. Add tools and recipes for monitoring as a contrib
   (Andrei Savu via phunt)
 
+  ZOOKEEPER-808. Web-based Administrative Interface
+  (Andrei Savu via phunt)
 
 Release 3.3.0 - 2010-03-24
 

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/README
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/README?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/README (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/README Wed Aug 18 05:47:51 2010
@@ -0,0 +1,62 @@
+
+ZooKeeper Browser - Hue Application
+===================================
+
+The ZooKeeper Browser application allows you to see how the cluster nodes are working and also allows you to do CRUD operations on the znode hierarchy.
+
+Requirements
+------------
+
+Hue-1.0:
+  * http://github.com/downloads/cloudera/hue/hue-1.0.tgz
+  * http://github.com/downloads/cloudera/hue/release-notes-1.0.html
+
+ZooKeeper REST gateway:
+  * available as contrib: contrib/rest
+
+How to install?
+---------------
+
+First of all you need to install Hue 1.0 release:
+
+  * http://archive.cloudera.com/cdh/3/hue/sdk/sdk.html
+  * http://github.com/cloudera/hue/tree/release-1.0
+
+After you finish the previous step you should copy the zkui/ folder to apps/ and register the new application:
+
+  * $ ./build/env/bin/python tools/app_reg/app_reg.py --install apps/zkui
+  * $ ./build/env/bin/python tools/app_reg/app_reg.py --list 2>&1 | grep zkui
+    zkui           0.1     /Users/philip/src/hue/apps/zkui
+
+
+And restart the Hue application server.
+
+Configuration
+-------------
+
+Edit zkui/src/zkui/settings.py:
+
+CLUSTERS = [{
+        'nice_name': 'Default',
+        'hostport': 'localhost:2181,localhost:2182,localhost:2183',
+        'rest_gateway': 'http://localhost:9998'
+    }, {
+      # ... and more clusters
+    }
+]
+
+What is Hue?
+------------
+
+Wiki: http://wiki.github.com/cloudera/hue/
+Main Repo: http://github.com/cloudera/hue 
+
+Hue is both a web UI for Hadoop and a framework to create interactive web applications. It features a FileBrowser for accessing HDFS, JobSub and JobBrowser applications for submitting and viewing MapReduce jobs, a Beeswax application for interacting with Hive. On top of that, the web frontend is mostly built from declarative widgets that require no JavaScript and are easy to learn.
+
+What is ZooKeeper?
+------------------
+
+http://hadoop.apache.org/zookeeper/
+
+ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. All of these kinds of services are used in some form or another by distributed applications. Each time they are implemented there is a lot of work that goes into fixing the bugs and race conditions that are inevitable. Because of the difficulty of implementing these kinds of services, applications initially usually skimp on them ,which make them brittle in the presence of change and difficult to manage. Even when done correctly, different implementations of these services lead to management complexity when the applications are deployed.
+

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/Makefile
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/Makefile?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/Makefile (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/Makefile Wed Aug 18 05:47:51 2010
@@ -0,0 +1,21 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+ifeq ($(ROOT),)
+  $(error "Error: Expect the environment variable $$ROOT to point to the Desktop installation")
+endif
+
+include $(ROOT)/Makefile.sdk

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/setup.py
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/setup.py?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/setup.py (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/setup.py Wed Aug 18 05:47:51 2010
@@ -0,0 +1,46 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from setuptools import setup, find_packages
+import os
+
+def expand_package_data(src_dirs, strip=""):
+  ret = []
+  for src_dir in src_dirs:
+    for path, dnames, fnames in os.walk(src_dir):
+      for fname in fnames:
+        ret.append(os.path.join(path, fname).replace(strip, ""))
+  return ret
+
+os.chdir(os.path.dirname(os.path.abspath(__file__)))
+setup(
+  name = "zkui",
+  version = "0.1",
+  url = 'http://hadoop.apache.org/zookeeper/',
+  description = 'ZooKeeper Browser',
+  packages = find_packages('src'),
+  package_dir = {'': 'src'},
+  install_requires = ['setuptools', 'desktop'],
+  entry_points = { 'desktop.sdk.application': 'zkui=zkui' },
+  zip_safe = False,
+  package_data = {
+    # Include static resources.  Package_data doesn't
+    # deal well with directory globs, so we enumerate
+    # the files manually.
+    'zkui': expand_package_data(
+      ["src/zkui/templates", "src/zkui/static"],
+      "src/zkui/")
+  }
+)

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/__init__.py
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/__init__.py?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/__init__.py (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/__init__.py Wed Aug 18 05:47:51 2010
@@ -0,0 +1,16 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/forms.py
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/forms.py?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/forms.py (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/forms.py Wed Aug 18 05:47:51 2010
@@ -0,0 +1,29 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from django import forms
+from django.forms.widgets import Textarea, HiddenInput
+
+class CreateZNodeForm(forms.Form):
+  name = forms.CharField(max_length=64)
+  data = forms.CharField(required=False, widget=Textarea)
+  sequence = forms.BooleanField(required=False)
+
+class EditZNodeForm(forms.Form):
+  data = forms.CharField(required=False, widget=Textarea)
+  version = forms.IntegerField(required=False, widget=HiddenInput)
+  
+

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/models.py
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/models.py?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/models.py (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/models.py Wed Aug 18 05:47:51 2010
@@ -0,0 +1,17 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/rest.py
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/rest.py?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/rest.py (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/rest.py Wed Aug 18 05:47:51 2010
@@ -0,0 +1,230 @@
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import urllib2
+import urllib
+import simplejson
+
+from contextlib import contextmanager
+
+class RequestWithMethod(urllib2.Request):
+    """ Request class that know how to set the method name """
+    def __init__(self, *args, **kwargs):
+        urllib2.Request.__init__(self, *args, **kwargs)
+        self._method = None
+
+    def get_method(self):
+        return self._method or \
+            urllib2.Request.get_method(self)
+
+    def set_method(self, method):
+        self._method = method
+
+class ZooKeeper(object):
+
+    class Error(Exception): pass
+
+    class NotFound(Error): pass
+
+    class ZNodeExists(Error): pass
+
+    class InvalidSession(Error): pass
+
+    class WrongVersion(Error): pass
+
+    def __init__(self, uri = 'http://localhost:9998'):
+        self._base = uri
+        self._session = None
+
+    def start_session(self, expire=5, id=None):
+        """ Create a session and return the ID """
+        if id is None:
+            url = "%s/sessions/v1/?op=create&expire=%d" % (self._base, expire)
+            self._session = self._do_post(url)['id']
+        else:
+            self._session = id
+        return self._session
+
+    def close_session(self):
+        """ Close the session on the server """
+        if self._session is not None:
+            url = '%s/sessions/v1/%s' % (self._base, self._session)
+            self._do_delete(url)
+            self._session = None
+
+    def heartbeat(self):
+        """ Send a heartbeat request. This is needed in order to keep a session alive """
+        if self._session is not None:
+            url = '%s/sessions/v1/%s' % (self._base, self._session)
+            self._do_put(url, '')
+
+    @contextmanager
+    def session(self, *args, **kwargs):
+        """ Session handling using a context manager """
+        yield self.start_session(*args, **kwargs)
+        self.close_session()
+
+    def get(self, path):
+        """ Get a node """
+        url = "%s/znodes/v1%s" % (self._base, path)
+        return self._do_get(url)
+
+    def get_children(self, path):
+        """ Get all the children for a given path. This function creates a generator """
+        for child_path in self.get_children_paths(path, uris=True):
+            try:
+                yield self._do_get(child_path)
+            except ZooKeeper.NotFound:
+                continue
+
+    def get_children_paths(self, path, uris=False):
+        """ Get the paths for children nodes """
+        url = "%s/znodes/v1%s?view=children" % (self._base, path)
+        resp = self._do_get(url)
+        for child in resp.get('children', []):
+            yield child if not uris else resp['child_uri_template']\
+              .replace('{child}', urllib2.quote(child))
+       
+    def create(self, path, data=None, sequence=False, ephemeral=False):
+        """ Create a new node. By default this call creates a persistent znode.
+
+        You can also create an ephemeral or a sequential znode.
+        """
+        ri = path.rindex('/')
+        head, name = path[:ri+1], path[ri+1:]
+        if head != '/': head = head[:-1]
+
+        flags = {
+            'null': 'true' if data is None else 'false',
+            'ephemeral': 'true' if ephemeral else 'false',
+            'sequence': 'true' if sequence else 'false'
+        }
+        if ephemeral:
+            if self._session:
+                flags['session'] = self._session
+            else:
+                raise ZooKeeper.Error, 'You need a session '\
+                    'to create an ephemeral node'
+        flags = urllib.urlencode(flags)
+
+        url = "%s/znodes/v1%s?op=create&name=%s&%s" % \
+            (self._base, head, name, flags)
+
+        return self._do_post(url, data)
+
+    def set(self, path, data=None, version=-1, null=False):
+        """ Set the value of node """
+        url = "%s/znodes/v1%s?%s" % (self._base, path, \
+            urllib.urlencode({
+                'version': version,
+                'null': 'true' if null else 'false'
+        }))
+        return self._do_put(url, data)
+
+    def delete(self, path, version=-1):
+        """ Delete a znode """
+        if type(path) is list:
+            map(lambda el: self.delete(el, version), path)
+            return
+
+        url = '%s/znodes/v1%s?%s' % (self._base, path, \
+            urllib.urlencode({
+                'version':version
+        }))
+        try:
+            return self._do_delete(url)
+        except urllib2.HTTPError, e:
+            if e.code == 412:
+                raise ZooKeeper.WrongVersion(path)
+            elif e.code == 404:
+                raise ZooKeeper.NotFound(path)
+            raise
+
+    def recursive_delete(self, path):
+        """ Delete all the nodes from the tree """
+        for child in self.get_children_paths(path):
+            fp = ("%s/%s" % (path, child)).replace('//', '/')
+            self.recursive_delete(fp)
+        self.delete(path)
+
+    def exists(self, path):
+        """ Do a znode exists """
+        try:
+            self.get(path)
+            return True
+        except ZooKeeper.NotFound:
+            return False
+
+    def _do_get(self, uri):
+        """ Send a GET request and convert errors to exceptions """
+        try:
+            req = urllib2.urlopen(uri)
+            resp = simplejson.load(req)
+
+            if 'Error' in resp:
+               raise ZooKeeper.Error(resp['Error'])
+
+            return resp
+        except urllib2.HTTPError, e:
+            if e.code == 404:
+                raise ZooKeeper.NotFound(uri)
+            raise
+
+    def _do_post(self, uri, data=None):
+        """ Send a POST request and convert errors to exceptions """
+        try:
+            req = urllib2.Request(uri, {})
+            req.add_header('Content-Type', 'application/octet-stream')
+            if data is not None:
+                req.add_data(data)
+
+            resp = simplejson.load(urllib2.urlopen(req))
+            if 'Error' in resp:
+                raise ZooKeeper.Error(resp['Error'])
+            return resp
+
+        except urllib2.HTTPError, e:
+            if e.code == 201:
+                return True
+            elif e.code == 409:
+                raise ZooKeeper.ZNodeExists(uri)
+            elif e.code == 401:
+                raise ZooKeeper.InvalidSession(uri)
+            raise
+
+    def _do_delete(self, uri):
+        """ Send a DELETE request """
+        req = RequestWithMethod(uri)
+        req.set_method('DELETE')
+        req.add_header('Content-Type', 'application/octet-stream')
+        return urllib2.urlopen(req).read()
+
+    def _do_put(self, uri, data):
+        """ Send a PUT request """
+        try:
+            req = RequestWithMethod(uri)
+            req.set_method('PUT')
+            req.add_header('Content-Type', 'application/octet-stream')
+            if data is not None:
+                req.add_data(data)
+
+            return urllib2.urlopen(req).read()
+        except urllib2.HTTPError, e:
+            if e.code == 412: # precondition failed
+                raise ZooKeeper.WrongVersion(uri)
+            raise
+

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/settings.py
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/settings.py?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/settings.py (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/settings.py Wed Aug 18 05:47:51 2010
@@ -0,0 +1,30 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+DJANGO_APPS = [ "zkui" ]
+NICE_NAME = "ZooKeeper Browser"
+REQUIRES_HADOOP = False
+
+CLUSTERS = [{
+        'nice_name': 'Default',
+        'hostport': 'localhost:2181,localhost:2182,localhost:2183',
+        'rest_gateway': 'http://localhost:9998'
+    }
+]
+
+DEPENDER_PACKAGE_YMLS = [
+    "src/zkui/static/js/package.yml",
+]

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/art/line_icons.png
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/art/line_icons.png?rev=986569&view=auto
==============================================================================
Binary file - no diff available.

Propchange: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/art/line_icons.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/art/zkui.png
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/art/zkui.png?rev=986569&view=auto
==============================================================================
Binary file - no diff available.

Propchange: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/art/zkui.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/bootstrap.js
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/bootstrap.js?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/bootstrap.js (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/bootstrap.js Wed Aug 18 05:47:51 2010
@@ -0,0 +1,32 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+CCS.Desktop.register({
+	Zkui : {
+		name : 'ZooKeeper Browser',
+		css : '/zkui/static/css/zkui.css',
+		require: [ 'Zkui' ],
+		launch: function(path, options){
+			return new Zkui(path || '/zkui/', options);
+		},
+		menu: {
+			id: 'ccs-zkui-menu',
+			img: {
+				src: '/zkui/static/art/zkui.png'
+			}
+		},
+		help: '/help/zkui/'
+	}
+});

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/css/zkui.css
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/css/zkui.css?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/css/zkui.css (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/css/zkui.css Wed Aug 18 05:47:51 2010
@@ -0,0 +1,56 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+.zkui img.zkui_icon {
+	width: 55px;
+	height: 55px;
+	position: absolute;
+	top: 27px;
+	left: 3px;
+}
+
+div.zkui .left_col li {
+    margin: 5px 0px;
+    font-size: 16px;
+    background-color: white;
+    color: black;
+    padding: 2px 1px 1px 5px;
+    -moz-border-radius: 3px;
+    -webkit-border-radius: 3px;
+    border: solid black 1px;
+}
+
+div.zkui .left_col li:hover {
+    background-color: lightBlue;
+    color: white;
+}
+
+div.zkui .left_col li a {
+    color: black;
+    display: block;
+}
+
+div.zkui .left_col li a:hover {
+    text-decoration: none;
+}
+
+div.zkui .createZnodeForm td,
+div.zkui .editZnodeForm td {
+  padding: 5px;
+}
+

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/help/index.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/help/index.html?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/help/index.html (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/help/index.html Wed Aug 18 05:47:51 2010
@@ -0,0 +1,10 @@
+
+<h1>ZooKeeper Browser</h1>
+
+
+<p>ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services</p>
+
+<h2>About</h2>
+
+<p>The ZooKeeper Browser application allows you to see how the cluster nodes are working and also allows you to do CRUD operations on the znode hierarchy.</p>
+

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/js/Source/Zkui/Zkui.js
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/js/Source/Zkui/Zkui.js?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/js/Source/Zkui/Zkui.js (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/js/Source/Zkui/Zkui.js Wed Aug 18 05:47:51 2010
@@ -0,0 +1,50 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/*
+---
+
+script: Zkui.js
+
+description: Defines Zkui; a Hue application that extends CCS.JBrowser.
+
+authors:
+- Unknown
+
+requires:
+- ccs-shared/CCS.JBrowser
+
+provides: [Zkui]
+
+...
+*/
+ART.Sheet.define('window.art.browser.zkui', {
+	'min-width': 620
+});
+
+var Zkui = new Class({
+
+	Extends: CCS.JBrowser,
+
+	options: {
+		className: 'art browser logo_header zkui'
+	},
+
+	initialize: function(path, options){
+		this.parent(path || '/zkui/', options);
+	}
+
+});

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/js/package.yml
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/js/package.yml?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/js/package.yml (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/static/js/package.yml Wed Aug 18 05:47:51 2010
@@ -0,0 +1,5 @@
+copyright: Apache License v2.0
+version: 0.1
+description: ZooKeeper Browser
+name: ZooKeeper Browser
+sources: [Source/Zkui/Zkui.js]

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/stats.py
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/stats.py?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/stats.py (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/stats.py Wed Aug 18 05:47:51 2010
@@ -0,0 +1,170 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import socket
+import re
+
+from StringIO import StringIO
+
+class Session(object):
+
+  class BrokenLine(Exception): pass
+
+  def __init__(self, session):
+    m = re.search('/(\d+\.\d+\.\d+\.\d+):(\d+)\[(\d+)\]\((.*)\)', session)
+    if m:
+        self.host = m.group(1)
+        self.port = m.group(2)
+        self.interest_ops = m.group(3)
+        for d in m.group(4).split(","):
+            k,v = d.split("=")
+            self.__dict__[k] = v
+    else:
+        raise Session.BrokenLine() 
+
+class ZooKeeperStats(object):
+
+    def __init__(self, host='localhost', port='2181', timeout=1):
+        self._address = (host, int(port))
+        self._timeout = timeout
+
+    def get_stats(self):
+        """ Get ZooKeeper server stats as a map """
+        data = self._send_cmd('mntr')
+        if data:
+            return self._parse(data)
+        else:
+            data = self._send_cmd('stat')
+            return self._parse_stat(data)
+
+    def get_clients(self):
+      """ Get ZooKeeper server clients """
+      clients = []
+
+      stat = self._send_cmd('stat')
+      if not stat:
+        return clients
+
+      sio = StringIO(stat)
+
+      #skip two lines
+      sio.readline()
+      sio.readline()
+
+      for line in sio:
+        if not line.strip():
+          break
+        try:
+          clients.append(Session(line.strip()))
+        except Session.BrokenLine:
+          continue
+
+      return clients
+
+    def _create_socket(self):
+        return socket.socket()
+
+    def _send_cmd(self, cmd):
+        """ Send a 4letter word command to the server """
+        s = self._create_socket()
+        s.settimeout(self._timeout)
+
+        s.connect(self._address)
+        s.send(cmd)
+
+        data = s.recv(2048)
+        s.close()
+
+        return data
+
+    def _parse(self, data):
+        """ Parse the output from the 'mntr' 4letter word command """
+        h = StringIO(data)
+        
+        result = {}
+        for line in h.readlines():
+            try:
+                key, value = self._parse_line(line)
+                result[key] = value
+            except ValueError:
+                pass # ignore broken lines
+
+        return result
+
+    def _parse_stat(self, data):
+        """ Parse the output from the 'stat' 4letter word command """
+        h = StringIO(data)
+
+        result = {}
+        
+        version = h.readline()
+        if version:
+            result['zk_version'] = version[version.index(':')+1:].strip()
+
+        # skip all lines until we find the empty one
+        while h.readline().strip(): pass
+
+        for line in h.readlines():
+            m = re.match('Latency min/avg/max: (\d+)/(\d+)/(\d+)', line)
+            if m is not None:
+                result['zk_min_latency'] = int(m.group(1))
+                result['zk_avg_latency'] = int(m.group(2))
+                result['zk_max_latency'] = int(m.group(3))
+                continue
+
+            m = re.match('Received: (\d+)', line)
+            if m is not None:
+                result['zk_packets_received'] = int(m.group(1))
+                continue
+
+            m = re.match('Sent: (\d+)', line)
+            if m is not None:
+                result['zk_packets_sent'] = int(m.group(1))
+                continue
+
+            m = re.match('Outstanding: (\d+)', line)
+            if m is not None:
+                result['zk_outstanding_requests'] = int(m.group(1))
+                continue
+
+            m = re.match('Mode: (.*)', line)
+            if m is not None:
+                result['zk_server_state'] = m.group(1)
+                continue
+
+            m = re.match('Node count: (\d+)', line)
+            if m is not None:
+                result['zk_znode_count'] = int(m.group(1))
+                continue
+
+        return result 
+
+    def _parse_line(self, line):
+        try:
+            key, value = map(str.strip, line.split('\t'))
+        except ValueError:
+            raise ValueError('Found invalid line: %s' % line)
+
+        if not key:
+            raise ValueError('The key is mandatory and should not be empty')
+
+        try:
+            value = int(value)
+        except (TypeError, ValueError):
+            pass
+
+        return key, value
+

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/clients.mako
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/clients.mako?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/clients.mako (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/clients.mako Wed Aug 18 05:47:51 2010
@@ -0,0 +1,51 @@
+<%!
+#  Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+%>
+
+<%namespace name="shared" file="shared_components.mako" />
+
+${shared.header("ZooKeeper Browser > Clients > %s:%s" % (host, port))}
+
+<h1>${host}:${port} :: client connections</h1>
+<br />
+
+% if clients:
+  <table data-filters="HtmlTable"> 
+  <thead>
+    <tr>
+      <th>Host</th>
+      <th>Port</th>
+      <th>Interest Ops</th>
+      <th>Queued</th>
+      <th>Received</th>
+      <th>Sent</th>
+  </thead>
+  % for client in clients:
+    <tr>
+      <td>${client.host}</td>
+      <td>${client.port}</td>
+      <td>${client.interest_ops}</td>
+      <td>${client.queued}</td>
+      <td>${client.recved}</td>
+      <td>${client.sent}</td>
+    </tr>
+  % endfor
+  </table>
+% endif
+
+${shared.footer()}
+

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/create.mako
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/create.mako?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/create.mako (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/create.mako Wed Aug 18 05:47:51 2010
@@ -0,0 +1,34 @@
+<%!
+#  Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+%>
+<%namespace name="shared" file="shared_components.mako" />
+
+${shared.header("ZooKeeper Browser > Create Znode")}
+
+<h2>Create New Znode :: ${path}</h2>
+<hr /><br />
+
+<form class="createZnodeForm" action="" method="POST">
+<table align="center">
+  ${form.as_table()|n}
+<tr><td colspan="2" align="right">
+  <button type="submit">Create</button>
+</td></tr>
+</table>
+</form>
+
+${shared.footer()}

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/edit.mako
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/edit.mako?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/edit.mako (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/edit.mako Wed Aug 18 05:47:51 2010
@@ -0,0 +1,34 @@
+<%!
+#  Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+%>
+<%namespace name="shared" file="shared_components.mako" />
+
+${shared.header("ZooKeeper Browser > Edit Znode > %s" % path)}
+
+<h2>Edit Znode Data :: ${path}</h2>
+<hr /><br />
+
+<form class="editZnodeForm" action="" method="POST">
+<table align="center">
+  ${form.as_table()|n}
+<tr><td colspan="2" align="right">
+  <button type="submit">Save</button>
+</td></tr>
+</table>
+</form>
+
+${shared.footer()}

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/index.mako
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/index.mako?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/index.mako (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/index.mako Wed Aug 18 05:47:51 2010
@@ -0,0 +1,54 @@
+<%!
+#  Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+%>
+<%namespace name="shared" file="shared_components.mako" />
+
+${shared.header("ZooKeeper Browser")}
+
+<h2>Overview</h2>
+
+<br />
+
+% for i, c in enumerate(overview):
+  <h3> ${i+1}. <a href="${url('zkui.views.view', id=i)}">${c['nice_name']} Cluster Overview</a></h3><br />
+
+  <table data-filters="HtmlTable">
+  <thead>
+    <tr>
+      <th>Node</th>
+      <th>Role</th>
+      <th>Avg Latency</th>
+      <th>Watch Count</th>
+      <th>Version</th>
+    </tr>
+  </thead>
+  % for host, stats in c['stats'].items():
+    <tr>
+      <td>${host}</td>
+      <td>${stats.get('zk_server_state', '')}</td>
+      <td>${stats.get('zk_avg_latency', '')}</td>
+      <td>${stats.get('zk_watch_count', '')}</td>
+      <td>${stats.get('zk_version', '')}</td>
+    </tr>
+  % endfor
+  </table>
+
+  <br /><br />
+% endfor 
+
+${shared.footer()}
+

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/shared_components.mako
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/shared_components.mako?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/shared_components.mako (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/shared_components.mako Wed Aug 18 05:47:51 2010
@@ -0,0 +1,66 @@
+<%!
+#  Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+%>
+
+<%!
+import datetime
+from django.template.defaultfilters import urlencode, escape
+from zkui import settings
+%>
+
+<%def name="header(title='ZooKeeper Browser', toolbar=True)">
+  <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+  <html>
+    <head>
+      <title>${title}</title>
+    </head>
+    <body>
+      % if toolbar:
+      <div class="toolbar">
+        <a href="${url('zkui.views.index')}"><img src="/zkui/static/art/zkui.png" class="zkui_icon"/></a>
+      </div>
+      % endif
+
+    <div data-filters="SplitView">
+    <div class="left_col jframe_padded" style="width:150px;">
+        <ul>
+          <li><a href="${url("zkui.views.index")}">Overview</a></li>
+        </ul>
+        <br />
+
+        <h2>Clusters</h2>
+        <ul>
+            % for id, c in enumerate(settings.CLUSTERS):
+                <li><a href="${url("zkui.views.view", id=id)}">
+                    ${c['nice_name']}</a></li>
+            % endfor
+        </ul>
+    </div>
+
+    <div class="right_col jframe_padded">
+</%def>
+
+<%def name="info_button(url, text)">
+  <a data-filters="ArtButton" href="${url}" style="background: url(/static/art/info.png) left 50%; padding: 6px 6px 6px 20px; margin: 10px;" data-icon-styles="{'width': 14, 'height': 14}">${text}</a>
+</%def>
+
+<%def name="footer()">
+        </div>
+    </div>
+    </body>
+  </html>
+</%def>

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/tree.mako
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/tree.mako?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/tree.mako (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/tree.mako Wed Aug 18 05:47:51 2010
@@ -0,0 +1,75 @@
+<%!
+#  Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+%>
+<%namespace name="shared" file="shared_components.mako" />
+
+${shared.header("ZooKeeper Browser > Tree > %s > %s" % (cluster['nice_name'], path))}
+
+<h1>${cluster['nice_name'].lower()} :: ${path}</h1>
+<br />
+
+<table data-filters="HtmlTable">
+  <thead>
+  <th colspan="2">Children</th>
+  </thead>
+  % for child in children:
+    <tr><td width="100%">
+      <a href="${url('zkui.views.tree', id=cluster['id'], \
+          path=("%s/%s" % (path, child)).replace('//', '/'))}">
+      ${child}</a>
+    </td><td>
+      <a title="Delete ${child}" class="delete frame_tip confirm_and_post" alt="Are you sure you want to delete ${child}?" href="${url('zkui.views.delete', id=cluster['id'], \
+          path=("%s/%s" % (path, child)).replace('//', '/'))}">Delete</a>
+    </td></tr>
+  % endfor
+</table>
+<br />
+<span style="float: right">
+  ${shared.info_button(url('zkui.views.create', id=cluster['id'], path=path), 'Create New')}
+</span>
+
+<div style="clear: both"></div>
+
+<h2>data :: base64 :: length :: ${znode.get('dataLength', 0)}</h2>
+<br />
+
+<textarea name="data64" style="width: 100%;" rows="5" readonly="readonly">${znode.get('data64', '')}</textarea>
+<div style="clear: both"></div>
+<span style="float: right">
+  ${shared.info_button(url('zkui.views.edit_as_base64', id=cluster['id'], path=path), 'Edit as Base64')}
+  ${shared.info_button(url('zkui.views.edit_as_text', id=cluster['id'], path=path), 'Edit as Text')}
+</span>
+<div style="clear: both"></div>
+<br />
+
+<h2>stat information</h2>
+<br />
+
+<table data-filters="HtmlTable">
+  <thead><tr><th>Key</th>
+    <th width="80%">Value</th></tr></thead>
+  % for key in ('pzxid', 'ctime', 'aversion', 'mzxid', \
+      'ephemeralOwner', 'version', 'mtime', 'cversion', 'czxid'):
+    <tr><td>${key}</td><td>${znode[key]}</td></tr> 
+  % endfor
+</table>
+
+<br />
+<a target="_blank" href="http://hadoop.apache.org/zookeeper/docs/current/zookeeperProgrammers.html#sc_zkStatStructure">Details on stat information.</a>
+
+${shared.footer()}
+

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/view.mako
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/view.mako?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/view.mako (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/templates/view.mako Wed Aug 18 05:47:51 2010
@@ -0,0 +1,128 @@
+<%!
+#  Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+%>
+<%namespace name="shared" file="shared_components.mako" />
+
+${shared.header("ZooKeeper Browser > %s" % cluster['nice_name'])}
+
+<%def name="show_stats(stats)">
+    <thead>
+      <tr><th>Key</th>
+      <th width="100%">Value</th></tr>
+    </thead>
+
+    <tr><td>Version</td>
+      <td>${stats.get('zk_version')}</td>
+    </tr>
+
+    <tr><td>Latency</td><td>
+      Min: ${stats.get('zk_min_latency', '')}
+      Avg: ${stats.get('zk_avg_latency', '')}
+      Max: ${stats.get('zk_max_latency', '')}
+    </td></tr>
+
+    <tr><td>Packets</td>
+      <td>Sent: ${stats.get('zk_packets_sent', '')}
+      Received: ${stats.get('zk_packets_received', '')}
+      </td>
+    </tr>
+
+    <tr><td>Outstanding Requests</td>
+      <td>${stats.get('zk_outstanding_requests', '')}</td>
+    </tr>
+
+    <tr><td>Watch Count</td>
+      <td>${stats.get('zk_watch_count', '')}</td>
+    </tr>
+
+    <tr><td>Open FD Count</td>
+      <td>${stats.get('zk_open_file_descriptor_count', '')}</td>
+    </tr>
+
+    <tr><td>Max FD Count</td>
+      <td>${stats.get('zk_max_file_descriptor_count', '')}</td>
+    </tr>
+
+</%def> 
+
+<h2> ${cluster['nice_name']} Cluster Overview </h2>
+
+${shared.info_button(url('zkui.views.tree', id=cluster['id'], path='/'), 'View Znode Hierarchy')}
+
+<br /><br />
+
+% if leader:
+<h2>General</h2>
+
+<table data-filters="HtmlTable">
+  <thead>
+    <tr><th>Key</th><th width="100%">Value</th></tr>
+  </thead>
+
+  <tr><td>ZNode Count</td>
+    <td>${leader.get('zk_znode_count', '')}</td></tr>
+
+  <tr><td>Ephemerals Count</td>
+    <td>${leader.get('zk_ephemerals_count', '')}</td></tr>
+
+  <tr><td>Approximate Data Size</td>
+    <td>${leader.get('zk_approximate_data_size', '')} bytes</td></tr>
+
+</table>
+<br /><br />
+% endif
+
+% if leader:
+  <h2>node :: ${leader['host']} :: leader</h2>
+
+  ${shared.info_button(url('zkui.views.clients', host=leader['host']), 'View Client Connections')}
+
+  <br /><br />
+  <table data-filters="HtmlTable">
+    ${show_stats(leader)}
+    
+    <tr><td>Followers</td>
+      <td>${leader.get('zk_followers', '')}</td>
+    </tr>
+
+    <tr><td>Synced Followers</td>
+      <td>${leader.get('zk_synced_followers', '')}</td>
+    </tr>
+
+    <tr><td>Pending Syncs</td>
+      <td>${leader.get('zk_pending_syncs', '')}</td>
+    </tr>
+  
+  </table>
+<br /><br />
+% endif
+
+% for stats in followers:
+  <h2>node :: ${stats['host']} :: follower</h2>
+  <br />
+
+  ${shared.info_button(url('zkui.views.clients', host=stats['host']), 'View Client Connections')}
+
+  <br /><br />
+  <table data-filters="HtmlTable">
+    ${show_stats(stats)}
+  </table>
+  <br /><br />
+% endfor
+
+${shared.footer()}
+

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/urls.py
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/urls.py?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/urls.py (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/urls.py Wed Aug 18 05:47:51 2010
@@ -0,0 +1,28 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from django.conf.urls.defaults import patterns, url
+
+urlpatterns = patterns('zkui',
+  url(r'^$', 'views.index'),
+  url(r'view/(?P<id>\d+)$', 'views.view'),
+  url(r'clients/(?P<host>.+)$', 'views.clients'),
+  url(r'tree/(?P<id>\d+)(?P<path>.+)$', 'views.tree'),
+  url(r'create/(?P<id>\d+)(?P<path>.*)$', 'views.create'),
+  url(r'delete/(?P<id>\d+)(?P<path>.*)$', 'views.delete'),
+  url(r'edit/base64/(?P<id>\d+)(?P<path>.*)$', 'views.edit_as_base64'),
+  url(r'edit/text/(?P<id>\d+)(?P<path>.*)$', 'views.edit_as_text')
+)

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/utils.py
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/utils.py?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/utils.py (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/utils.py Wed Aug 18 05:47:51 2010
@@ -0,0 +1,33 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from zkui import settings
+
+from django.http import Http404
+
+def get_cluster_or_404(id):
+  try:
+    id = int(id)
+    if not (0 <= id < len(settings.CLUSTERS)):
+      raise ValueError, 'Undefined cluster id.'
+  except (TypeError, ValueError):
+    raise Http404()
+
+  cluster = settings.CLUSTERS[id]
+  cluster['id'] = id
+
+  return cluster
+

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/views.py
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/views.py?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/views.py (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/views.py Wed Aug 18 05:47:51 2010
@@ -0,0 +1,165 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from desktop.lib.django_util import render
+from django.http import Http404
+
+from zkui import settings
+from zkui.stats import ZooKeeperStats
+from zkui.rest import ZooKeeper
+from zkui.utils import get_cluster_or_404
+from zkui.forms import CreateZNodeForm, EditZNodeForm
+
+def _get_global_overview():
+  overview = []
+  for c in settings.CLUSTERS:
+    overview.append(_get_overview(c))
+  return overview
+
+def _get_overview(cluster):
+  stats = {}
+  for s in cluster['hostport'].split(','):
+    host, port = map(str.strip, s.split(':'))
+
+    zks = ZooKeeperStats(host, port)
+    stats[s] = zks.get_stats() or {}
+
+  cluster['stats'] = stats
+  return cluster
+
+def _group_stats_by_role(cluster):
+  leader, followers = None, []
+  for host, stats in cluster['stats'].items():
+    stats['host'] = host
+
+    if stats.get('zk_server_state') == 'leader':
+      leader = stats
+
+    elif stats.get('zk_server_state') == 'follower':
+      followers.append(stats) 
+
+  return leader, followers           
+ 
+def index(request):
+  overview = _get_global_overview()  
+  return render('index.mako', request, 
+    dict(overview=overview))
+
+def view(request, id):
+  cluster = get_cluster_or_404(id)
+
+  cluster = _get_overview(cluster)
+  leader, followers = _group_stats_by_role(cluster)
+
+  return render('view.mako', request, 
+    dict(cluster=cluster, leader=leader, followers=followers))
+
+def clients(request, host):
+  parts = host.split(':')  
+  if len(parts) != 2:
+    raise Http404
+
+  host, port = parts
+  zks = ZooKeeperStats(host, port)
+  clients = zks.get_clients()
+
+  return render('clients.mako', request,
+    dict(host=host, port=port, clients=clients))
+
+def tree(request, id, path):
+  cluster = get_cluster_or_404(id)
+  zk = ZooKeeper(cluster['rest_gateway'])
+
+  znode = zk.get(path)
+  children = sorted(zk.get_children_paths(path))
+  
+  return render('tree.mako', request,
+    dict(cluster=cluster, path=path, \
+      znode=znode, children=children))
+
+def delete(request, id, path):
+  cluster = get_cluster_or_404(id)
+  if request.method == 'POST':
+    zk = ZooKeeper(cluster['rest_gateway'])
+    try:
+      zk.recursive_delete(path)
+    except ZooKeeper.NotFound:
+      pass
+
+  return tree(request, id, path[:path.rindex('/')] or '/')
+
+def create(request, id, path):
+  cluster = get_cluster_or_404(id)
+
+  if request.method == 'POST':
+    form = CreateZNodeForm(request.POST)
+    if form.is_valid():
+      zk = ZooKeeper(cluster['rest_gateway'])
+
+      full_path = ("%s/%s" % (path, form.cleaned_data['name']))\
+        .replace('//', '/')
+
+      zk.create(full_path, \
+        form.cleaned_data['data'], \
+        sequence = form.cleaned_data['sequence'])
+      return tree(request, id, path)
+  else:
+    form = CreateZNodeForm()
+
+  return render('create.mako', request, 
+    dict(path=path, form=form))
+
+def edit_as_base64(request, id, path):
+  cluster = get_cluster_or_404(id)
+  zk = ZooKeeper(cluster['rest_gateway'])
+  node = zk.get(path)
+
+  if request.method == 'POST':
+    form = EditZNodeForm(request.POST)
+    if form.is_valid():
+      # TODO is valid base64 string?
+      data = form.cleaned_data['data'].decode('base64')
+      zk.set(path, data, form.cleaned_data['version'])
+
+    return tree(request, id, path)
+  else:
+    form = EditZNodeForm(dict(\
+      data=node.get('data64', ''), 
+      version=node.get('version', '-1')))
+
+  return render('edit.mako', request,
+    dict(path=path, form=form))
+
+def edit_as_text(request, id, path):
+  cluster = get_cluster_or_404(id)
+  zk = ZooKeeper(cluster['rest_gateway'])
+  node = zk.get(path)
+
+  if request.method == 'POST':
+    form = EditZNodeForm(request.POST)
+    if form.is_valid():
+      zk.set(path, form.cleaned_data['data'])
+
+    return tree(request, id, path)
+  else:
+    form = EditZNodeForm(dict(data=node.get('data64', '')\
+      .decode('base64').strip(), 
+      version=node.get('version', '-1')))
+
+  return render('edit.mako', request,
+    dict(path=path, form=form))
+
+

Added: hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/windmilltests.py
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/windmilltests.py?rev=986569&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/windmilltests.py (added)
+++ hadoop/zookeeper/trunk/src/contrib/huebrowser/zkui/src/zkui/windmilltests.py Wed Aug 18 05:47:51 2010
@@ -0,0 +1,23 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from desktop.lib.windmill_util import logged_in_client
+
+def test_zkui():
+  """ launches the default view for zkui """
+  client = logged_in_client()
+  client.click(id='ccs-zkui-menu')
+  client.waits.forElement(classname='CCS-ZKUI', timeout='2000')  



Mime
View raw message