Pārlūkot izejas kodu

[Threads] Remove Threads tab from Administrator Server Tab (#3815)

* Basic frontend file found

* [Threads]Remove Threads tab from Admin Pages

* Removing the frontend file

* Removing the desktop.views.threads test

* Removing the COLLECT_THREADS instance from hue_collect_data.sh file

* Removing the hue_collect_data.sh file

* Adding test function back

* Passing the errors on GitHub

* Fixes based on runruff linting

* nit

* Fixes based on review comments

* Final changes based on review comments
Ananya_Agarwal 1 gadu atpakaļ
vecāks
revīzija
5ec331d402

+ 0 - 9
desktop/core/src/desktop/js/onePageViewModel.js

@@ -533,15 +533,6 @@ class OnePageViewModel {
         }
       },
       { url: '/desktop/dump_config', app: 'dump_config' },
-      {
-        url: '/desktop/debug/threads',
-        app: function () {
-          self.loadApp('threads');
-          self.getActiveAppViewModel(viewModel => {
-            viewModel.fetchThreads();
-          });
-        }
-      },
       {
         url: '/gist',
         app: function () {

+ 0 - 3
desktop/core/src/desktop/templates/about_layout.mako

@@ -67,9 +67,6 @@ def is_selected(section, matcher):
                 <li class="${is_selected(section, 'log_view')}">
                   <a href="${ url('desktop.views.log_view') }">${_('Server Logs')}</a>
                 </li>
-                <li class="${is_selected(section, 'threads')}">
-                  <a href="${ url('desktop.views.threads') }">${_('Threads')}</a>
-                </li>
                 % if METRICS.ENABLE_WEB_METRICS.get():
                 <li class="${is_selected(section, 'metrics')}">
                   <a href="${ url('desktop.lib.metrics.views.index') }">${_('Metrics')}</a>

+ 0 - 1
desktop/core/src/desktop/templates/global_js_constants.mako

@@ -102,7 +102,6 @@
     admin_wizard: { url: '/about/admin_wizard', title: '${_('Admin Wizard')}' },
     logs: { url: '/logs', title: '${_('Logs')}' },
     dump_config: { url: '/desktop/dump_config', title: '${_('Dump Configuration')}' },
-    threads: { url: '/desktop/debug/threads', title: '${_('Threads')}' },
     metrics: { url: '/desktop/metrics', title: '${_('Metrics')}' },
     taskserver: { url: '/task_server', title: '${_('Task Server')}' },
     connectors: { url: '/desktop/connectors', title: '${_('Connectors')}' },

+ 0 - 61
desktop/core/src/desktop/templates/threads.mako

@@ -1,61 +0,0 @@
-## 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.
-<%!
-import sys
-from desktop.views import commonheader, commonfooter
-if sys.version_info[0] > 2:
-  from django.utils.translation import gettext as _
-else:
-  from django.utils.translation import ugettext as _
-%>
-
-<%namespace name="actionbar" file="actionbar.mako" />
-<%namespace name="layout" file="about_layout.mako" />
-
-%if not is_embeddable:
-${ commonheader(_('Threads'), "about", user, request) | n,unicode }
-%endif
-
-
-<script type="text/javascript">
-  (function () {
-    var ThreadsViewModel = function () {
-      var self = this;
-      self.threads = ko.observable();
-      self.fetchThreads = function () {
-        window.simpleGet('/desktop/debug/threads', {}, {
-          successCallback: self.threads
-        });
-      };
-    };
-    $(document).ready(function () {
-      var viewModel = new ThreadsViewModel();
-      ko.applyBindings(viewModel, $('#threadsComponents')[0]);
-    });
-  })();
-</script>
-
-${layout.menubar(section='threads')}
-
-<div id="threadsComponents" class="container-fluid">
-  <div class="card card-small" style="padding-top: 10px">
-    <pre data-bind="text: $root.threads"></pre>
-  </div>
-</div>
-
-%if not is_embeddable:
-${ commonfooter(request, messages) | n,unicode }
-%endif

+ 2 - 9
desktop/core/src/desktop/tests.py

@@ -357,13 +357,6 @@ def test_paginator():
   assert_page(pgn.page(2), list(range(20, 25)), 21, 25)
 
 
-@pytest.mark.django_db
-def test_thread_dump():
-  c = make_logged_in_client()
-  response = c.get("/desktop/debug/threads", HTTP_X_REQUESTED_WITH='XMLHttpRequest')
-  assert b"test_thread_dump" in response.content
-
-
 def test_truncating_model():
   class TinyModel(TruncatingModel):
     short_field = CharField(max_length=10)
@@ -674,7 +667,7 @@ def test_app_permissions():
 @pytest.mark.django_db
 def test_error_handling_failure():
   # Change rewrite_user to call has_hue_permission
-  # Try to get filebrowser page
+  # Try to get logs page
   # test for default 500 page
   # Restore rewrite_user
   import desktop.auth.backend
@@ -698,7 +691,7 @@ def test_error_handling_failure():
     # Make sure we are showing default 500.html page.
     # See django.test.client#L246
     with pytest.raises(AttributeError):
-      c.get(reverse('desktop.views.threads'))
+      c.get(reverse('desktop.views.log_view'))
   finally:
     # Restore the world
     restore_django_debug()

+ 0 - 1
desktop/core/src/desktop/urls.py

@@ -87,7 +87,6 @@ dynamic_patterns += [
   re_path(r'^desktop/status_bar/?$', desktop_views.status_bar),
   re_path(r'^desktop/debug/is_alive$', desktop_views.is_alive),
   re_path(r'^desktop/debug/is_idle$', desktop_views.is_idle),
-  re_path(r'^desktop/debug/threads$', desktop_views.threads, name="desktop.views.threads"),
   re_path(r'^desktop/debug/memory$', desktop_views.memory),
   re_path(r'^desktop/debug/check_config$', desktop_views.check_config, name="desktop.views.check_config"),
   re_path(r'^desktop/debug/check_config_ajax$', desktop_views.check_config_ajax),

+ 71 - 60
desktop/core/src/desktop/views.py

@@ -15,44 +15,40 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from future import standard_library
-
-standard_library.install_aliases()
-import json
-import logging
 import os
 import re
-import six
-import socket
 import sys
-import tempfile
+import json
 import time
-import traceback
+import socket
+import logging
 import zipfile
-import validate
+import tempfile
+import traceback
+from io import StringIO as string_io
+from wsgiref.util import FileWrapper
 
-from django.http import HttpResponseRedirect
+import six
+import validate
+import django.views.debug
+from configobj import ConfigObj, ConfigObjError, get_extra_values
 from django.conf import settings
 from django.contrib.staticfiles.storage import staticfiles_storage
-from django.shortcuts import render as django_render
-from django.http import HttpResponse
+from django.http import HttpResponse, HttpResponseRedirect
 from django.http.response import StreamingHttpResponse
+from django.shortcuts import redirect, render as django_render
 from django.urls import reverse
-from django.shortcuts import redirect
+from django.utils.translation import gettext as _
 from django.views.decorators.http import require_POST
-from configobj import ConfigObj, get_extra_values, ConfigObjError
-from wsgiref.util import FileWrapper
 from webpack_loader.utils import get_static
-import django.views.debug
 
 import desktop.conf
 import desktop.log.log_buffer
-
 from desktop import appmanager
-from desktop.api import massaged_tags_for_json, massaged_documents_for_json, _get_docs
+from desktop.api import _get_docs, massaged_documents_for_json, massaged_tags_for_json
 from desktop.auth.backend import is_admin
 from desktop.auth.decorators import admin_required, hue_admin_required
-from desktop.conf import USE_NEW_EDITOR, HUE_LOAD_BALANCER, get_clusters, ENABLE_CONNECTORS
+from desktop.conf import ENABLE_CONNECTORS, HUE_LOAD_BALANCER, USE_NEW_EDITOR, get_clusters
 from desktop.lib import django_mako, fsmanager
 from desktop.lib.conf import GLOBAL_CONFIG, BoundConfig, _configs_from_dir
 from desktop.lib.config_spec_dump import ConfigSpec
@@ -61,21 +57,16 @@ from desktop.lib.i18n import smart_str
 from desktop.lib.paths import get_desktop_root
 from desktop.lib.thread_util import dump_traceback
 from desktop.lib.view_util import is_ajax
-from desktop.log.access import access_log_level, access_warn, AccessInfo
-from desktop.log import set_all_debug as _set_all_debug, reset_all_debug as _reset_all_debug, \
-                        get_all_debug as _get_all_debug, DEFAULT_LOG_DIR
-from desktop.models import Settings, hue_version, _get_apps, UserPreferences
+from desktop.log import (
+  DEFAULT_LOG_DIR,
+  get_all_debug as _get_all_debug,
+  reset_all_debug as _reset_all_debug,
+  set_all_debug as _set_all_debug,
+)
+from desktop.log.access import AccessInfo, access_log_level, access_warn
+from desktop.models import Settings, UserPreferences, _get_apps, hue_version
 from libsaml.conf import REQUIRED_GROUPS, REQUIRED_GROUPS_ATTRIBUTE
-from useradmin.models import get_profile
-from useradmin.models import User
-
-if sys.version_info[0] > 2:
-  from io import StringIO as string_io
-  from django.utils.translation import gettext as _
-else:
-  from StringIO import StringIO as string_io
-  from django.utils.translation import ugettext as _
-
+from useradmin.models import User, get_profile
 
 LOG = logging.getLogger()
 
@@ -83,12 +74,13 @@ LOG = logging.getLogger()
 def is_alive(request):
   return HttpResponse('')
 
+
 def samlgroup_check(request):
   if 'SAML2Backend' in desktop.auth.forms.get_backend_names():
     if REQUIRED_GROUPS.get():
       try:
         userprofile = get_profile(request.user)
-      except:
+      except Exception:
         return False
 
       json_data = json.loads(userprofile.json_data)
@@ -115,6 +107,7 @@ def samlgroup_check(request):
       LOG.info("User %s found in the required SAML groups %s" % (request.user.username, ",".join(saml_group_found)))
   return True
 
+
 def saml_login_headers(request):
   userprofile = get_profile(request.user)
   try:
@@ -125,9 +118,10 @@ def saml_login_headers(request):
   try:
     userprofile.update_data({'X-CSRF-TOKEN': request.META['CSRF_COOKIE']})
     userprofile.save()
-  except:
+  except Exception:
     LOG.error("X-CSRF-TOKEN header not found")
 
+
 def hue(request):
   current_app, other_apps, apps_list = _get_apps(request.user, '')
   clusters = list(get_clusters(request.user).values())
@@ -270,15 +264,18 @@ def log_view(request):
         prev_log_file_size = os.path.getsize(prev_log_file)
         with open(prev_log_file, 'rb') as fh1:
           fh1.seek(prev_log_file_size - BUF_SIZE - log_file_size)
-          for l in fh1.readlines(): buffer.append(l)
+          for line in fh1.readlines():
+            buffer.append(line)
       # read the current log file
       with open(log_file, 'rb') as fh:
         fh.seek(0)
-        for l in fh.readlines(): buffer.append(l)
+        for line in fh.readlines():
+          buffer.append(line)
     else:
       with open(log_file, 'rb') as fh:
         fh.seek(log_file_size - BUF_SIZE)
-        for l in fh.readlines(): buffer.append(l)
+        for line in fh.readlines():
+          buffer.append(line)
     return render('logs.mako', request, dict(
         log=buffer,
         query=request.GET.get("q", ""),
@@ -290,6 +287,7 @@ def log_view(request):
     )
   )
 
+
 def task_server_view(request):
   """
   This view renders the Task Server page with basic functionality.
@@ -303,6 +301,7 @@ def task_server_view(request):
     'users_json': json.dumps(list(User.objects.values_list('id', flat=True)))
   })
 
+
 @hue_admin_required
 @access_log_level(logging.WARN)
 def download_log_view(request):
@@ -327,22 +326,25 @@ def download_log_view(request):
         prev_log_file_size = os.path.getsize(prev_log_file)
         with open(prev_log_file, 'rb') as fh1:
           fh1.seek(prev_log_file_size - BUF_SIZE - log_file_size)
-          for l in fh1.readlines(): buffer.append(l)
+          for line in fh1.readlines():
+            buffer.append(line)
       # read the current log file
       with open(log_file, 'rb') as fh:
         fh.seek(0)
-        for l in fh.readlines(): buffer.append(l)
+        for line in fh.readlines():
+          buffer.append(line)
     else:
       with open(log_file, 'rb') as fh:
         fh.seek(log_file_size - BUF_SIZE)
-        for l in fh.readlines(): buffer.append(l)
+        for line in fh.readlines():
+          buffer.append(line)
     try:
       # We want to avoid doing a '\n'.join of the entire log in memory
       # in case it is rather big. So we write it to a file line by line
       # and pass that file to zipfile, which might follow a more efficient path.
       tmp = tempfile.NamedTemporaryFile()
       log_tmp = tempfile.NamedTemporaryFile("w+t") if sys.version_info[0] == 2 else tempfile.NamedTemporaryFile("w+t", encoding='utf-8')
-      for l in buffer:
+      for line in buffer:
         log_tmp.write(smart_str(l, errors='replace'))
       # This is not just for show - w/out flush, we often get truncated logs
       log_tmp.flush()
@@ -360,7 +362,7 @@ def download_log_view(request):
       response['Content-Disposition'] = 'attachment; filename=hue-logs-%s.zip' % t
       response['Content-Length'] = length
       return response
-    except Exception as e:
+    except Exception:
       LOG.exception("Couldn't construct zip file to write logs")
       return log_view(request)
 
@@ -384,6 +386,8 @@ def bootstrap(request):
 
 
 _status_bar_views = []
+
+
 def register_status_bar_view(view):
   global _status_bar_views
   _status_bar_views.append(view)
@@ -403,7 +407,7 @@ def status_bar(request):
         resp += r.content
       else:
         LOG.warning("Failed to execute status_bar view %s" % (view,))
-    except:
+    except Exception:
       LOG.exception("Failed to execute status_bar view %s" % (view,))
   return HttpResponse(resp)
 
@@ -416,19 +420,6 @@ def dump_config(request):
   return render("dump_config.mako", request, {})
 
 
-@hue_admin_required
-@access_log_level(logging.WARN)
-def threads(request):
-  """Dumps out server threads. Useful for debugging."""
-  out = string_io()
-  dump_traceback(file=out)
-
-  if is_ajax(request):
-    return HttpResponse(out.getvalue(), content_type="text/plain")
-  else:
-    return render("threads.mako", request, {'text': out.getvalue(), 'is_embeddable': request.GET.get('is_embeddable', False)})
-
-
 @hue_admin_required
 @access_log_level(logging.WARN)
 def memory(request):
@@ -483,10 +474,12 @@ def global_js_constants(request):
 def ace_sql_location_worker(request):
   return HttpResponse(render('ace_sql_location_worker.mako', request, None), content_type="application/javascript")
 
+
 def ace_sql_syntax_worker(request):
   return HttpResponse(render('ace_sql_syntax_worker.mako', request, None), content_type="application/javascript")
 
-#Redirect to static resources no need for auth. Fails with 401 with Knox.
+
+# Redirect to static resources no need for auth. Fails with 401 with Knox.
 @login_notrequired
 def dynamic_bundle(request, config, bundle_name):
   try:
@@ -498,28 +491,34 @@ def dynamic_bundle(request, config, bundle_name):
     LOG.exception("Failed loading dynamic bundle %s: %s" % (bundle_name, ex))
   return render("404.mako", request, dict(uri=request.build_absolute_uri()), status=404)
 
+
 def assist_m(request):
   return render('assist_m.mako', request, None)
 
+
 def index(request):
   return redirect('desktop_views_hue')
 
+
 def csrf_failure(request, reason=None):
   """Registered handler for CSRF."""
   access_warn(request, reason)
   return render("403_csrf.mako", request, dict(uri=request.build_absolute_uri()), status=403)
 
+
 @login_notrequired
 def serve_403_error(request, *args, **kwargs):
   """Registered handler for 403. We just return a simple error"""
   access_warn(request, "403 access forbidden")
   return render("403.mako", request, dict(uri=request.build_absolute_uri()), status=403)
 
+
 def serve_404_error(request, *args, **kwargs):
   """Registered handler for 404. We just return a simple error"""
   access_warn(request, "404 not found")
   return render("404.mako", request, dict(uri=request.build_absolute_uri()), status=404)
 
+
 def serve_500_error(request, *args, **kwargs):
   """Registered handler for 500. We use the debug view to make debugging easier."""
   try:
@@ -544,6 +543,7 @@ def serve_500_error(request, *args, **kwargs):
     #   - Packaging and install issues
     pass
 
+
 _LOG_LEVELS = {
   "critical": logging.CRITICAL,
   "error": logging.ERROR,
@@ -616,6 +616,7 @@ def commonheader(title, section, user, request=None, padding="90px", skip_topbar
     'banner_message': get_banner_message(request)
   })
 
+
 def get_banner_message(request):
   banner_message = None
   forwarded_host = request.get_host()
@@ -636,24 +637,31 @@ def get_banner_message(request):
 
   return banner_message
 
+
 def commonshare():
   return django_mako.render_to_string("common_share.mako", {})
 
+
 def commonshare2():
   return django_mako.render_to_string("common_share2.mako", {})
 
+
 def commonimportexport(request):
   return django_mako.render_to_string("common_import_export.mako", {'request': request})
 
+
 def login_modal(request):
   return desktop.auth.views.dt_login(request, True)
 
+
 def is_idle(request):
   return HttpResponse("no!")
 
+
 def commonfooter_m(request, messages=None):
   return commonfooter(request, messages, True)
 
+
 def commonfooter(request, messages=None, is_mobile=False):
   """
   Returns the rendered common footer
@@ -691,6 +699,7 @@ CONFIG_VALIDATOR = 'config_validator'
 #
 _CONFIG_ERROR_LIST = None
 
+
 def _get_config_errors(request, cache=True):
   """Returns a list of (confvar, err_msg) tuples."""
   global _CONFIG_ERROR_LIST
@@ -746,6 +755,7 @@ def validate_by_spec(error_list):
     if configspec:
       os.remove(configspec.name)
 
+
 def load_confs(configspecpath, conf_source=None):
   """Loads and merges all of the configurations passed in,
   returning a ConfigObj for the result.
@@ -880,6 +890,7 @@ def reset_all_debug(request):
 def _ko(str=""):
   return _(str).replace("'", "\\'")
 
+
 # This global Mako filtering option, use it with ${ yourvalue | n,antixss }
 def antixss(value):
   xss_regex = re.compile(r'<[^>]+>')
@@ -889,5 +900,5 @@ def antixss(value):
 def topo(request, location='world'):
   file_path = os.path.join('desktop', 'ext', 'topo', location + '.topo.json')
   response = StreamingHttpResponse(streaming_content=staticfiles_storage.open(file_path))
-  #//return settings.STATIC_URL + path
+  # return settings.STATIC_URL + path
   return response

+ 0 - 464
tools/ops/hue_collect_data.sh

@@ -1,464 +0,0 @@
-#!/bin/bash
-# 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.
-
-# NOTE: This script requires curl, strace and lsof to be installed. It
-# must be run on the Hue server. Set HUE_USER to a user in Hue with 
-# Superuser access to get thread dumps.  Set HUE_PASSWORD to HUE_USER's 
-# password.
-
-# Please change USER to contain the user to login
-HUE_USER="admin"
-
-# Please change PASSWORD to contain the password for the above user
-HUE_PASSWORD="admin"
-
-#parse command line arguments
-parse_arguments()
-{
-  # Test that we're using compatible getopt version.
-  getopt -T > /dev/null
-  if [[ $? -ne 4 ]]; then
-    echo "Incompatible getopt version."
-    exit 1
-  fi
-
-  # Parse short and long option parameters.
-  STRACE_WAIT=15
-  RUNS=4
-  RUN_WAIT=30
-  OUTPUT_DIR_BASE=/tmp/hue_collect_data
-  COLLECT_STRACE=true
-  COLLECT_LSOF=true
-  COLLECT_NETSTAT=true
-  COLLECT_THREADS=
-  #This is necessary to handle AD auth, doesn't seem to hurt non-ad auth
-  #if they have multiple ldap servers or for some reason the drop down
-  #at login says something other than "LDAP", then this must match the drop
-  #down
-  HUE_AUTH_SERVER="LDAP"
-  COLLECT_INSTANCE=true
-  GETOPT=`getopt -n $0 -o s,l,n,w:,r:,t,u:,p:,i,o:,d:,y:,a:,h \
-      -l strace,,lsof,netstat,wait:,runs:,threads,hueuser:,huepass:,instance,outdir:,huelog:,swait:,authserver:,help \
-      -- "$@"`
-  eval set -- "$GETOPT"
-  while true;
-  do
-    case "$1" in
-    -s|--strace)
-      COLLECT_STRACE=
-      shift
-      ;;
-    -y|--swait)
-      STRACE_WAIT=$2
-      shift 2
-      ;;
-    -l|--lsof)
-      COLLECT_LSOF=
-      shift
-      ;;
-    -n|--netstat)
-      COLLECT_NETSTAT=
-      shift
-      ;;
-    -t|--threads)
-      COLLECT_THREADS=$1
-      shift
-      ;;
-    -u|--hueuser)
-      HUE_USER=$2
-      shift 2
-      ;;
-    -p|--huepass)
-      HUE_PASSWORD=$2
-      shift 2
-      ;;
-    -a|--authserver)
-      HUE_AUTH_SERVER=$2
-      shift 2
-      ;;
-    -i|--instance)
-      COLLECT_INSTANCE=
-      shift
-      ;;
-    -w|--wait)
-      RUN_WAIT=$2
-      shift 2
-      ;;
-    -r|--runs)
-      RUNS=$2
-      shift 2
-      ;;
-    -o|--outdir)
-      OUTPUT_DIR_BASE=$2
-      shift 2
-      ;;
-    -d|--huelog)
-      HUE_LOG_DIR=$2
-      shift 2
-      ;;
-    --)
-      shift
-      break
-      ;;
-    *)
-      usage
-      exit 1
-      ;;
-    esac
-  done
-  #
-}
-
-usage()
-{
-cat << EOF
-usage: $0 [options]
-
-Collects troubleshooting data from Hue server:
-
-OPTIONS
-   -s|--strace             Setting this will disable collecting strace, default 
-                           strace will be collected
-   -y|--swait <secs>       Interval to wait before stopping strace - default 15.
-   -l|--lsof               Setting this will disable collecting lsof, default
-                           lsof will be collected
-   -n|--netstat            Setting this will disable collecting netstat, default
-                           netstat will be collected
-   -t|--threads            This will enable thread collection, default threads
-                           will NOT be collected
-   -u|--hueuser		   Hue username for collecting threads - must be admin user - default admin.
-   -p|--huepass		   Hue password for collecting threads - default admin.
-   -a|--authserver         This is the Ldap auth server name in the hue.ini if using
-                           multiple ldap servers for auth.  Must be set to the auth 
-                           server that "hueuser" belongs to.
-   -i|--instance	   Setting this will disable collecting CM Hue configs, default
-                           CM Hue configs will be collected
-   -w|--wait <secs>        Seconds to wait between runs of collecting data - default 30.
-   -r|--runs <numruns>     Number of times to collect data - default 4.
-   -o|--outdir <outdir>    Location to dump collected data - default /tmp/hue_collect_data.
-   -h|--help               Show this message.
-EOF
-}
-
-main()
-{
-
-   parse_arguments "$@"
-
-   if [[ ! ${USER} =~ .*root* ]]
-   then
-      echo "Script must be run as root: exiting"
-      exit 1
-   fi
-
-   AGENT_PROCESS_DIR="/var/run/cloudera-scm-agent/process"
-   START_DATE=$(date '+%Y%m%d-%H%M')
-   MKDIR="mkdir -p"
-
-   for PID in `ps aux | grep [r]uncherrypyserver | awk '{print $2}'`
-   do
-      if [[ ! ${PID} == ?(-)+([0-9]) ]]
-      then
-        echo "Unable to get PID from Process, either Hue is not running on this host or Hue is not using CherryPy server"
-        exit 1
-      fi
-
-      OUTPUT_DIR_DATE=${OUTPUT_DIR_BASE}/${START_DATE}
-      OUTPUT_DIR=${OUTPUT_DIR_DATE}/${PID}
-      HUE_USAGE_FILE=${OUTPUT_DIR}/cpu_mem_usage/cpu_mem_usage
-      HUE_THREADS_FILE=${OUTPUT_DIR}/threads/threads
-      HUE_STRACE_FILE=${OUTPUT_DIR}/strace/strace
-      HUE_LSOF_FILE=${OUTPUT_DIR}/lsof/lsof
-      HUE_ENVIRON_FILE=${OUTPUT_DIR}/environ/environ
-      HUE_CMDLINE_FILE=${OUTPUT_DIR}/cmdline/cmdline
-      HUE_LIMITS_FILE=${OUTPUT_DIR}/limits/limits
-      HUE_NETSTAT_FILE=${OUTPUT_DIR}/netstat/netstat
-      HUE_SUDO=${OUTPUT_DIR}/sudo
-      HUE_CONFS=${OUTPUT_DIR}/confs
-      COOKIE_JAR=${OUTPUT_DIR}/${USER}_cookie.jar
-
-      HOSTNAME=$(hostname)
-      HUE_SERVER=${HOSTNAME}
-
-      echo "Making ${OUTPUT_DIR} if it does not exist"
-      ${MKDIR} ${OUTPUT_DIR}
-
-      get_cm_process_dir ${PID}
-
-      if [[ -f ${CM_PROPS} ]]
-      then
-         HUE_LOG_DIR=`grep log_dir ${CM_PROPS} | awk '{print $3}'`
-      else
-         HUE_LOG_DIR=/var/log/hue
-      fi
-      HUE_PORT=`grep http_port ${HUE_INI} | awk -F= '{print $2}'`
-      if [[ -z ${HUE_PORT} ]]
-      then
-         HUE_PORT=8888
-      fi
-      SSL_CERT=`grep ssl_certificate ${HUE_INI} | awk -F= '{print $2}'`
-      if [[ ! -z ${SSL_CERT} ]]
-      then
-         HUE_HTTP="https"
-      else
-         HUE_HTTP="http"
-      fi
-      HUE_PASS_URL="${HUE_HTTP}://${HUE_SERVER}:${HUE_PORT}/accounts/login/"
-      HUE_THREADS_URL="${HUE_HTTP}://${HUE_SERVER}:${HUE_PORT}/desktop/debug/threads"
-   
-      if [[ ! -z ${COLLECT_THREADS} ]]
-      then
-         hue_login
-      fi
-   
-      echo "Gathering info:"
-      for (( x=1; x<=${RUNS}; x++ ))
-      do
-         DATE=$(date '+%Y%m%d-%H%M%S')
-         echo "DATE: ${DATE}"
-      
-         echo "Getting CPU and Memory usage"
-         do_ps ${PID}
-         ${MKDIR} `dirname ${HUE_USAGE_FILE}`
-         echo "PID CPU MEM MEM_MB" >> ${HUE_USAGE_FILE}_${DATE}
-         echo "${PID} ${CPU} ${MEM} ${MEM_MB}" >> ${HUE_USAGE_FILE}_${DATE}
-         echo "free -m results" >> ${HUE_USAGE_FILE}_${DATE}
-         free -m >> ${HUE_USAGE_FILE}_${DATE}
-   
-         if [[ ${COLLECT_NETSTAT} ]]
-         then
-            echo "Gathering netstat info"
-            ${MKDIR} `dirname ${HUE_NETSTAT_FILE}`
-            netstat -anp | grep ${PID} >> ${HUE_NETSTAT_FILE}_${DATE}
-         fi
-
-         if [[ ${COLLECT_STRACE} ]]
-         then
-            echo "Getting strace"
-            ${MKDIR} `dirname ${HUE_STRACE_FILE}`
-            do_strace \
-                 ${PID} \
-                 ${STRACE_WAIT} \
-                 -o ${HUE_STRACE_FILE}_${DATE} -T -t
-         fi
-
-         if [[ ${COLLECT_LSOF} ]]
-         then
-            echo "Getting open connections"
-            ${MKDIR} `dirname ${HUE_LSOF_FILE}`
-            do_lsof \
-                 ${PID} \
-                 ${HUE_LSOF_FILE}_${DATE}
-         fi
-
-         if [[ ! -z ${COLLECT_THREADS} ]]
-         then
-            echo "Getting a thread dump:"
-            ${MKDIR} `dirname ${HUE_THREADS_FILE}`
-            do_curl \
-                 GET \
-                 "${HUE_THREADS_URL}" \
-                 -L -o ${HUE_THREADS_FILE}_${DATE}
-         fi
-
-         sleep ${RUN_WAIT}
-      done
-   
-      if [[ ! -z ${COLLECT_INSTANCE} ]]
-      then
-         echo "Gathering CM config instances"
-         do_instances ${HUE_PORT}
-      fi
-
-      echo "Gathering process info"
-      ${MKDIR} `dirname ${HUE_ENVIRON_FILE}`
-      strings /proc/${PID}/environ >> ${HUE_ENVIRON_FILE}_${DATE}
-      ${MKDIR} `dirname ${HUE_CMDLINE_FILE}`
-      strings /proc/${PID}/cmdline >> ${HUE_CMDLINE_FILE}_${DATE}
-      ${MKDIR} `dirname ${HUE_LIMITS_FILE}`
-      strings /proc/${PID}/limits >> ${HUE_LIMITS_FILE}_${DATE}
-
-      ${MKDIR} ${OUTPUT_DIR}/logs
-      cp -pr ${HUE_LOG_DIR}/* ${OUTPUT_DIR}/logs 
-
-   done
-
-   echo "Gathering environment info"
-   do_sudo \
-        ${HUE_SUDO} \
-        ${DATE}
-
-  if [[ ! -z ${STRACE_PID} ]]
-   then
-      echo "strace still running, waiting for it to complete: ${STRACE_PID}"
-      wait ${STRACE_PID}
-   fi
-
-   echo "Collecting done, please zip ${OUTPUT_DIR_DATE} and upload to the ticket"
-}
-
-function do_curl() {
-
-   METHOD=$1
-   shift
-   URL=$1
-   shift
-   ARGS=$@
-
-   CURL=$(which curl)
-   if [ -z ${COOKIE_JAR} ]
-   then
-      COOKIE_JAR=/tmp/cookie.jar
-   fi
-   if [ -f ${COOKIE_JAR} ]
-   then
-      CSRF_TOKEN=`grep ${HOSTNAME} ${COOKIE_JAR} | grep csrftoken | cut -f 7`
-   fi
-   if [ ! -f ${CURL} ]
-   then
-      echo "curl not found, unable to run any curl commands"
-   else
-      ${CURL} \
-         ${CURL_OPTS} \
-         -k \
-         -e "${HUE_HTTP}://${HUE_SERVER}:${HUE_PORT}/" \
-         -b @${COOKIE_JAR} \
-         -c ${COOKIE_JAR} \
-         -H "X-CSRFToken: ${CSRF_TOKEN}" \
-         -X ${METHOD} \
-         -s \
-         -f \
-         ${URL} \
-         ${ARGS}
-   fi
-
-}
-
-function hue_login() {
-   echo "Login to Hue to get Cookie:"
-   do_curl \
-	GET \
-	"${HUE_PASS_URL}" \
-	-L 2>&1 > /dev/null
-
-   do_curl \
-        POST \
-        "${HUE_PASS_URL}" \
-        -F username=${HUE_USER} -F password="${HUE_PASSWORD}" -F server="${HUE_AUTH_SERVER}" 2>&1 > /dev/null
-}
-
-function do_strace()
-{
-   SPID=$1
-   shift
-   WAIT=$1
-   shift
-   ARGS=$@
-
-   STRACE=$(which strace)
-   if [ ! -f ${STRACE} ]
-   then
-      echo "strace not found, unable to collect strace info"
-   else
-      if [[ ! -z ${STRACE_PID} ]]
-      then
-         echo "strace still running, waiting for it to complete: ${STRACE_PID}"
-         wait ${STRACE_PID}
-      fi
-      timeout ${WAIT}s ${STRACE} -f -v -p ${SPID} ${ARGS} &
-      STRACE_PID=$!
-   fi
-}
-
-function do_lsof()
-{
-   LPID=$1
-   shift
-   LOG_FILE=$1
-   shift
-   ARGS=$@
-
-   if [ -z ${LOG_FILE} ]
-   then
-      LOG_FILE=/tmp/lsof.log
-   fi
-
-   LSOF=$(which lsof)
-   if [ ! -f ${LSOF} ]
-   then
-      echo "lsof not found, unable to determine number of connections"
-   else
-      ${LSOF} -P -p ${LPID} ${ARGS} > ${LOG_FILE}
-   fi
-}
-
-function do_ps()
-{
-   PID=$1
-   shift
-   PS_COMMAND=$(ps aux | grep ${PID} | grep [r]uncherrypyserver | tail -1 | awk '{print $6" "$2" "$3" "$12}')
-   MEM=$(echo ${PS_COMMAND} | awk '{print $1}')
-   CPU=$(echo ${PS_COMMAND} | awk '{print $3}')
-   PROC=$(echo ${PS_COMMAND} | awk '{print $4}')
-   MEM_MB=$(expr ${MEM} / 1024)
-}
-
-function do_sudo()
-{
-   HUE_SUDO=$1
-   shift
-   DATE=$1
-   shift
-   ARGS=$@
-   sudo -u hue /bin/bash -c "/usr/bin/env" >> ${HUE_SUDO}_env_${DATE}
-   sudo -u hue /bin/bash -c "/usr/bin/env which python2.6" >> ${HUE_SUDO}_python_${DATE}
-}
-
-function get_cm_process_dir()
-{
-   PID=$1
-   shift
-   if [[ -d ${AGENT_PROCESS_DIR} ]]
-   then
-      HUE_CONF_DIR=`strings /proc/${PID}/environ | grep HUE_CONF_DIR | awk -F\= '{print $2}'`
-   else
-      HUE_CONF_DIR=/etc/hue/conf
-   fi
-   HUE_INI=${HUE_CONF_DIR}/hue.ini
-   CM_PROPS=${HUE_CONF_DIR}/cloudera-monitor.properties
-}
-
-function do_instances()
-{
-   HUE_PORT=$1
-   ${MKDIR} ${HUE_CONFS}
-   if [[ -d ${AGENT_PROCESS_DIR} ]]
-   then
-      for x in `find ${AGENT_PROCESS_DIR}/*hue-HUE_SERVER -name "hue.ini" -exec grep -H ${HUE_PORT} {} \; | awk -F\/ '{print $6}' | sort -n | tail -3`
-      do
-         cp -pr ${AGENT_PROCESS_DIR}/$x ${HUE_CONFS}
-      done
-   else
-      cp -pr /etc/hue/conf ${HUE_CONFS}/0-hue-HUE_SERVER
-   fi
-   for x in `find ${HUE_CONFS} -name "*" -type f`
-   do
-      sed -i "/password/Id" $x
-   done
-}
-
-main "$@"