cas-admin cas.spec Makefile setup.py version
by Adam Stokes
Makefile | 5 +----
cas-admin | 9 ++++++---
cas.spec | 3 +++
setup.py | 4 ----
version | 2 +-
5 files changed, 11 insertions(+), 12 deletions(-)
New commits:
commit a7aa32cca2efe5a43b6e6df9f2f9f22a2b67bc30
Author: Adam Stokes <ajs(a)redhat.com>
Date: Fri Dec 19 09:12:03 2008 -0500
spec cleanup
diff --git a/Makefile b/Makefile
index a927610..8cd102e 100644
--- a/Makefile
+++ b/Makefile
@@ -12,7 +12,7 @@ SOURCE4 = $(PWD)/cas-admin.1.gz
all:
-.PHONY: tarball install version clean rpm
+.PHONY: tarball install clean rpm
tarball: clean
@echo "Creating archive"
@@ -30,9 +30,6 @@ tarball: clean
rpm:
rpmbuild -ba $(NAME).spec
-version:
- @echo "The version is $(NAME)-$(VERSION)"
-
clean:
@rm -rfv {dist,build}
@rm -rf *.\~*
diff --git a/cas-admin b/cas-admin
index 9e1c553..100140d 100755
--- a/cas-admin
+++ b/cas-admin
@@ -62,6 +62,7 @@ class CasDatabaseHandler(object):
pipe = Popen(cmd, stdout=PIPE, stderr=PIPE)
# setup count for kernels found, mainly for console output
count = 0
+ # create list of rpms from `cmd`
for line in pipe.stdout:
rpms.append(line.strip())
self.casLog.status("(found) %-5d kernel(s)" % (count,))
@@ -77,6 +78,7 @@ class CasDatabaseHandler(object):
if not self.rpmExist(x):
self.rpmDB[x] = []
count = count + 1
+ # temporary storage path in form of DEBUGS/COUNT
dst = os.path.join(DEBUGS, str(count))
rpmTool = RPMBase()
self.casLog.status("(extracting) [%d/%d] %-50s" % (count, totalRpms,
@@ -91,7 +93,6 @@ class CasDatabaseHandler(object):
timestamp = stamper.timestamp(debugKernel)
# Build tuple of each debug type
self.rpmDB[x].append((debugKernel, timestamp))
- self.casLog.status("(timestamp) gathering timestamp ..")
self.util.save(self.rpmDB, RPMS)
# Cleanup extracted debugs
rmtree(dst)
@@ -121,7 +122,9 @@ class CasServerHandler(object):
# silly magic to get output from command module
# since we are doing one host at a time we just pull the first
# key from the dict and parse its return
- (sts, arch, err) = client_dict[client_dict.keys()[0]]
+ sts, arch, err = client_dict[client_dict.keys()[0]]
+ if sts:
+ self.casLog.debug(err)
# clean up arch string
arch = arch.strip()
if serverList.has_key(arch):
@@ -130,7 +133,7 @@ class CasServerHandler(object):
serverList[arch] = [hostname]
hostname_count = hostname_count + 1
self.util.save(serverList, SERVERS)
- self.casLog.debug("Server database built with %d server(s) added.\n" % (hostname_count,))
+ self.casLog.info("Server database built with %d server(s) added." % (hostname_count,))
except ImportError:
self.casLog.debug("Please install func (http://fedorahosted.org/func) for " \
"an automated machine arch population.\n")
diff --git a/cas.spec b/cas.spec
index c9c7011..7a8c923 100644
--- a/cas.spec
+++ b/cas.spec
@@ -6,6 +6,9 @@ Source1: version
Version: %(echo `awk '{print $1 }' %{SOURCE1}`)
Release: %(echo `awk '{print $2 }' %{SOURCE1}`)%{?dist}
Source0: %{name}-%{version}.tar.gz
+Source2: cas-admin.1.gz
+Source3: cas.1.gz
+Source4: cas.conf
License: GPL
Group: Development/Libraries
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
diff --git a/setup.py b/setup.py
index 038664c..06cffd6 100644
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,3 @@
-#!/usr/bin/env python
-
-# $Id: setup.py,v 1.12 2008/02/20 21:40:05 sdodson Exp $
-
"""
setup.py - distutils packaging
"""
diff --git a/version b/version
index 7885ba9..d13d5c2 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-0.13 110
+0.13 112
15 years, 4 months
cas cas-admin lib/cas version
by Adam Stokes
cas | 19 ++-
cas-admin | 2
lib/cas/cas_shutil.py | 268 ++++++++++++++++++++++++++++++++++++++++++++++++++
lib/cas/util.py | 2
version | 2
5 files changed, 285 insertions(+), 8 deletions(-)
New commits:
commit 4fe82903020250a62deb08e017fa2e6b080fb5ff
Author: Adam Stokes <ajs(a)redhat.com>
Date: Tue Dec 16 10:10:03 2008 -0500
- include shutil from python 2.6, major performance
improvement within the move method
- decided to handle all files within the `cwd` until
extracted and ready for processing (thats where shutil
comes into play)
diff --git a/cas b/cas
index 0e66cda..2854f72 100755
--- a/cas
+++ b/cas
@@ -18,7 +18,6 @@ import sys
import optparse
import os
import ConfigParser
-import shutil
import smtplib
from subprocess import Popen, PIPE
@@ -28,6 +27,10 @@ from cas.core import CoreBase, CoreException
from cas.util import UtilBase, Logging
from cas.rpmutils import RPMBase
+# shutil from python 2.6 includes several enhancements for our use
+# mainly in the _move_ method.
+import cas.cas_shutil as shutil
+
if sys.version_info[:2] < (2,4):
raise SystemExit("Python >= 2.4 required")
@@ -43,6 +46,7 @@ SMTPHOST = config.get("settings", "mailServer")
class CoreHandler(object):
def __init__(self, filename, dst, logger):
self.filename = filename
+ self.basename = os.path.basename(self.filename)
self.dst = dst
self.currentDirectory = os.path.realpath(os.curdir)
self.casLog = logger
@@ -61,17 +65,22 @@ class CoreHandler(object):
self.casLog.debug("Unable to find file %s" % (self.filename,))
sys.exit(1)
if self.tool.isCorefile(self.filename):
- basename = os.path.basename(self.filename)
# No need to proceed to extracting corefile since we assume
# this is already at the proper stage.
shutil.move(self.filename,
- os.path.join(self.dst, basename))
- self.filename = os.path.join(self.dst, basename)
+ os.path.join(self.dst, self.basename))
+ self.filename = os.path.join(self.dst, self.basename)
return self.filename
try:
self.casLog.info("Detected a compressed core, extracting.. please wait as " \
"this process can take a long time.")
- corepath = self.tool.extractCore(self.filename)
+ # ok so some decompression utilites like gzip, bzip do not extract
+ # files into the `cwd` unless specified with a to-stdout option.
+ # this is a pain so we just move everything to `cwd` and proceed
+ # from there.
+ dst = os.path.join(self.currentDirectory, self.basename)
+ shutil.move(self.filename, dst)
+ corepath = self.tool.extractCore(dst)
# corefile extracted now move it to work directory, pull basename
# from corepath since we auto-detect the core file from extraction
coreBasename = os.path.basename(corepath)
diff --git a/cas-admin b/cas-admin
index a852be0..9e1c553 100755
--- a/cas-admin
+++ b/cas-admin
@@ -24,7 +24,7 @@ from cas.core import CoreBase
from cas.util import UtilBase, Logging
from cas.rpmutils import RPMBase
from subprocess import Popen, PIPE
-from shutil import rmtree
+from cas.cas_shutil import rmtree
if sys.version_info[:2] < (2,4):
raise SystemExit("Python >= 2.4 required")
diff --git a/lib/cas/cas_shutil.py b/lib/cas/cas_shutil.py
new file mode 100644
index 0000000..ae2c66c
--- /dev/null
+++ b/lib/cas/cas_shutil.py
@@ -0,0 +1,268 @@
+"""Utility functions for copying files and directory trees.
+
+XXX The functions here don't copy the resource fork or other metadata on Mac.
+
+"""
+
+import os
+import sys
+import stat
+from os.path import abspath
+import fnmatch
+
+__all__ = ["copyfileobj","copyfile","copymode","copystat","copy","copy2",
+ "copytree","move","rmtree","Error"]
+
+class Error(EnvironmentError):
+ pass
+
+try:
+ WindowsError
+except NameError:
+ WindowsError = None
+
+def copyfileobj(fsrc, fdst, length=16*1024):
+ """copy data from file-like object fsrc to file-like object fdst"""
+ while 1:
+ buf = fsrc.read(length)
+ if not buf:
+ break
+ fdst.write(buf)
+
+def _samefile(src, dst):
+ # Macintosh, Unix.
+ if hasattr(os.path,'samefile'):
+ try:
+ return os.path.samefile(src, dst)
+ except OSError:
+ return False
+
+ # All other platforms: check for same pathname.
+ return (os.path.normcase(os.path.abspath(src)) ==
+ os.path.normcase(os.path.abspath(dst)))
+
+def copyfile(src, dst):
+ """Copy data from src to dst"""
+ if _samefile(src, dst):
+ raise Error, "`%s` and `%s` are the same file" % (src, dst)
+
+ fsrc = None
+ fdst = None
+ try:
+ fsrc = open(src, 'rb')
+ fdst = open(dst, 'wb')
+ copyfileobj(fsrc, fdst)
+ finally:
+ if fdst:
+ fdst.close()
+ if fsrc:
+ fsrc.close()
+
+def copymode(src, dst):
+ """Copy mode bits from src to dst"""
+ if hasattr(os, 'chmod'):
+ st = os.stat(src)
+ mode = stat.S_IMODE(st.st_mode)
+ os.chmod(dst, mode)
+
+def copystat(src, dst):
+ """Copy all stat info (mode bits, atime, mtime, flags) from src to dst"""
+ st = os.stat(src)
+ mode = stat.S_IMODE(st.st_mode)
+ if hasattr(os, 'utime'):
+ os.utime(dst, (st.st_atime, st.st_mtime))
+ if hasattr(os, 'chmod'):
+ os.chmod(dst, mode)
+ if hasattr(os, 'chflags') and hasattr(st, 'st_flags'):
+ os.chflags(dst, st.st_flags)
+
+
+def copy(src, dst):
+ """Copy data and mode bits ("cp src dst").
+
+ The destination may be a directory.
+
+ """
+ if os.path.isdir(dst):
+ dst = os.path.join(dst, os.path.basename(src))
+ copyfile(src, dst)
+ copymode(src, dst)
+
+def copy2(src, dst):
+ """Copy data and all stat info ("cp -p src dst").
+
+ The destination may be a directory.
+
+ """
+ if os.path.isdir(dst):
+ dst = os.path.join(dst, os.path.basename(src))
+ copyfile(src, dst)
+ copystat(src, dst)
+
+def ignore_patterns(*patterns):
+ """Function that can be used as copytree() ignore parameter.
+
+ Patterns is a sequence of glob-style patterns
+ that are used to exclude files"""
+ def _ignore_patterns(path, names):
+ ignored_names = []
+ for pattern in patterns:
+ ignored_names.extend(fnmatch.filter(names, pattern))
+ return set(ignored_names)
+ return _ignore_patterns
+
+def copytree(src, dst, symlinks=False, ignore=None):
+ """Recursively copy a directory tree using copy2().
+
+ The destination directory must not already exist.
+ If exception(s) occur, an Error is raised with a list of reasons.
+
+ If the optional symlinks flag is true, symbolic links in the
+ source tree result in symbolic links in the destination tree; if
+ it is false, the contents of the files pointed to by symbolic
+ links are copied.
+
+ The optional ignore argument is a callable. If given, it
+ is called with the `src` parameter, which is the directory
+ being visited by copytree(), and `names` which is the list of
+ `src` contents, as returned by os.listdir():
+
+ callable(src, names) -> ignored_names
+
+ Since copytree() is called recursively, the callable will be
+ called once for each directory that is copied. It returns a
+ list of names relative to the `src` directory that should
+ not be copied.
+
+ XXX Consider this example code rather than the ultimate tool.
+
+ """
+ names = os.listdir(src)
+ if ignore is not None:
+ ignored_names = ignore(src, names)
+ else:
+ ignored_names = set()
+
+ os.makedirs(dst)
+ errors = []
+ for name in names:
+ if name in ignored_names:
+ continue
+ srcname = os.path.join(src, name)
+ dstname = os.path.join(dst, name)
+ try:
+ if symlinks and os.path.islink(srcname):
+ linkto = os.readlink(srcname)
+ os.symlink(linkto, dstname)
+ elif os.path.isdir(srcname):
+ copytree(srcname, dstname, symlinks, ignore)
+ else:
+ copy2(srcname, dstname)
+ # XXX What about devices, sockets etc.?
+ except (IOError, os.error), why:
+ errors.append((srcname, dstname, str(why)))
+ # catch the Error from the recursive copytree so that we can
+ # continue with other files
+ except Error, err:
+ errors.extend(err.args[0])
+ try:
+ copystat(src, dst)
+ except OSError, why:
+ if WindowsError is not None and isinstance(why, WindowsError):
+ # Copying file access times may fail on Windows
+ pass
+ else:
+ errors.extend((src, dst, str(why)))
+ if errors:
+ raise Error, errors
+
+def rmtree(path, ignore_errors=False, onerror=None):
+ """Recursively delete a directory tree.
+
+ If ignore_errors is set, errors are ignored; otherwise, if onerror
+ is set, it is called to handle the error with arguments (func,
+ path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
+ path is the argument to that function that caused it to fail; and
+ exc_info is a tuple returned by sys.exc_info(). If ignore_errors
+ is false and onerror is None, an exception is raised.
+
+ """
+ if ignore_errors:
+ def onerror(*args):
+ pass
+ elif onerror is None:
+ def onerror(*args):
+ raise
+ try:
+ if os.path.islink(path):
+ # symlinks to directories are forbidden, see bug #1669
+ raise OSError("Cannot call rmtree on a symbolic link")
+ except OSError:
+ onerror(os.path.islink, path, sys.exc_info())
+ # can't continue even if onerror hook returns
+ return
+ names = []
+ try:
+ names = os.listdir(path)
+ except os.error, err:
+ onerror(os.listdir, path, sys.exc_info())
+ for name in names:
+ fullname = os.path.join(path, name)
+ try:
+ mode = os.lstat(fullname).st_mode
+ except os.error:
+ mode = 0
+ if stat.S_ISDIR(mode):
+ rmtree(fullname, ignore_errors, onerror)
+ else:
+ try:
+ os.remove(fullname)
+ except os.error, err:
+ onerror(os.remove, fullname, sys.exc_info())
+ try:
+ os.rmdir(path)
+ except os.error:
+ onerror(os.rmdir, path, sys.exc_info())
+
+
+def _basename(path):
+ # A basename() variant which first strips the trailing slash, if present.
+ # Thus we always get the last component of the path, even for directories.
+ return os.path.basename(path.rstrip(os.path.sep))
+
+def move(src, dst):
+ """Recursively move a file or directory to another location. This is
+ similar to the Unix "mv" command.
+
+ If the destination is a directory or a symlink to a directory, the source
+ is moved inside the directory. The destination path must not already
+ exist.
+
+ If the destination already exists but is not a directory, it may be
+ overwritten depending on os.rename() semantics.
+
+ If the destination is on our current filesystem, then rename() is used.
+ Otherwise, src is copied to the destination and then removed.
+ A lot more could be done here... A look at a mv.c shows a lot of
+ the issues this implementation glosses over.
+
+ """
+ real_dst = dst
+ if os.path.isdir(dst):
+ real_dst = os.path.join(dst, _basename(src))
+ if os.path.exists(real_dst):
+ raise Error, "Destination path '%s' already exists" % real_dst
+ try:
+ os.rename(src, real_dst)
+ except OSError:
+ if os.path.isdir(src):
+ if destinsrc(src, dst):
+ raise Error, "Cannot move a directory '%s' into itself '%s'." % (src, dst)
+ copytree(src, real_dst, symlinks=True)
+ rmtree(src)
+ else:
+ copy2(src, real_dst)
+ os.unlink(src)
+
+def destinsrc(src, dst):
+ return abspath(dst).startswith(abspath(src))
diff --git a/lib/cas/util.py b/lib/cas/util.py
index d17232c..3ed4fff 100755
--- a/lib/cas/util.py
+++ b/lib/cas/util.py
@@ -16,8 +16,8 @@ import commands
import os
import re
import sys
-import shutil
import logging
+import cas.cas_shutil as shutil
from subprocess import Popen, PIPE, call
diff --git a/version b/version
index 094b0d8..7885ba9 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-0.13 107
+0.13 110
15 years, 4 months
cas lib/cas README version
by Adam Stokes
README | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++------
cas | 3 +-
lib/cas/core.py | 7 ------
version | 2 -
4 files changed, 56 insertions(+), 14 deletions(-)
New commits:
commit ce2402d04447ab8a3108e044f411357a1734768b
Author: Adam Stokes <ajs(a)redhat.com>
Date: Tue Dec 16 09:16:40 2008 -0500
- update README
- still deciding what to do about extracting of cores
for now when downloading cores from a remote site
it's all handled within the `cwd`. still need to
figure out how to handle gzip/bzip compressed files
when cas is ran against those outside of `cwd`.
diff --git a/README b/README
index b6d879f..df865b7 100644
--- a/README
+++ b/README
@@ -1,10 +1,56 @@
CAS.README
-* Alter /etc/cas.conf to suite your needs.
+* Other documentation check the wiki http://fedorahosted.org/cas
-* Build your rpm database and server database with cas-admin -b and cas-admin -s
- (requires http://fedorahosted.org/func for server process)
-
-* Grab kernel dump and run against cas, cas -i <id> -f corefile(.gz, tbz2, tgz, etc)
+Requirements
-* Other documentation check the wiki http://fedorahosted.org/cas
+/etc/cas.conf - This needs to be modified with your directory specifics.
+Comments in the conf file are pretty straight forward.
+
+A cas database needs to be prepared which houses all the build timestamps
+of the debug kernels you wish to use.
+
+As root run:
+
+# cas-admin -b
+
+Optional Requirements
+
+func - Please obtain this software from http://fedorahosted.org/func - setup is
+a breeze and enables cas to do automated core processing on different machine
+for different architectures.
+
+If you have func installed and setup you may re-run cas-admin to populate
+your server database:
+
+# cas-admin -s
+
+Running CAS
+
+Once completed take a generated kernel dump and send it through cas:
+
+# cas -i <ID> -f vmcore -m username(a)example.com
+
+The vmcore may be in the form of http/ftp (e.g. http://myhost.com/files/vmcore.tar.gz).
+
+The compression scheme for a vmcore should be in the form of one of the following:
+
+# tar cvzf vmcore.tar.gz vmcore
+# tar cvjf vmcore.tar.bz2 vmcore
+# gzip vmcore
+# bzip2 vmcore
+
+or you may pass it an uncompressed vmcore.
+
+Please do not _double compress_! For example, do not do a gzip vmcore,
+then a tar cvzf vmcore.tar.gz vmcore.gz as you will not gain anything
+from this. CAS will also fail to detect the decompression type.
+
+Once complete results should be emailed to the address specified or if
+processed locally should be prepared for you to do further analyzation
+within crash.
+
+If any problem occurs please check the log within
+/your/core/processed_dir/identifier/identifier.log
+
+Other documentation check the wiki http://fedorahosted.org/cas
diff --git a/cas b/cas
index 7a81329..0e66cda 100755
--- a/cas
+++ b/cas
@@ -44,6 +44,7 @@ class CoreHandler(object):
def __init__(self, filename, dst, logger):
self.filename = filename
self.dst = dst
+ self.currentDirectory = os.path.realpath(os.curdir)
self.casLog = logger
self.tool = CoreBase()
@@ -53,7 +54,7 @@ class CoreHandler(object):
# filename is a url, process it with our download module
# this should return the the abspath to our processed directory
# and downloaded file
- self.filename = Download(self.filename, self.dst).get()
+ self.filename = Download(self.filename, self.currentDirectory).get()
if not os.path.isfile(self.filename):
# not a url in this case so tests for local existence
# TODO: add support to check remote hosts
diff --git a/lib/cas/core.py b/lib/cas/core.py
index b46af47..d3cd0db 100644
--- a/lib/cas/core.py
+++ b/lib/cas/core.py
@@ -26,7 +26,7 @@ class CoreBase(object):
"Return a good default Operation, judging by the first 300 bytes or so."
suffix_map = { "tar" : ["tar", "xvf"],
"tgz" : ["tar", "xvzf"],
- "gz" : ["gunzip", "-qcd"],
+ "gz" : ["gunzip", "-q"],
"tbz" : ["tar", "xvjf"],
"bz2" : ["bunzip2", "-q"],
"zip" : ["unzip", "-f"]}
@@ -65,11 +65,6 @@ class CoreBase(object):
raise CoreException("Can not determine compression format.")
else:
format.append(self.filepath)
- # if gunzip in format we need to redirect to stdout
- # FIXME: this is stupid and ugly, gotta be a better way.
- if 'gunzip' in format[0]:
- format.append(">")
- format.append(os.path.join(self.dst,"vmcore"))
# TODO: figure out someway to print some status to the screen
# during extraction
# FIXME: failing to determine corefile after extraction, running
diff --git a/version b/version
index 9c81921..094b0d8 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-0.13 106
+0.13 107
15 years, 4 months
cas lib/cas version
by Adam Stokes
cas | 5 ++++-
lib/cas/core.py | 7 ++++++-
lib/cas/util.py | 2 +-
version | 2 +-
4 files changed, 12 insertions(+), 4 deletions(-)
New commits:
commit 4948390870a0b44969bb8b0e478946b434c99327
Author: Adam Stokes <ajs(a)redhat.com>
Date: Tue Dec 16 08:58:39 2008 -0500
- trying to solve all problems that arise when running
cas against a file outside of its `cwd`. latest problem
is with a gzipped file when not being redirected to
stdout. ugly hack to address that for now
diff --git a/cas b/cas
index 3d63000..7a81329 100755
--- a/cas
+++ b/cas
@@ -49,6 +49,7 @@ class CoreHandler(object):
def run(self):
if(self.filename.startswith("http") or self.filename.startswith("ftp")):
+ self.casLog.info("Downloading %s" % (self.filename,))
# filename is a url, process it with our download module
# this should return the the abspath to our processed directory
# and downloaded file
@@ -182,7 +183,9 @@ class CasApplication(object):
client = fc.Overlord(casProcessMachine)
clientDict = client.command.run(cmd)
# Only necessary for debugging why running of crash failed.
- # (sts, out, err) = clientDict[clientDict.keys()[0]]
+ sts, out, err = clientDict[clientDict.keys()[0]]
+ if sts:
+ self.casLog.debug(out.strip())
else:
self.casLog.info("No servers available for arch and current system not "\
"suitable for processing, please run cas-admin -h " \
diff --git a/lib/cas/core.py b/lib/cas/core.py
index d3cd0db..b46af47 100644
--- a/lib/cas/core.py
+++ b/lib/cas/core.py
@@ -26,7 +26,7 @@ class CoreBase(object):
"Return a good default Operation, judging by the first 300 bytes or so."
suffix_map = { "tar" : ["tar", "xvf"],
"tgz" : ["tar", "xvzf"],
- "gz" : ["gunzip", "-q"],
+ "gz" : ["gunzip", "-qcd"],
"tbz" : ["tar", "xvjf"],
"bz2" : ["bunzip2", "-q"],
"zip" : ["unzip", "-f"]}
@@ -65,6 +65,11 @@ class CoreBase(object):
raise CoreException("Can not determine compression format.")
else:
format.append(self.filepath)
+ # if gunzip in format we need to redirect to stdout
+ # FIXME: this is stupid and ugly, gotta be a better way.
+ if 'gunzip' in format[0]:
+ format.append(">")
+ format.append(os.path.join(self.dst,"vmcore"))
# TODO: figure out someway to print some status to the screen
# during extraction
# FIXME: failing to determine corefile after extraction, running
diff --git a/lib/cas/util.py b/lib/cas/util.py
index 5617771..d17232c 100755
--- a/lib/cas/util.py
+++ b/lib/cas/util.py
@@ -169,7 +169,7 @@ class UtilBase(object):
crashInputFH.close()
vmcorePath = os.path.join(dst, vmcore)
- crashCmd = "#!/bin/sh\ncrash %s %s -i %s -s\n" % (vmcorePath, debug,
+ crashCmd = "#!/bin/sh\ncrash %s %s -s < %s\n" % (vmcorePath, debug,
crashInputPath)
crashExe = os.path.join(dst,"crash")
fh = open(crashExe,"w")
diff --git a/version b/version
index f4a3dd4..9c81921 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-0.13 104
+0.13 106
15 years, 4 months
cas cas.conf lib/cas version
by Adam Stokes
cas | 16 +++++++++-------
cas.conf | 6 ++++--
lib/cas/util.py | 10 ++++++----
version | 2 +-
4 files changed, 20 insertions(+), 14 deletions(-)
New commits:
commit aea790393f682d24689d4eaf1016b831df8ca17c
Author: Adam Stokes <ajs(a)redhat.com>
Date: Tue Dec 16 07:10:05 2008 -0500
- some initial tests of extracting the compressed core
were successful in detecting the core.
- fixed an issue with running cas against a core outside
of `cwd` were not being moved to work directory.
diff --git a/cas b/cas
index 89cfc1e..3d63000 100755
--- a/cas
+++ b/cas
@@ -59,11 +59,12 @@ class CoreHandler(object):
self.casLog.debug("Unable to find file %s" % (self.filename,))
sys.exit(1)
if self.tool.isCorefile(self.filename):
+ basename = os.path.basename(self.filename)
# No need to proceed to extracting corefile since we assume
# this is already at the proper stage.
shutil.move(self.filename,
- os.path.join(self.dst, self.filename))
- self.filename = os.path.join(self.dst, self.filename)
+ os.path.join(self.dst, basename))
+ self.filename = os.path.join(self.dst, basename)
return self.filename
try:
self.casLog.info("Detected a compressed core, extracting.. please wait as " \
@@ -174,13 +175,14 @@ class CasApplication(object):
serverList = self.util.load(SERVERS)
if serverList.has_key(debugKernelArch):
# TODO: Randomize server selection
+ # TODO: Verify remote server is reachable
casProcessMachine = serverList[debugKernelArch][0]
self.casLog.info("Machine %s found, processing crash output" % (casProcessMachine,))
cmd = os.path.join(self.storagePath,"crash")
client = fc.Overlord(casProcessMachine)
- client_dict = client.command.run(cmd)
+ clientDict = client.command.run(cmd)
# Only necessary for debugging why running of crash failed.
- # (sts, out, err) = client_dict[client_dict.keys()[0]]
+ # (sts, out, err) = clientDict[clientDict.keys()[0]]
else:
self.casLog.info("No servers available for arch and current system not "\
"suitable for processing, please run cas-admin -h " \
@@ -227,13 +229,13 @@ class CasApplication(object):
# for name or service not known :(
mailServer = smtplib.SMTP(SMTPHOST)
except:
- dprint("Unable to connect to mail server: %s, no email " \
- "results sent." % (SMTPHOST,))
+ self.casLog.debug("Unable to connect to mail server: %s, no email " \
+ "results sent." % (SMTPHOST,))
mailServer.set_debuglevel(0)
mailServer.sendmail(self.email,self.email,msg)
mailServer.quit()
except smtplib.SMTPException, e:
- dprint(e)
+ self.casLog.debug(e)
self.casLog.info("Job on %s complete and located in %s." % (self.filename,
self.storagePath))
return
diff --git a/cas.conf b/cas.conf
index 774b4f6..5a49447 100644
--- a/cas.conf
+++ b/cas.conf
@@ -12,8 +12,10 @@ rpms=/var/db/cas/rpms.db
rpmFilter=.*kernel-debuginfo-[0-9].*\.rpm
# Define where to store necessary debug information
-# NOTE: This is more than likely going to be temporary storage
-# so you could essentially set this to /tmp if space permitted
+# NOTE: This is a temporary storage area for when
+# cpio is run against an rpm and extract the debug kernel
+# for a small amount of time. This could be something like
+# /tmp if space permitted
debugs=/cores/debugs
# debug level (DEBUG, INFO)
diff --git a/lib/cas/util.py b/lib/cas/util.py
index 59cb65f..5617771 100755
--- a/lib/cas/util.py
+++ b/lib/cas/util.py
@@ -23,6 +23,7 @@ from subprocess import Popen, PIPE, call
class Logging(object):
def __init__(self, dst, logger_id, debug_level='DEBUG'):
+ self.debug_level = debug_level
self.dst = dst
self.logger_id = logger_id
self.logfile = logger_id+".log"
@@ -39,12 +40,13 @@ class Logging(object):
fh_fmt = logging.Formatter("%(asctime)s %(process)d (%(levelname)s)\t: %(message)s")
ch.setFormatter(ch_fmt)
fh.setFormatter(fh_fmt)
- logging_level = {'DEBUG':logging.DEBUG,
- 'INFO':logging.INFO}
- self.log.setLevel(logging_level[debug_level])
+ logging_level = {'DEBUG': logging.DEBUG,
+ 'INFO' : logging.INFO}
+ self.log.setLevel(logging_level[self.debug_level])
def debug(self, msg):
- self.log.debug("[.cas.][debug] :: %s" % (msg,))
+ if self.debug_level == 'DEBUG':
+ self.log.debug("[.cas.][debug] :: %s" % (msg,))
def status(self, msg):
""" function to print status messages
diff --git a/version b/version
index a0881bd..f4a3dd4 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-0.13 103
+0.13 104
15 years, 4 months
cas lib/cas version
by Adam Stokes
cas | 10 ++++++----
lib/cas/core.py | 9 ++++++---
version | 2 +-
3 files changed, 13 insertions(+), 8 deletions(-)
New commits:
commit cfd5c56822c396c8a72ff7acfadc435bef90e8ce
Author: Adam Stokes <adam(a)conans.battleaxe>
Date: Mon Dec 15 19:37:05 2008 -0500
- hopefully fixed the problem where cores weren't detected
from extracted archives/compressed files.
diff --git a/cas b/cas
index 7674104..89cfc1e 100755
--- a/cas
+++ b/cas
@@ -66,12 +66,14 @@ class CoreHandler(object):
self.filename = os.path.join(self.dst, self.filename)
return self.filename
try:
- self.casLog.info("Detected a compressed core, extracting")
- corepath = self.tool.extractCore(self.filename, self.dst)
+ self.casLog.info("Detected a compressed core, extracting.. please wait as " \
+ "this process can take a long time.")
+ corepath = self.tool.extractCore(self.filename)
# corefile extracted now move it to work directory, pull basename
# from corepath since we auto-detect the core file from extraction
- shutil.move(corepath,os.path.join(self.dst, os.path.basename(corepath)))
- self.filename = os.path.join(self.dst, os.path.basename(corepath))
+ coreBasename = os.path.basename(corepath)
+ shutil.move(corepath,os.path.join(self.dst, coreBasename))
+ self.filename = os.path.join(self.dst, coreBasename)
return self.filename
except CoreException, err:
self.casLog.debug(err)
diff --git a/lib/cas/core.py b/lib/cas/core.py
index 37f175f..d3cd0db 100644
--- a/lib/cas/core.py
+++ b/lib/cas/core.py
@@ -51,10 +51,12 @@ class CoreBase(object):
return suffix_map["bz2"]
return False
- def extractCore(self, filepath, dst):
+ def extractCore(self, filepath):
""" utility to extract archive and pull out core
"""
- self.dst = dst
+ # Making an assumption that if we are extracting a file then
+ # the contents of that file are placed wherever cas is run from
+ self.dst = os.path.realpath(os.curdir)
self.filepath = filepath
fd = open(self.filepath, 'rb')
data = os.read(fd.fileno(), 1000)
@@ -66,7 +68,8 @@ class CoreBase(object):
# TODO: figure out someway to print some status to the screen
# during extraction
# FIXME: failing to determine corefile after extraction, running
- # on extracted core works.
+ # on extracted core works. possible problem being looking in the wrong
+ # directory
p = Popen(format, stdout=PIPE, stderr=PIPE)
err = p.stderr.read()
out = p.stdout.read()
diff --git a/version b/version
index 50c8612..a0881bd 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-0.13 102
+0.13 103
15 years, 4 months
cas.spec lib/cas README
by Adam Stokes
README | 2 ++
cas.spec | 1 +
lib/cas/core.py | 2 ++
3 files changed, 5 insertions(+)
New commits:
commit 295fca06ff003319223f1c3944a600bb2d7e085c
Author: Adam Stokes <adam(a)conans.battleaxe>
Date: Mon Dec 15 18:30:45 2008 -0500
- FIXME: problem detecting corefile from a compressed file/archive
it should work but doesn't quite yet :( in the meantime running cas
twice is the alternative, once against the compressed file then second
on the core itself ( or uncompress it as you normally would )
- add crash for requirements
diff --git a/README b/README
index cc73619..b6d879f 100644
--- a/README
+++ b/README
@@ -6,3 +6,5 @@ CAS.README
(requires http://fedorahosted.org/func for server process)
* Grab kernel dump and run against cas, cas -i <id> -f corefile(.gz, tbz2, tgz, etc)
+
+* Other documentation check the wiki http://fedorahosted.org/cas
diff --git a/cas.spec b/cas.spec
index a516164..c9c7011 100644
--- a/cas.spec
+++ b/cas.spec
@@ -13,6 +13,7 @@ BuildArch: noarch
Url: http://fedorahosted.org/cas
BuildRequires: python-devel
Requires: python >= 2.4
+Requires: crash
%description
CAS provides a support engineer the ability to configure an environment for
diff --git a/lib/cas/core.py b/lib/cas/core.py
index 75c1cb4..37f175f 100644
--- a/lib/cas/core.py
+++ b/lib/cas/core.py
@@ -65,6 +65,8 @@ class CoreBase(object):
format.append(self.filepath)
# TODO: figure out someway to print some status to the screen
# during extraction
+ # FIXME: failing to determine corefile after extraction, running
+ # on extracted core works.
p = Popen(format, stdout=PIPE, stderr=PIPE)
err = p.stderr.read()
out = p.stdout.read()
15 years, 4 months
crash not a requirement?
by Jon Stanley
It seems that crash isn't required in the RPM, so I battled a bit on a
system without it giving non-obvious errors. Might wanna add that to
Requires.
Other than that, I got my first successful analysis! Next thing that
I'd like to try out is the func stuff, but I'm not that familiar with
func (and I've been meaning to learn it for other stuff, too). The
documentation seems to make it as simple as 'install func, run
cas-admin -s', but I'm sure it can't be so simple :)
15 years, 4 months
CentOS/RHEL support
by Jon Stanley
So in my testbed at home has a somewhat random combination of CentOS,
RHEL, and Fedora. A box which I thought to be RHEL (and stupid me I
didn't check /etc/redhat-release) turned out not to be. Where this
gets interesting is that I tried running CAS on a core from it:
[root@dhcp-149 ~]# cas -i 1 -f 2008-1215-1219.59-rhds-1.70.core
[.cas.] :: Starting job at /cores/processed/12 on file
/root/2008-1215-1219.59-rhds-1.70.core
[.cas.] :: Corefile prepared, processing /root/2008-1215-1219.59-rhds-1.70.core
[.cas.] :: Running timestamp
[.cas.](debug) :: Unable to match
(/root/2008-1215-1219.59-rhds-1.70.core,Linux version
2.6.9-78.0.1.ELxenU (mockbuild(a)builder10.centos.org) (gcc version
3.4.6 20060404 (Red Hat 3.4.6-10)) #1 SMP Tue Aug 5 11:25:12 EDT 2008)
with debugKernel
So I tried finding the debuginfo from CentOS (can''t find it, I'll
take that up with the CentOS guys). But even if I did, would it work
since I have a RHEL debuginfo of the exact same NEVRA? Food for
thought....
15 years, 4 months
cas cas-admin cas.conf lib/cas version
by Adam Stokes
cas | 87 ++++++++++++++++++++++++++++----------------------------
cas-admin | 38 ++++++++++++++----------
cas.conf | 4 +-
lib/cas/core.py | 2 +
lib/cas/util.py | 61 +++++++++++++++++++++------------------
version | 2 -
6 files changed, 107 insertions(+), 87 deletions(-)
New commits:
commit 1682f17099ae9920c5f375cc94125e783d8eb89e
Author: Adam Stokes <adam(a)conans.battleaxe>
Date: Mon Dec 15 13:39:11 2008 -0500
- some issues rose when running cas outside of the processed directory
hopefully fixed, however, note that if you use anything less than
python 2.6 shutil.move does a copy rather than just a rename which
can add to the wait time :(
- more work done on the logger, so far seems easy to implement in the code
just need to carry the object over to my different classes.
diff --git a/cas b/cas
index 307bc04..7674104 100755
--- a/cas
+++ b/cas
@@ -25,7 +25,7 @@ from subprocess import Popen, PIPE
from cas.network import Download
from cas.core import CoreBase, CoreException
-from cas.util import UtilBase, dprint, cprint
+from cas.util import UtilBase, Logging
from cas.rpmutils import RPMBase
if sys.version_info[:2] < (2,4):
@@ -36,64 +36,69 @@ config = ConfigParser.ConfigParser()
config.read("/etc/cas.conf")
WORKDIRECTORY = config.get("settings","workDirectory")
RPMS = config.get("settings","rpms")
-DPRINT = config.get("settings","dprint")
+DEBUGLEVEL = config.get("settings","debugLevel")
SERVERS = config.get("settings", "servers")
SMTPHOST = config.get("settings", "mailServer")
class CoreHandler(object):
- def __init__(self, filename, dst, is_url):
- self.filename = filename # abspath of file or url
- self.is_url = is_url
+ def __init__(self, filename, dst, logger):
+ self.filename = filename
self.dst = dst
+ self.casLog = logger
self.tool = CoreBase()
def run(self):
- if self.is_url:
- # return abspath of location of downloaded corefile
+ if(self.filename.startswith("http") or self.filename.startswith("ftp")):
+ # filename is a url, process it with our download module
+ # this should return the the abspath to our processed directory
+ # and downloaded file
self.filename = Download(self.filename, self.dst).get()
if not os.path.isfile(self.filename):
- dprint("Unable to find file %s" % (self.filename,), DPRINT)
+ # not a url in this case so tests for local existence
+ # TODO: add support to check remote hosts
+ self.casLog.debug("Unable to find file %s" % (self.filename,))
sys.exit(1)
if self.tool.isCorefile(self.filename):
# No need to proceed to extracting corefile since we assume
# this is already at the proper stage.
shutil.move(self.filename,
os.path.join(self.dst, self.filename))
- return os.path.join(self.dst, self.filename)
+ self.filename = os.path.join(self.dst, self.filename)
+ return self.filename
try:
- cprint("Detected compressed archive, extracting.")
+ self.casLog.info("Detected a compressed core, extracting")
corepath = self.tool.extractCore(self.filename, self.dst)
# corefile extracted now move it to work directory, pull basename
# from corepath since we auto-detect the core file from extraction
shutil.move(corepath,os.path.join(self.dst, os.path.basename(corepath)))
- return os.path.join(self.dst, os.path.basename(corepath))
+ self.filename = os.path.join(self.dst, os.path.basename(corepath))
+ return self.filename
except CoreException, err:
- dprint(err, DPRINT)
+ self.casLog.debug(err)
sys.exit(1)
class TimestampHandler(object):
- def __init__(self, corefile):
+ def __init__(self, corefile, logger):
self.corefile = corefile
+ self.casLog = logger
self.util = UtilBase()
self.tool = CoreBase()
def run(self):
# dig through the buildstamp database and attempt to match it with the
# one found in the core
- cprint("Running timestamp on %s" % (self.corefile,))
rpmDB = self.util.load(RPMS)
try:
coreTimestamp = self.tool.timestamp(self.corefile)
except CoreException, err:
- dprint(err, DPRINT)
+ self.casLog.debug(err)
sys.exit(1)
for k,v in rpmDB.iteritems():
for coreObj in rpmDB[k]:
debugKernel, timestamp = coreObj
if timestamp and coreTimestamp in timestamp:
- cprint("Timestamp found %s" % (coreTimestamp,))
return (k, debugKernel)
- dprint("Unable to match (%s,%s) with debugKernel" % (self.corefile, coreTimestamp), DPRINT)
+ self.casLog.debug("Unable to match timestamp %s/%s" % (timestamp,debugKernel))
sys.exit(1)
class CasApplication(object):
@@ -121,29 +126,25 @@ class CasApplication(object):
parser.error("A file object is missing.")
self.filename = self.opts.filename
- self.is_url = True
- # not a url, so we assume its a local file, pre-pend absolute path
- if (not self.filename.startswith("http") or not self.filename.startswith("ftp")):
- self.filename = os.path.abspath(self.filename)
- self.is_url = False
self.identifier = self.opts.identifier
self.email = self.opts.email
-
self.storagePath = os.path.join(WORKDIRECTORY, self.identifier)
+
+ # build logger object to deal with logging per job and keep things
+ # clean and easy to debug
+ self.casLog = Logging(self.storagePath, self.identifier)
def run(self):
# setup directory structure
if not os.path.isdir(self.storagePath):
os.makedirs(self.storagePath)
- cprint("Starting job at %s on file %s" % (self.storagePath, self.filename))
- # change into processed directory for completion
- # os.chdir(self.storagePath)
+ self.casLog.info("Starting job at %s" % (self.storagePath,))
# begin core extraction analysis
- corefile = CoreHandler(self.filename, self.storagePath, self.is_url).run()
- cprint("Corefile prepared, processing %s" % (corefile,))
- debuginfo, debugKernel = TimestampHandler(corefile).run()
+ corefile = CoreHandler(self.filename, self.storagePath, self.casLog).run()
+ self.casLog.info("Corefile prepared, processing %s" % (corefile,))
+ debuginfo, debugKernel = TimestampHandler(corefile, self.casLog).run()
filterString = "*/%s" % (debugKernel,)
- cprint("Extracting debug kernel with filter %s" % (filterString,))
+ self.casLog.info("Extracting debug kernel with filter %s" % (filterString,))
self.rpmTool.extract(debuginfo, self.storagePath,
filter=filterString,
return_results=False)
@@ -165,49 +166,51 @@ class CasApplication(object):
# is configured we attempt to process the core at another machine.
try:
import func.overlord.client as fc
- cprint("Crash file built, locating suitable %s system for " \
+ self.casLog.info("Crash file built, locating suitable %s system for " \
"processing" % (debugKernelArch,))
if os.path.isfile(SERVERS):
serverList = self.util.load(SERVERS)
if serverList.has_key(debugKernelArch):
# TODO: Randomize server selection
casProcessMachine = serverList[debugKernelArch][0]
- cprint("Machine %s found, processing crash output" % (casProcessMachine,))
+ self.casLog.info("Machine %s found, processing crash output" % (casProcessMachine,))
cmd = os.path.join(self.storagePath,"crash")
client = fc.Overlord(casProcessMachine)
client_dict = client.command.run(cmd)
# Only necessary for debugging why running of crash failed.
# (sts, out, err) = client_dict[client_dict.keys()[0]]
else:
- cprint("No servers available for arch and current system not "\
+ self.casLog.info("No servers available for arch and current system not "\
"suitable for processing, please run cas-admin -h " \
"for more information")
else:
- cprint("No servers database found, please run cas-admin -h for " \
+ self.casLog.info("No servers database found, please run cas-admin -h for " \
"more information")
sys.exit(1)
# DONE: Possibly handle this exception more gracefully?
except ImportError:
- cprint("Current running machine is not suitable for processing this core " \
+ self.casLog.info("Current running machine is not suitable for processing this core " \
"and http://fedorahosted.org/func is not installed/configured properly.")
- cprint("Finishing job without processing the core, please find a suitable %s "\
+ self.casLog.info("Finishing job without processing the core, please find a suitable %s "\
"machine in order to view this core in crash." % (debugKernelArch,))
else:
import platform
# Define current machine hostname, mainly used for email results.
casProcessMachine = platform.uname()[1]
# The machine is suitable for processing the core through crash.
- cprint("Current machine suitable for processing core, running crash.")
+ self.casLog.info("Current machine suitable for processing core, running crash.")
cmd = os.path.join(self.storagePath,"crash")
# DONE: capture any errors returned from crash when processing core.
cmdPipe = Popen([cmd], stdout=PIPE, stderr=PIPE)
cmdData = cmdPipe.communicate()
- sts, out, err = (cmdPipe.returncode, cmdData[0], cmdData[1])
- if err:
- dprint(err, DPRINT)
+ # pull status code to verify crash even ran to completeness
+ sts, out, err = (cmdPipe.returncode, cmdData[0].strip(),
+ cmdData[1].strip())
+ if sts:
+ self.casLog.debug("crash problem: err: %s, out: %s" % (err, out))
crashOutFile = os.path.join(self.storagePath,"crash.out")
if os.path.isfile(crashOutFile):
- cprint("Crash output processed, sending email to %s" % (self.email,))
+ self.casLog.info("Crash output processed, sending email to %s" % (self.email,))
try:
# Compose email msg of results
msg = "Subject: CAS results for %s\r\n\n" % (self.identifier,)
@@ -229,7 +232,7 @@ class CasApplication(object):
mailServer.quit()
except smtplib.SMTPException, e:
dprint(e)
- cprint("Job on %s complete and located in %s." % (self.filename,
+ self.casLog.info("Job on %s complete and located in %s." % (self.filename,
self.storagePath))
return
diff --git a/cas-admin b/cas-admin
index d441f2c..a852be0 100755
--- a/cas-admin
+++ b/cas-admin
@@ -21,7 +21,7 @@ import sys
import urlparse
from cas.core import CoreBase
-from cas.util import UtilBase, sprint, dprint, cprint
+from cas.util import UtilBase, Logging
from cas.rpmutils import RPMBase
from subprocess import Popen, PIPE
from shutil import rmtree
@@ -36,11 +36,12 @@ KERNELS = config.get("settings","kernels")
RPMS = config.get("settings","rpms")
RPMFILTER = config.get("settings","rpmFilter")
DEBUGS = config.get("settings","debugs")
-DPRINT = config.get("settings","dprint")
+DEBUGLEVEL = config.get("settings","debugLevel")
SERVERS = config.get("settings","servers")
class CasDatabaseHandler(object):
- def __init__(self):
+ def __init__(self, logger):
+ self.casLog = logger
self.util = UtilBase()
if os.path.isfile(RPMS):
self.rpmDB = self.util.load(RPMS)
@@ -59,9 +60,13 @@ class CasDatabaseHandler(object):
# Uses emacs regex -- see `man find`
cmd = ["find", "-L", KERNELS, "-iregex", RPMFILTER]
pipe = Popen(cmd, stdout=PIPE, stderr=PIPE)
+ # setup count for kernels found, mainly for console output
+ count = 0
for line in pipe.stdout:
rpms.append(line.strip())
- sprint("(found) %-100s" % (os.path.basename(line.strip()),))
+ self.casLog.status("(found) %-5d kernel(s)" % (count,))
+ count = count + 1
+ # reset count for further informational messaging
totalRpms = len(rpms)
count = 0
""" Build database out in the form of
@@ -74,7 +79,8 @@ class CasDatabaseHandler(object):
count = count + 1
dst = os.path.join(DEBUGS, str(count))
rpmTool = RPMBase()
- sprint("(extracting) [%d/%d] %-100s" % (count, totalRpms, os.path.basename(x)))
+ self.casLog.status("(extracting) [%d/%d] %-50s" % (count, totalRpms,
+ os.path.basename(x)))
results = rpmTool.extract(x, dst)
# Sort through extracted debug for each type
# e.g. hugemem, PAE, smp, largesmp
@@ -85,14 +91,15 @@ class CasDatabaseHandler(object):
timestamp = stamper.timestamp(debugKernel)
# Build tuple of each debug type
self.rpmDB[x].append((debugKernel, timestamp))
- sprint("(timestamp) %-100s" % (debugKernel,))
+ self.casLog.status("(timestamp) gathering timestamp ..")
self.util.save(self.rpmDB, RPMS)
# Cleanup extracted debugs
rmtree(dst)
return
class CasServerHandler(object):
- def __init__(self):
+ def __init__(self, logger):
+ self.casLog = logger
self.util = UtilBase()
def run(self):
@@ -123,16 +130,17 @@ class CasServerHandler(object):
serverList[arch] = [hostname]
hostname_count = hostname_count + 1
self.util.save(serverList, SERVERS)
- dprint("Server database built with %d server(s) added.\n" % (hostname_count,))
+ self.casLog.debug("Server database built with %d server(s) added.\n" % (hostname_count,))
except ImportError:
- dprint("Please install func (http://fedorahosted.org/func) for " \
- "an automated machine arch population.\n", DPRINT)
+ self.casLog.debug("Please install func (http://fedorahosted.org/func) for " \
+ "an automated machine arch population.\n")
sys.exit(1)
return
class CasAdminApplication(object):
def __init__(self, args):
self.parse_options(args)
+ self.casLog = Logging("/var/log","cas-admin")
def parse_options(self, args):
parser = optparse.OptionParser(usage="casprint [opts] args")
@@ -156,13 +164,13 @@ class CasAdminApplication(object):
os.makedirs(DEBUGS)
if self.buildDB:
- cprint("Starting CAS DB instance.")
- dbHandler = CasDatabaseHandler().run()
+ self.casLog.info("Starting CAS DB instance.")
+ dbHandler = CasDatabaseHandler(self.casLog).run()
elif self.server_init:
- cprint("Building CAS Server DB instance.")
- serverHandler = CasServerHandler().run()
+ self.casLog.info("Building CAS Server DB instance.")
+ serverHandler = CasServerHandler(self.casLog).run()
else:
- cprint("Missing options, please run with --help.")
+ self.casLog.info("Missing options, please run with --help.")
sys.exit(1)
if __name__=="__main__":
diff --git a/cas.conf b/cas.conf
index 950b791..774b4f6 100644
--- a/cas.conf
+++ b/cas.conf
@@ -16,8 +16,8 @@ rpmFilter=.*kernel-debuginfo-[0-9].*\.rpm
# so you could essentially set this to /tmp if space permitted
debugs=/cores/debugs
-# debug print on? (True/False)
-dprint=True
+# debug level (DEBUG, INFO)
+debugLevel=DEBUG
# define work directory
workDirectory=/cores/processed
diff --git a/lib/cas/core.py b/lib/cas/core.py
index 937df39..75c1cb4 100644
--- a/lib/cas/core.py
+++ b/lib/cas/core.py
@@ -63,6 +63,8 @@ class CoreBase(object):
raise CoreException("Can not determine compression format.")
else:
format.append(self.filepath)
+ # TODO: figure out someway to print some status to the screen
+ # during extraction
p = Popen(format, stdout=PIPE, stderr=PIPE)
err = p.stderr.read()
out = p.stdout.read()
diff --git a/lib/cas/util.py b/lib/cas/util.py
index 8086993..59cb65f 100755
--- a/lib/cas/util.py
+++ b/lib/cas/util.py
@@ -21,34 +21,41 @@ import logging
from subprocess import Popen, PIPE, call
-# setup logging
-logFile = '/var/log/cas.log'
-log = logging.getLogger()
-ch = logging.StreamHandler()
-fh = logging.FileHandler(logFile)
-log.addHandler(ch)
-log.addHandler(fh)
-ch_fmt = logging.Formatter("%(message)s")
-fh_fmt = logging.Formatter("%(asctime)s %(process)d (%(levelname)s)\t: %(message)s")
-ch.setFormatter(ch_fmt)
-fh.setFormatter(fh_fmt)
-
-def dprint(msg, debug=True):
- if debug:
- log.setLevel(logging.DEBUG)
- log.debug("[.cas.][debug] :: " +msg)
-
-def sprint(msg):
- """ function to print status messages
- """
- sys.stdout.write("[.cas.] :: " + msg + "\r")
- sys.stdout.flush()
+class Logging(object):
+ def __init__(self, dst, logger_id, debug_level='DEBUG'):
+ self.dst = dst
+ self.logger_id = logger_id
+ self.logfile = logger_id+".log"
+ self.logfile = os.path.join(self.dst, self.logfile)
+ self.log = logging.getLogger(self.logger_id)
+ ch = logging.StreamHandler()
+ # never fail if directory doesn't exist.
+ if not os.path.exists(os.path.dirname(self.logfile)):
+ os.makedirs(os.path.dirname(self.logfile))
+ fh = logging.FileHandler(self.logfile)
+ self.log.addHandler(ch)
+ self.log.addHandler(fh)
+ ch_fmt = logging.Formatter("%(message)s")
+ fh_fmt = logging.Formatter("%(asctime)s %(process)d (%(levelname)s)\t: %(message)s")
+ ch.setFormatter(ch_fmt)
+ fh.setFormatter(fh_fmt)
+ logging_level = {'DEBUG':logging.DEBUG,
+ 'INFO':logging.INFO}
+ self.log.setLevel(logging_level[debug_level])
+
+ def debug(self, msg):
+ self.log.debug("[.cas.][debug] :: %s" % (msg,))
-def cprint(msg):
- """ function to print procedure
- """
- log.setLevel(logging.INFO)
- log.info("[.cas.] :: " +msg)
+ def status(self, msg):
+ """ function to print status messages
+ """
+ sys.stdout.write("[.cas.] :: " + msg + "\r")
+ sys.stdout.flush()
+
+ def info(self, msg):
+ """ function to print procedure
+ """
+ self.log.info("[.cas.] :: %s" % (msg,))
class UtilException(Exception): pass
diff --git a/version b/version
index 88e3999..50c8612 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-0.13 97
+0.13 102
15 years, 4 months