Преглед на файлове

HUE-202. Implementing sample for tree view. A "pstree" jframegallery.

Implementing sample for tree view.  A "pstree" jframegallery.
Philip Zeyliger преди 15 години
родител
ревизия
8bddf179d5

+ 69 - 0
apps/jframegallery/src/jframegallery/templates/pstree.mako

@@ -0,0 +1,69 @@
+## Licensed to Cloudera, Inc. under one
+## or more contributor license agreements.  See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership.  Cloudera, Inc. 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.
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+	<head>
+		<title>Process Viewer</title>
+	</head>
+	<body>
+        
+<a href="${request_path}?show_all=true">Show everything</a>
+<table data-filters="HtmlTable" class="treeView">
+
+<%def name="r(node, depth, path)">
+  <tr class="table-folder table-depth-${depth}">
+  % if node.children:
+    <td class="expand">${node.pid}</td>
+  % else:
+    <td>${node.pid}</td>
+  % endif
+  <td>
+  % if path in open_paths:
+    <a href="${remove(path)}">collapse</a>
+  % elif node.children:
+    <a href="${add(path)}">expand</a>
+  % endif
+
+  <a href="${request_path}?subtree=${node.pid}">subset</a>
+  </td>
+  <td>${node.user}</td>
+  <td>${node.cputime}</td>
+  <td>${node.command}</td>
+  </tr>
+  % if path in open_paths or show_all:
+    % for child in node.children:
+      ${r(child, depth+1, path+"/"+str(child.pid))}
+    % endfor
+  % endif
+</%def>
+
+<thead>
+<th>pid</th>
+<th>links</th>
+<th>user</th>
+<th>cputime</th>
+<th>command</th>
+</thead>
+<tbody>
+% for top in tops:
+ ${r(top, 0, "/" + str(top.pid))}
+% endfor
+</tbody>
+</table>
+
+
+        </body>
+</html>

+ 1 - 0
apps/jframegallery/src/jframegallery/urls.py

@@ -31,5 +31,6 @@ urlpatterns = patterns('jframegallery',
   url(r'^error_message_exception.*$', 'views.error_message_exception'),
   url(r'^error_popup_exception.*$', 'views.error_popup_exception'),
   url(r'^forms_with_dependencies.*$', 'views.forms_with_dependencies'),
+  url(r'^pstree.*$', 'views.pstree'),
   url(r'^(?P<path>.*)$', 'views.show')
 )

+ 83 - 0
apps/jframegallery/src/jframegallery/views.py

@@ -117,3 +117,86 @@ def forms_with_dependencies(request):
   else:
     form = DepForm()
   return render("forms_with_dependencies.mako", request, dict(form=form, data=data))
+
+class PsLine(object):
+  def __init__(self, user, pid, ppid, pgid, cputime, command):
+    self.user = user
+    self.pid = int(pid)
+    self.ppid = int(ppid)
+    self.pgid = int(pgid)
+    self.cputime = cputime
+    self.command = command
+    self.children = []
+
+def pstree(request):
+  """
+  Draws 'pstree' by using output from ps command.
+
+  GET arguments:
+    subtree: show only pids below this tree
+    show_all: expand the entire tree
+    paths: slash-separated paths that are expanded
+      (can be specified multiple times)
+  
+  """
+  import subprocess
+  import urllib
+  import re
+
+  # Call ps
+  p = subprocess.Popen(args=["ps", "-axwwo", "user,pid,ppid,pgid,cputime,command"], stdout=subprocess.PIPE)
+
+  children = {}
+  first = True
+  if "subtree" in request.GET:
+    subtree = long(request.GET.get("subtree"))
+  else:
+    subtree = None
+  subtree_top = None
+
+  # Parse in the data
+  for row in p.stdout:
+    if first:
+      # skip header line
+      first = False
+      continue
+    data = user, pid, ppid, pgid, cputime, command = re.split("\s+", row.rstrip(), 5)
+    ps = PsLine(*data)
+    if ps.pid == subtree:
+      subtree_top = ps
+    if ps.ppid in children:
+      children[ps.ppid].append(ps)
+    else:
+      children[ps.ppid] = [ps]
+
+  # Utility method to create the tree
+  def fill(root):
+    root.children = children.get(root.pid, [])
+    for child in root.children:
+      fill(child)
+
+  if subtree_top:
+    fill(subtree_top)
+    tops = subtree_top.children
+  else:
+    # Start with init and create the tree
+    assert len(children[0]) == 1
+    top = children[0][0]
+    fill(top)
+    tops = [top]
+
+  # Methods to manipulate the extant paths list; used by the template.
+  def add(p):
+    paths = list(request.GET.getlist("paths")) # make a copy
+    paths.append(p)
+    return request.path + "?" + "&".join(urllib.urlencode([("paths", x)]) for x in paths)
+  def remove(p):
+    paths = list(request.GET.getlist("paths")) # make a copy
+    paths.remove(p)
+    return request.path + "?" + "&".join(urllib.urlencode([("paths", x)]) for x in paths)
+
+  paths = request.GET.getlist("paths")
+  return render("pstree.mako", request, dict(
+    tops=tops, show_all=request.GET.get("show_all"), 
+    open_paths=paths, request_path=request.path,
+    add=add, remove=remove))