diff options
-rw-r--r-- | sos/plugins/__init__.py | 136 | ||||
-rw-r--r-- | sos/plugins/as7.py | 253 | ||||
-rw-r--r-- | sos/plugins/jboss.py | 713 |
3 files changed, 0 insertions, 1102 deletions
diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py index b0e3ab3f..24ae7094 100644 --- a/sos/plugins/__init__.py +++ b/sos/plugins/__init__.py @@ -714,142 +714,6 @@ class IndependentPlugin(object): """Tagging class that indicates this plugin can run on any platform""" pass -class AS7Mixin(object): - """A mixin class that adds some helpful methods for AS7 related plugins""" - - class Request(object): - - def __init__(self, resource, operation="read-resource", parameters=None): - self.resource = resource - self.operation = operation - if parameters: - self.parameters = parameters - else: - self.parameters = {} - - def url_parts(self): - """Generator function to split a url into (key, value) tuples. The - url should contain an even number of pairs. In the case of / the - generator will immediately stop iteration. - """ - parts = self.resource.strip("/").split("/") - - if parts == ['']: - raise StopIteration - - while parts: - yield (parts.pop(0), parts.pop(0)) - - def get_jboss_home(self): - return self._get_opt('home', 'as7_home') or os.getenv("JBOSS_HOME", None) - - def query(self, request_obj): - try: - return self.query_java(request_obj) - except Exception, e: - self.add_alert("JBOSS API call failed, falling back to HTTP: %s" % e) - return self.query_http(request_obj) - - def _get_opt(self, first, second, default=None): - val = self.get_option(first) - if val: - return val - val = self.get_option(second) - if val: - return val - return default - - def query_java(self, request_obj): - from org.jboss.dmr import ModelNode - controller_client = self.get_option('controller_client_proxy') - if not controller_client: - raise AttributeError("Controller Client is not available") - - request = ModelNode() - request.get("operation").set(request_obj.operation) - - for key, val in request_obj.url_parts(): - request.get('address').add(key,val) - - if request_obj.parameters: - for key, value in request_obj.parameters.iteritems(): - request.get(key).set(value) - - return controller_client.execute(request).toJSONString(True) - - def query_http(self, request_obj, postdata=None): - host = self._get_opt('host', 'as7_host') - port = self._get_opt('port', 'as7_port') - - username = self._get_opt('user', 'as7_user') - password = self._get_opt('pass', 'as7_pass') - - uri = "http://%s:%s/management" % (host,port) - - json_data = {'operation': request_obj.operation, - 'address': []} - - for key, val in request_obj.url_parts(): - json_data['address'].append({key:val}) - - for key, val in request_obj.parameters.iteritems(): - json_data[key] = val - - postdata = json.dumps(json_data) - headers = {'Content-Type': 'application/json', - 'Accept': 'application/json'} - - opener = urllib2.build_opener() - - if username and password: - passwd_manager = urllib2.HTTPPasswordMgrWithDefaultRealm() - passwd_manager.add_password(realm="ManagementRealm", - uri=uri, - user=username, - passwd=password) - digest_auth_handler = urllib2.HTTPDigestAuthHandler(passwd_manager) - basic_auth_handler = urllib2.HTTPBasicAuthHandler(passwd_manager) - - opener.add_handler(digest_auth_handler) - opener.add_handler(basic_auth_handler) - - req = urllib2.Request(uri, data=postdata, headers=headers) - - try: - resp = opener.open(req) - return resp.read() - except Exception, e: - err_msg = "Could not query url: %s; error: %s" % (uri, e) - self.add_alert(err_msg) - return err_msg - - def set_domain_info(self, parameters=None): - """This function will add host controller and server instance name data - if it is present to the desired resource. This is to support - domain-mode operation in AS7. - """ - host_controller_name = self.get_option("as7_host_controller_name") - server_name = self.get_option("as7_server_name") - - if host_controller_name and server_name: - if not parameters: - parameters = {} - - parameters['host'] = host_controller_name - parameters['server'] = server_name - - return parameters - - - def resource_to_file(self, resource=None, parameters=None, operation='read-resource', outfile=None): - parameters = self.set_domain_info(parameters) - - r = self.Request(resource=resource, - parameters=parameters, - operation=operation) - self.add_string_as_file(self.query(r), filename=outfile) - - def import_plugin(name, superclasses=None): """Import name as a module and return a list of all classes defined in that module. superclasses should be a tuple of valid superclasses to import, diff --git a/sos/plugins/as7.py b/sos/plugins/as7.py deleted file mode 100644 index 52f71203..00000000 --- a/sos/plugins/as7.py +++ /dev/null @@ -1,253 +0,0 @@ -import os -import sys -import re -import zipfile -import urllib2 -import tempfile -from xml.etree import ElementTree -from itertools import chain - -from sos.plugins import Plugin, IndependentPlugin, AS7Mixin -from sos.utilities import DirTree, find, checksum - -class AS7(Plugin, IndependentPlugin, AS7Mixin): - """JBoss related information - """ - - requires_root = False - - version = "1.0" - - option_list = [ - ("home", "JBoss's installation dir (i.e. JBOSS_HOME)", '', False), - ("logsize", 'max size (MiB) to collect per log file', '', 15), - ("stdjar", 'Collect jar statistics for standard jars.', '', True), - ("host", 'hostname of the management api for jboss', '', 'localhost'), - ("port", 'port of the management api for jboss', '', '9990'), - ("user", 'username for management console', '', None), - ("pass", 'password for management console', '', None), - ] - - __MD5_CHUNK_SIZE=128 - __jbossHome=None - __haveJava=False - __twiddleCmd=None - __jbossServerConfigDirs = ["standalone", "domain"] - __jbossHTMLBody=None - - def __alert(self, msg): - self.soslog.error(msg) - self.add_alert(msg) - - def __getJbossHome(self): - - self.__jbossHome = self.get_jboss_home() - if not self.__jbossHome: - self.add_alert("ERROR: The JBoss installation directory was not supplied.\ - The JBoss SOS plug-in cannot continue.") - return False - - self.add_alert("INFO: The JBoss installation directory supplied to SOS is " + - self.__jbossHome) - return True - - - def __getMd5(self, file): - """Returns the MD5 sum of the specified file.""" - - retVal = "?" * 32 - - try: - retVal = checksum(file, self.__MD5_CHUNK_SIZE) - except IOError, ioe: - self.__alert("ERROR: Unable to open %s for reading. Error: %s" % (file,ioe)) - - return retVal - - def __getManifest(self, jarFile): - """ - Given a jar file, this function will extract the Manifest and return it's contents - as a string. - """ - manifest = None - try: - zf = zipfile.ZipFile(jarFile) - try: - manifest = zf.read("META-INF/MANIFEST.MF") - except Exception, e: - self.__alert("ERROR: reading manifest from %s. Error: %s" % (jarFile, e)) - zf.close() - except Exception, e: - self.__alert("ERROR: reading contents of %s. Error: %s" % (jarFile, e)) - return manifest - - def __getStdJarInfo(self): - jar_info_list = [] - - for jarFile in find("*.jar", self.__jbossHome): - checksum = self.__getMd5(jarFile) - manifest = self.__getManifest(jarFile) - path = jarFile.replace(self.__jbossHome, 'JBOSSHOME') - if manifest: - manifest = manifest.strip() - jar_info_list.append((path, checksum, manifest)) - - if jar_info_list: - jar_info_list.sort() - self.add_string_as_file("\n".join([ - "%s\n%s\n%s\n===\n" % (name, checksum, manifest) - for (name, checksum, manifest) in jar_info_list]), - 'jarinfo.txt') - else: - self.add_alert("WARN: No jars found in JBoss system path (" + self.__jbossHome + ").") - - def get_online_data(self): - """ - This function co-locates calls to the management api that gather - information from a running system. - """ - self.resource_to_file(resource="/", - parameters={"recursive": "true"}, - outfile="configuration.json") - self.resource_to_file(resource="/core-service/service-container", - operation="dump-services", - outfile="dump-services.json") - self.resource_to_file(resource="/subsystem/modcluster", - operation="read-proxies-configuration", - outfile="cluster-proxies-configuration.json") - self.resource_to_file(resource="/core-service/platform-mbean/type/threading", - operation="dump-all-threads", - parameters={"locked-synchronizers": "true", - "locked-monitors": "true"}, - outfile="threaddump.json") - - def __getFiles(self, configDirAry): - """ - This function will collect files from JBOSS_HOME for analysis. The scope of files to - be collected are determined by options to this SOS plug-in. - """ - for dir_ in configDirAry: - path = os.path.join(self.__jbossHome, dir_) - ## First add forbidden files - self.add_forbidden_path(os.path.join(path, "tmp")) - self.add_forbidden_path(os.path.join(path, "work")) - self.add_forbidden_path(os.path.join(path, "data")) - - if os.path.exists(path): - ## First get everything in the conf dir - confDir = os.path.join(path, "configuration") - self.add_forbidden_path(os.path.join(confDir, 'mgmt-users.properties')) - self.add_forbidden_path(os.path.join(confDir, 'application-users.properties')) - - for logFile in find("*.log", path): - self.add_copy_spec_limit(logFile, - self.get_option("logsize"), - sub=(self.__jbossHome, 'JBOSSHOME')) - - for xml in find("*.xml", path): - self.add_copy_spec(xml, sub=(self.__jbossHome, 'JBOSSHOME')) - - for prop in find("*.properties", path): - self.add_copy_spec(prop, sub=(self.__jbossHome, 'JBOSSHOME')) - - deployment_info = self.__get_deployment_info(confDir) - deployments = self.__get_deployments(path) - for deployment in deployments: - self.__get_listing_from_deployment(deployment, deployment_info) - - for xml in find("*.xml", os.path.join(self.__jbossHome, 'modules')): - self.add_copy_spec(xml, sub=(self.__jbossHome, 'JBOSSHOME')) - - def __get_deployment_info(self, dir_): - """Gets the deployment name to sha1 mapping for all deployments defined - in configs under dir_""" - deployment_info = {} - for config in find("*.xml", dir_): - root = ElementTree.parse(config).getroot() - # the namespace is harder to fetch than it should be - ns = root.tag.rpartition("}")[0] - ns += "}" - for deployment in root.findall("./%sdeployments/%sdeployment" % (ns, ns)): - name = deployment.attrib.get("name") - sha1 = deployment.getchildren()[0].attrib.get("sha1") - deployment_info[sha1] = name - return deployment_info - - def __get_deployments(self, path): - return list(chain( - find("*", os.path.join(path, "deployments")), - find("content", path))) - - def __get_listing_from_deployment(self, path, mapping): - try: - zf = zipfile.ZipFile(path) - contents = [] - for zipinfo in zf.infolist(): - if zipinfo.filename.endswith("/"): - continue - contents.append((zipinfo.filename, zipinfo.file_size)) - zf.close() - contents.sort() - output = "\n".join(["%s:%d" % (fn, fs) for fn, fs in contents]) - - path_to = path.replace(self.__jbossHome, '') - if 'content' in path: - path_to = path_to.strip(os.path.sep).rstrip("content") - path_to = os.path.join(*path_to.split(os.path.sep)[:-2]) - sha1 = "".join(path.split(os.path.sep)[-3:-1]) - name = mapping.get(sha1, sha1) - else: - path_to, name = os.path.split(path_to) - - self.add_string_as_file(output, os.path.join(path_to, "%s.txt" % name)) - except: - # this is probably not a zipfile so we don't care - pass - - def check_enabled(self): - return self.__getJbossHome() - - def setup(self): - - if not self.__getJbossHome(): - self.exit_please() - - try: - self.get_online_data() - except urllib2.URLError: - pass - - if self.get_option("stdjar"): - self.__getStdJarInfo() - - tree = DirTree(self.__jbossHome).as_string() - self.add_string_as_file(tree, "jboss_home_tree.txt") - - self.__getFiles(self.__jbossServerConfigDirs) - - def postproc(self): - """ - Obfuscate passwords. - """ - - password_xml_regex = re.compile(r'<password>.*</password>', re.IGNORECASE) - - for dir_ in self.__jbossServerConfigDirs: - path = os.path.join(self.__jbossHome, dir_) - - self.do_file_sub(os.path.join(path,"configuration","*.xml"), - password_xml_regex, - r'<password>********</password>') - - tmp = os.path.join(path,"configuration") - for propFile in find("*-users.properties", tmp): - self.do_file_sub(propFile, - r"=(.*)", - r'=********') - -# Remove PW from -ds.xml files - tmp = os.path.join(path, "deployments") - for dsFile in find("*-ds.xml", tmp): - self.do_file_sub(dsFile, - password_xml_regex, - r"<password>********</password>") diff --git a/sos/plugins/jboss.py b/sos/plugins/jboss.py deleted file mode 100644 index f36ba1d0..00000000 --- a/sos/plugins/jboss.py +++ /dev/null @@ -1,713 +0,0 @@ -import os -import zipfile -import platform -import fnmatch -import shlex -import subprocess -import string -import grp, pwd - -from sos.plugins import Plugin, RedHatPlugin -from sos.utilities import DirTree, find - -class jboss(Plugin, RedHatPlugin): - """JBoss related information - """ - - option_list = [("home", 'JBoss\'s installation dir (i.e. JBOSS_HOME)', '', False), - ("javahome", 'Java\'s installation dir (i.e. JAVA_HOME)', '', False), - ("profile", 'Quoted and space separated list of server profiles to limit collection. \ -Default=\'all default minimal production standard web\'.', '', False), - ("user", 'JBoss JMX invoker user to be used with twiddle.', '', False), - ("pass", 'JBoss JMX invoker user\'s password to be used with twiddle.', '', False), - ("logsize", 'max size (MiB) to collect per log file', '', 15), - ("stdjar", 'Collect jar statistics for standard jars.', '', True), - ("servjar", 'Collect jar statistics from any server configuration dirs.', '', True), - ("twiddle", 'Collect twiddle data.', '', True), - ("appxml", 'Quoted and space separated list of application\'s whose XML descriptors you want. The keyword \"all\" will collect all descriptors in the designated profile(s).', '', False)] - - __MD5_CHUNK_SIZE=128 - __jbossHome=None - __haveJava=False - __twiddleCmd=None - __jbossSystemJarDirs = [ "client", "lib" , "common/lib" ] - __jbossServerConfigDirs = ["all", "default", "minimal", "production", "standard", "web"] - __jbossHTMLBody=None - - def __getJbossHome(self): - """ - Will attempt to locate the JBoss installation dir in either jboss.home or - scrape it from the environment variable JBOSS_HOME. - Returns: - True JBOSS_HOME is set and the path exists. False otherwise. - """ - if self.get_option("home"): - ## Prefer this value first over the ENV - self.__jbossHome=self.get_option("home") - self.add_alert("INFO: The JBoss installation directory supplied to SOS is " + - self.__jbossHome) - elif os.environ.get("JBOSS_HOME"): - self.__jbossHome=os.environ.get("JBOSS_HOME") - self.add_alert("INFO: The JBoss installation directory (i.e. JBOSS_HOME) from the environment is " + - self.__jbossHome) - else: - self.add_alert("ERROR: The JBoss installation directory was not supplied.\ - The JBoss SOS plug-in cannot continue.") - return False - - if os.path.exists(self.__jbossHome): - ## We need to set JBOSS_CLASSPATH otherwise some twiddle commands will not work. - jbossClasspath=None - tmp=os.path.join(self.__jbossHome, "lib") - if os.path.exists(tmp): - jbossClasspath=tmp + os.sep + "*" + os.pathsep - else: - self.add_alert("WARN: The JBoss lib directory does not exist. Dir(%s) " % tmp) - - tmp=os.path.join(self.__jbossHome, "common" , "lib") - if os.path.exists(tmp): - jbossClasspath+=tmp + os.sep + "*" - else: - self.add_alert("WARN: The JBoss lib directory does not exist. Dir(%s) " % tmp) - - os.environ['JBOSS_CLASSPATH']=jbossClasspath - - return True - else: - msg = "ERROR: The path to the JBoss installation directory does not exist. Path is: " + self.__jbossHome - print msg - self.add_alert(msg) - return False - - def __getJavaHome(self): - """ - This SOS plug-in makes extensive use of JBoss' twiddle program and twiddle uses Java. As such, we - need to ensure that java and JAVA_HOME is known to the plug-in so that it can use Java. - This function will put JAVA_HOME and JAVA_HOME/bin into the environment if they're not already - there. - """ - javaHome=None - java="bin/java" - - if self.get_option("javahome"): - ## Prefer this value first over the ENV - javaHome=self.get_option("javahome") - self.add_alert("INFO: The Java installation directory supplied to SOS is " + - javaHome) - elif os.environ.get("JAVA_HOME"): - javaHome=os.environ.get("JAVA_HOME") - self.add_alert("INFO: The Java installation directory (i.e. JAVA_HOME) from the environment is " + - javaHome) - else: - ## Test to see if Java is already in the PATH - (status, output, rtime) = self.call_ext_prog("java -version") - if (status == 0): - self.add_alert("INFO: The Java installation directory is in the system path.") - return True - else: - self.add_alert("ERROR: The Java installation directory was not supplied.\ - The JBoss SOS plug-in will not collect twiddle data.") - return False - - - java=os.path.join(javaHome, java) - if os.path.exists(java) and os.access(java, os.X_OK): - os.environ['JAVA_HOME']=javaHome - ## Place the supplied Java at the *head* of the path. - os.environ['PATH'] = os.path.join(javaHome, "bin") + os.pathsep + os.environ['PATH'] - return True - else: - msg = "ERROR: The path to the Java installation directory does not exist. Path is: %s" % (javaHome) - print msg - self.add_alert(msg) - return False - - - def __getJMXCredentials(self): - """ - Read the JMX credentials from the option list. - Returns: - A formatted credential string for twiddle consumption if both user and pass - are supplied. None otherwise. - """ - credential = None - ## Let's make a best effort not to pass expansions or escapes to the shell - ## by strong quoting the user's input - if self.get_option("user"): - credential=" -u '" + self.get_option("user") + "' " - if self.get_option("pass"): - credential+=" -p '" + self.get_option("pass") + "' " - else: - credential=None - return credential - - def __updateServerConfigDirs(self): - """ - By default this plug-in will attempt to collect logs from every - JBoss server configuration directory (i.e. profile). The - user may have supplied a limited list, as such, we must respect - that wish. - Returns: - Nothing. Will update __jbossServerConfigDirs if the user - supplied a limited list. - """ - if self.get_option("profile"): - profiles=self.get_option("profile") - ## I'd rather use comma as the delimiter but get_option doesn't seem to be passing it through. - ## Since we are using spaces as the delimiter, we need to filter out empty list elements - ## if the user did something like ' all default web '. - profiles=profiles.split(' ') - ## Flter(None doesn't work. Allows 0. - self.__jbossServerConfigDirs=filter(lambda x: len(x), profiles) - return - - def __buildTwiddleCmd(self): - """ - Utility function to build the twiddle command with/without credentials - so that it can be used by later fcns. If twiddle is found - """ - ## In the off-chance that SOS is ever ported to cygwin or this plugin - ## is ported to win... - if platform.system() == "Windows": - self.__twiddleCmd=os.path.join(self.__jbossHome, "bin", "twiddle.bat") - else: - self.__twiddleCmd=os.path.join(self.__jbossHome, "bin", "twiddle.sh") - - if os.path.exists(self.__twiddleCmd) and os.access(self.__twiddleCmd, os.X_OK): - credential = self.__getJMXCredentials() - if credential: - self.__twiddleCmd += credential - else: - ## Reset twiddlecmd to None - self.add_alert("ERROR: The twiddle program could not be found. Program=%s" % (self.__twiddleCmd)) - self.__twiddleCmd = None - - return - - def __createHTMLBodyStart(self): - """ - The free-form HTML that can be inserted into the SOS report with add_custom_text is within - a <p> block. We need to add a few pieces of HTML so that all of our subsequent data will - be rendered properly. - """ - self.__jbossHTMLBody = """ - <br/> - <br/> - <script type="text/javascript"> - <!-- - function show(h) { - var tbl = document.getElementById(h); - tbl.style.display = 'block'; - } - function hide(h) { - var tbl = document.getElementById(h); - tbl.style.display = 'none'; - } - // --> - </script> - <b>JBoss SOS Report Table of Contents</b> - <ul style="list-style-type: square"> - <li><a href="#system-jar-info">JBoss System Jar Information</a> - </li> - <li><a href="#profile-jar-info">JBoss Server Configurations Jar Information</a> - </li> - <li><a href="#jboss-home-directory-tree">JBOSS_HOME Directory Tree</a> - </li> - <li><a href="#jboss-system-mbean-data">JBoss JMX MBean Data from <tt>jboss.system:*</tt></a> - </li> - <li><a href="#jboss-mbean-data">JBoss JMX MBean Data from <tt>jboss:*</tt></a> - </li> - <li><a href="#jboss-mbean-summary">JBoss MBean Summary</a> - </li> - <li><a href="#jboss-messaging">JBoss JMX Messaging MBean Data from <tt>jboss.messaging:*</tt></a> - </li> - <li><a href="#jboss-j2ee">JBoss JMX J2EE MBean Data from <tt>jboss.j2ee:*</tt></a> - </li> - <li><a href="#jboss-vfs">JBoss JMX VFS MBean Data from <tt>jboss.vfs:*</tt></a> - </li> - <li><a href="#jboss-jsr77-data">JBoss JSR77 Data</a> - </li> - </ul> - <br/> - <br/> - """ - - def __getMd5(self, file): - """ - Will perform an MD5 sum on a given file and return the file's message digest. This function - will not read the entire file into memory, instead, it will consume the file in 128 byte - chunks. This might be slightly slower but, the intent of a SOS report is to collect data from - a system that could be under stress and we shouldn't stress it more by loading entire Jars into - real memory. - - Note: This fcn expects hashlib; however, this isn't always available. If it isn't then - we will use md5sum - """ - - retVal="????????????????????????????????" - - try: - import hashlib - try: - fd = open(file,"rb") - except IOError, ioe: - msg = "ERROR: Unable to open %s for reading. Error: " % (file,ioe) - print msg - self.add_alert(msg) - - md5 = hashlib.md5() - data = fd.read(self.__MD5_CHUNK_SIZE) - while data: - md5.update(data) - data = fd.read(self.__MD5_CHUNK_SIZE) - retVal = md5.hexdigest() - except ImportError, e: - process = subprocess.Popen(['md5sum', file], - shell=False, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - result = process.communicate() - if (process.returncode == 0): - retVal = result[0].partition(' ')[0] - else: - msg = "ERROR: Unable to compute md5sum of %s. Msg (%s)" % (file, result[1]) - print msg - self.add_alert(msg) - - return retVal - - - def __getManifest(self, jarFile): - """ - Given a jar file, this function will extract the Manifest and return it's contents - as a string. - """ - manifest=None - try: - zf = zipfile.ZipFile(jarFile) - try: - manifest=zf.read("META-INF/MANIFEST.MF") - except Exception, e: - msg="ERROR: reading manifest from %s. Error: %s" % (jarFile, e) - print msg - self.add_alert(msg) - zf.close() - except Exception, e: - msg="ERROR: reading contents of %s. Error: %s" % (jarFile, e) - print msg - self.add_alert(msg) - return manifest - - def __getStdJarInfo(self): - - self.__jbossHTMLBody += """ - <div id="system-jar-info" style="font-weight: bold;">– JBoss System Jar Information</div> - """ - - for dir in self.__jbossSystemJarDirs: - path=os.path.join(self.__jbossHome, dir) - if os.path.exists(path): - nicePath=path.replace(os.sep, "-") - self.__jbossHTMLBody += """ - <div> - — Summary of Jar Files in JBoss System Directory - <tt>%s</tt> - ( <a href="javascript:show('%s')">Show</a> / <a - href="javascript:hide('%s')">Hide</a> ): - </div> - <div id="%s" style="overflow: hidden; display: none"> - <ul style="list-style-type: square"> - """ % (path,nicePath,nicePath,nicePath) - - found= False - for jarFile in find("*.jar", path): - found= True - nicePath=jarFile.replace(os.sep, "-") - self.__jbossHTMLBody += """ - <li>Jar File: <tt>%s</tt><br/> - MD5: <tt>%s</tt> - <br /> Manifest File ( - <a href="javascript:show('%s')">Show</a> / - <a href="javascript:hide('%s')">Hide</a> ):<br /> - <div id="%s" style="overflow: hidden; display: none"> - <pre> - %s - </pre> - </div> - </li> - """ % (jarFile, - self.__getMd5(jarFile), - nicePath, - nicePath, - nicePath, - self.__getManifest(jarFile)) - - if not found: - self.add_alert("WARN: No jars found in JBoss system path (" + path + ").") - self.__jbossHTMLBody += """ - </ul> - </div> - """ - else: - self.add_alert("ERROR: JBoss system path (" + path + ") does not exist.") - return - - def __getServerConfigJarInfo(self, configDirAry): - - self.__jbossHTMLBody += """ - <br/> - <br/> - <div id="profile-jar-info" style="font-weight: bold;">– JBoss Server Configurations Jar Information</div> - """ - for dir in configDirAry: - serverDir = os.path.join("server", dir) - path=os.path.join(self.__jbossHome, serverDir) - if os.path.exists(path): - nicePath=path.replace(os.sep, "-") - self.__jbossHTMLBody += """ - <div> - — Summary of Jar Files in the <tt>%s</tt> JBoss Server Configuration - ( <a href="javascript:show('%s')">Show</a> / <a - href="javascript:hide('%s')">Hide</a> ): - </div> - <div id="%s" style="overflow: hidden; display: none"> - <ul style="list-style-type: square"> - """ % (dir, nicePath,nicePath,nicePath) - - found = False - for jarFile in find("*.jar", path): - found = True - nicePath=jarFile.replace(os.sep, "-") - self.__jbossHTMLBody += """ - <li id="system-jar-info">Jar File: <tt>%s</tt><br/> - MD5: <tt>%s</tt> - <br /> Manifest File ( - <a href="javascript:show('%s')">Show</a> / - <a href="javascript:hide('%s')">Hide</a> ):<br /> - <div id="%s" style="overflow: hidden; display: none"> - <pre> - %s - </pre> - </div> - </li> - """ % (jarFile, - self.__getMd5(jarFile), - nicePath, - nicePath, - nicePath, - self.__getManifest(jarFile)) - - if not found: - self.add_alert("WARN: No jars found in the JBoss server configuration (%s)." % (path)) - - self.__jbossHTMLBody += """ - </ul> -</div> - """ - else: - self.add_alert("ERROR: JBoss server configuration path (" + path + ") does not exist.") - - return - - def __getJBossHomeTree(self): - """ - This function will execute the "tree" command on JBOSS_HOME. - """ - self.__jbossHTMLBody += """ - <br/> - <br/> - <div id="jboss-home-directory-tree" style="font-weight: bold;">– JBOSS_HOME Directory Tree</div> - - <div> - — JBOSS_HOME Tree - ( <a href="javascript:show('jboss-home-tree')">Show</a> / <a - href="javascript:hide('jboss-home-tree')">Hide</a> ): - </div> - <div id="jboss-home-tree" style="overflow: hidden; display: none"> - <pre> - """ - try: - output = DirTree(self.__jbossHome).as_string() - self.__jbossHTMLBody += """ -%s - </pre> - </div> - """ % (output) - except Exception, e: - self.__jbossHTMLBody += """ - ERROR: Unable to generate <tt>tree</tt> on JBOSS_HOME. - Exception: %s - </pre> - </div> - """ % e - return - - def __getMbeanData(self, dataTitle, divId, twiddleOpts): - credentials = "" - if self.__haveJava and self.__twiddleCmd: - self.__jbossHTMLBody += """ - <div> - — %s - ( <a href="javascript:show('%s')">Show</a> / <a - href="javascript:hide('%s')">Hide</a> ): - </div> - <div id="%s" style="overflow: hidden; display: none"> - <table style="margin-left: 30px;font-size:14px"> - <tr> - <td align="left"> - Twiddle Options: - </td> - <td align="left"><tt>%s</tt></td> - </tr> - </table> - <pre> - - """ % (dataTitle, divId, divId, divId,twiddleOpts) - cmd = "%s %s" % (self.__twiddleCmd, twiddleOpts) - - proc = subprocess.Popen(shlex.split(cmd), stderr=subprocess.STDOUT, stdout=subprocess.PIPE) - output = proc.communicate()[0] - status = proc.returncode - if status == 0 and output: - self.__jbossHTMLBody += output.strip() - else: - self.__jbossHTMLBody += """ - ERROR: Unable to collect %s data. - Output: %s - Status: %d - """ % (twiddleOpts, output, status) - else: - self.__jbossHTMLBody += "ERROR: Unable to collect data twiddle or Java is missing." - - self.__jbossHTMLBody += """ - </pre> - </div> - """ - return - - def __getTwiddleData(self): - """ - This function co-locates all of the calls to twiddle so that they can be easily disabled. - """ - - ## Get jboss.system.* Data - self.__jbossHTMLBody += """ - <br/> - <br/> - <div id="jboss-system-mbean-data" style="font-weight: bold;">– JBoss JMX MBean Data from <tt>jboss.system:*</tt></div> - """ - self.__getMbeanData("JBoss Server Info", - "jboss-server-info", - " get 'jboss.system:type=ServerInfo' ") - self.__getMbeanData("JBoss Server Config Info", - "jboss-server-config-info", - " get 'jboss.system:type=ServerConfig' ") - self.__getMbeanData("JBoss CXF Server Config Info", - "jboss-cxfserver-config-info", - " get 'jboss.ws:service=ServerConfig' ") - self.__getMbeanData("JBoss Memory Pool Info", - "jboss-memory-pool-info", - " invoke 'jboss.system:type=ServerInfo' listMemoryPools true ") - self.__getMbeanData("JBoss Thread CPU Utilization", - "jboss-thread-cpu-info", - " invoke 'jboss.system:type=ServerInfo' listThreadCpuUtilization ") - self.__getMbeanData("JBoss Thread Dump", - "jboss-thread-dump", - " invoke 'jboss.system:type=ServerInfo' listThreadDump ") - self.__getMbeanData("JBoss Logging Config Info", - "jboss-logging-config-info", - " get 'jboss.system:service=Logging,type=Log4jService' ") - - ## Get jboss.* Data - self.__jbossHTMLBody += """ - <br/> - <br/> - <div id="jboss-mbean-data" style="font-weight: bold;">– JBoss JMX MBean Data from <tt>jboss:*</tt></div> - """ - self.__getMbeanData("JBoss System Properties", - "jboss-system-properties-info", - " invoke 'jboss:name=SystemProperties,type=Service' showAll ") - - self.__getMbeanData("JBoss JNDI List View", - "jboss-jndi-list-info", - " invoke 'jboss:service=JNDIView' list true ") - - ## MBean Summary - self.__jbossHTMLBody += """ - <br/> - <br/> - <div id="jboss-mbean-summary" style="font-weight: bold;">– JBoss MBean Summary</div> - """ - self.__getMbeanData("JBoss MBean Vendor/Version Info", - "jboss-vendor-version", - " get 'JMImplementation:type=MBeanServerDelegate' ") - self.__getMbeanData("JBoss MBean Count", - "jboss-mbean-count", - " serverinfo -c ") - self.__getMbeanData("JBoss MBean List", - "jboss-mbean-list", - " serverinfo -l ") - - ##JBoss Messaging Data - self.__jbossHTMLBody += """ - <br/> - <br/> - <div id="jboss-messaging" style="font-weight: bold;">– JBoss JMX Messaging MBean Data from <tt>jboss.messaging:*</tt></div> - """ - self.__getMbeanData("JBoss Message Counters", - "jboss-message-counters", - " invoke 'jboss.messaging:service=ServerPeer' listMessageCountersAsHTML ") - - self.__getMbeanData("JBoss Prepared Transactions Table", - "jboss-prepared-transactions", - " invoke 'jboss.messaging:service=ServerPeer' listAllPreparedTransactions ") - - self.__getMbeanData("JBoss Active Clients Table", - "jboss-active-clients", - " invoke 'jboss.messaging:service=ServerPeer' showActiveClientsAsHTML ") - - ## Get j2ee Data query 'jboss.j2ee:*' - self.__jbossHTMLBody += """ - <br/> - <br/> - <div id="jboss-j2ee" style="font-weight: bold;">– JBoss JMX J2EE MBean Data from <tt>jboss.j2ee:*</tt></div> - """ - self.__getMbeanData("JBoss J2EE MBeans", - "jboss-j2ee-mbeans", - " query 'jboss.j2ee:*' ") - - ## VFS - self.__jbossHTMLBody += """ - <br/> - <br/> - <div id="jboss-vfs" style="font-weight: bold;">– JBoss JMX VFS MBean Data from <tt>jboss.vfs:*</tt></div> - """ - self.__getMbeanData("JBoss VFS Cached Contexts", - "jboss-vfs-contexts", - " invoke 'jboss.vfs:service=VFSCacheStatistics' listCachedContexts ") - - ## Get jsr77 Data - self.__jbossHTMLBody += """ - <br/> - <br/> - <div id="jboss-jsr77-data" style="font-weight: bold;">– JBoss JSR77 Data</div> - """ - self.__getMbeanData("JBoss JSR77 Data", - "jboss-jsr77", - " jsr77 ") - return - - - def __getFiles(self, configDirAry): - """ - This function will collect files from JBOSS_HOME for analysis. The scope of files to - be collected are determined by options to this SOS plug-in. - """ - - for dir in configDirAry: - path=os.path.join(self.__jbossHome, "server", dir) - ## First add forbidden files - self.add_forbidden_path(os.path.join(path, "tmp")) - self.add_forbidden_path(os.path.join(path, "work")) - self.add_forbidden_path(os.path.join(path, "data")) - - if os.path.exists(path): - ## First get everything in the conf dir - confDir=os.path.join(path, "conf") - self.do_copy_file_or_dir(confDir) - ## Log dir next - logDir=os.path.join(path, "log") - - for logFile in find("*", logDir): - self.add_copy_spec_limit(logFile, self.get_option("logsize")) - ## Deploy dir - deployDir=os.path.join(path, "deploy") - - for deployFile in find("*", deployDir, max_depth=1): - self.add_copy_spec(deployFile) - - ## Get application deployment descriptors if designated. - if self.option_enabled("appxml"): - appxml=self.get_option("appxml") - ## I'd rather use comma as the delimiter but get_option doesn't seem to be passing it through. - ## Since we are using spaces as the delimiter, we need to filter out empty list elements - ## if the user did something like ' all default web '. - appxml=appxml.split(' ') - ## Flter(None doesn't work. Allows 0. - appxml=filter(lambda x: len(x), appxml) - for app in appxml: - pat = os.path.join("*%s*" % (app,), "WEB-INF") - for file in find("*.xml", deployDir, path_pattern=pat): - self.add_copy_spec(file) - return - - def check_enabled(self): - if not self.__getJbossHome(): - return False - return True - - def setup(self): - - ## We need to know where JBoss is installed and if we can't find it we - ## must exit immediately. - if not self.__getJbossHome(): - self.exit_please() - return - - ## Check to see if the user passed in a limited list of server config jars. - self.__updateServerConfigDirs() - - ## Generate HTML Body for report - self.__createHTMLBodyStart() - - ## Generate hashes of the stock Jar files for the report. - if self.get_option("stdjar"): - self.__getStdJarInfo() - - ## Generate hashes for the Jars in the various profiles - if self.get_option("servjar"): - self.__getServerConfigJarInfo(self.__jbossServerConfigDirs) - - ## Generate a Tree for JBOSS_HOME - self.__getJBossHomeTree() - - if self.get_option("twiddle"): - ## We need to know where Java is installed or at least ensure that it - ## is available to the plug-in so that we can run twiddle. - self.__haveJava = self.__getJavaHome() - self.__buildTwiddleCmd() - self.__getTwiddleData() - - - self.add_custom_text(self.__jbossHTMLBody) - - self.__getFiles(self.__jbossServerConfigDirs) - - return - - def postproc(self): - """ - Obfuscate passwords. - """ - - for dir in self.__jbossServerConfigDirs: - path=os.path.join(self.__jbossHome, "server", dir) - ## Really annoying that there appears to be no vehicle to - ## say I want ignore case...argh! - self.do_file_sub(os.path.join(path,"conf","login-config.xml"), - r"\"[Pp][Aa][Ss][Ss][Ww][Oo][Rr][Dd]\".*>.*</[Mm][Oo][Dd][Uu][Ll][Ee]-[Oo][Pp][Tt][Ii][Oo][Nn].*>", - r'"password">********</module-option>') - - tmp = os.path.join(path,"conf", "props") - for propFile in find("*-users.properties", tmp): - self.do_file_sub(propFile, - r"=(.*)", - r'=********') - - ## Remove PW from -ds.xml files - tmp=os.path.join(path, "deploy") - for dsFile in find("*-ds.xml", tmp): - self.do_file_sub(dsFile, - r"<[Pp][Aa][Ss][Ss][Ww][Oo][Rr][Dd].*>.*</[Pp][Aa][Ss][Ss][Ww][Oo][Rr][Dd].*>", - r"<password>********</password>") - return |