????

Your IP : 18.227.52.11


Current Path : /usr/bin/
Upload File :
Current File : //usr/bin/cas-admin

#!/usr/bin/python
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

""" cas-admin - fingerprinting utility for cas
"""
import os
import ConfigParser
import optparse
import sys
import urlparse
import datetime
import calendar
import paramiko

from cas.core import CoreBase
from cas.util import UtilBase, Logging
from cas.rpmutils import RPMBase
from cas.db import CasStorage, CasStorageException
from cas.cas_subprocess import Popen, PIPE
from cas.cas_shutil import rmtree

if sys.version_info[:2] < (2,3):
    raise SystemExit("Python >= 2.3 required")

# Read in configuration
config = ConfigParser.ConfigParser()
config.read("/etc/cas.conf")
settings = {}
if config.has_section("settings"):
    for opt, val in config.items("settings"):
        settings[opt.upper()] = val

# read maintenance options
PURGELIMIT = config.get("maintenance","purgeLimit")
AUTOPURGE = config.getboolean("maintenance","autoPurge")

# advance options
BUFFERSIZE=None
if config.has_option("advanced", "buffersize"):
    BUFFERSIZE=config.get("advanced", "buffersize")

class CasDatabaseHandler(object):
    def __init__(self, logger):
        self.casLog = logger
        self.util = UtilBase()
        # setup database connection
        self.first_run = False
        if not os.path.isfile(settings["DATABASE"]):
            self.first_run = True
        self.db = CasStorage(settings["DATABASE"])
        self.db.connect()
        if self.first_run:
            self.db.buildTable()

    def run(self):
        # Uses emacs regex -- see `man find`
        # TODO: rework kernel filtering to expand scope
        #       beyond just debuginfo rpms.
        cmd = ["find", "-L", settings["KERNELS"], "-iregex", settings["RPMFILTER"]]
        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:
            self.db.addDebuginfoRPM(line.strip())
            self.casLog.status("(found) %-5d kernel(s)" % (count,))
            count = count + 1
        # query database for debuginfo rpms
        rpms = self.db.getAllDebuginfoRPM()
        for id, rpm in rpms:
            # temporary storage path in form of DEBUGS/COUNT
            dst = os.path.join(settings["DEBUGS"], str(count))
            if not os.path.isdir(dst):
                os.makedirs(dst)
            rpmTool = RPMBase()
            self.casLog.status("(extracting) %-50s" % (os.path.basename(rpm),))
            results = rpmTool.extract(rpm, dst)
            # Sort through extracted debug for each type
            # e.g. hugemem, PAE, smp, largesmp
            for item in results:
                vmlinux = item.strip()
                stamper = CoreBase()
                debugKernel = os.path.normpath(vmlinux)
                timestamp = stamper.timestamp(debugKernel, BUFFERSIZE)
                # add rpm id, debug, timestamp to database
                self.db.addTimestamp(id, debugKernel, timestamp)
            # Cleanup extracted debugs
            rmtree(dst)
        self.casLog.info("Timestamp database built.") 
        return

class CasServerHandler(object):
    def __init__(self, logger):
        self.casLog = logger
        self.util = UtilBase()
        # setup database connection
        self.first_run = False
        if not os.path.isfile(settings["DATABASE"]):
            self.first_run = True
        self.db = CasStorage(settings["DATABASE"])
        self.db.connect()
        if self.first_run:
            self.db.buildTable()

    def run(self):
        host = None
        port = 22
        hostname_count = 0
        ssh_obj = paramiko.SSHClient()
        ssh_obj.load_host_keys(os.path.expanduser("~/.ssh/known_hosts"))
        for server in ssh_obj.get_host_keys().keys():
            server = server.strip()
            # here we test for ports and apply accordingly
            if ':' in server:
                server, port = server.split(':')
                # ssh keys place [host] when defining servers with ports
                server = server[1:-1]
            try:
                ssh_obj.connect(server, port=port, username=settings["CASUSER"])
            except paramiko.AuthenticationException, e:
                raise SystemExit(self.casLog.debug("Failed to connect to %s: %s" % (server,e)))
            stdin, stdout, stderr = ssh_obj.exec_command("/bin/uname -m")
            if stderr:
                self.casLog.debug(stderr)
            # clean up arch string
            for i in stdout.readlines():
                arch = i.strip()
            self.db.addServer(server, port, arch)
            hostname_count = hostname_count + 1
        self.casLog.info("Server database built with %d server(s) added." % (hostname_count,))
        return
        
class PurgeHandler(object):
    def __init__(self, purgeDays, logger):
        self.purgeDataDays = purgeDays
        self.casLog = logger
        self.util = UtilBase()
        self.todaysDate = datetime.date.today()
        
    def run(self):
        # create date of timedelta
        cutOffDate = self.todaysDate - datetime.timedelta(days=self.purgeDataDays)
        self.casLog.debug(cutOffDate)
        # Start of purging data
        for root, dirs, files in os.walk(settings["WORKDIRECTORY"]):
            for d in dirs:
                dirpath = os.path.join(root,d)
                # pull out date from directory structure and trim it to
                # (year, month, day)
                searchDate = self.util.regexSearch('(\d{4})\.(\d+)\.(\d+)', dirpath)
                if searchDate:
                    self.casLog.debug('found %s' % (searchDate,))
                    (year, month, day) = searchDate.split('.')
                    # create our datetime object so we can do some arithmetic
                    dirDate = datetime.date(int(year), int(month), int(day))
                    self.casLog.debug(dirDate)
                    if dirDate < cutOffDate:
                        self.casLog.debug('Should purge old directories, %s' % (dirpath,))
                        rmtree(dirpath)

class CasAdminApplication(object):
    def __init__(self, args):
        self.parse_options(args)
        self.casLog = Logging("/var/log","cas-admin", settings["DEBUGLEVEL"])

    def parse_options(self, args):
        parser = optparse.OptionParser(usage="cas-admin [opts] args")
        parser.add_option("-b","--build", dest="buildDB",
                          help="Build CAS DB", action="store_true",
                          default=False)
        parser.add_option("-s","--server", dest="server_init",
                          help="Build SERVER DB", action="store_true",
                          default=False)
        parser.add_option("-p","--purge", dest="purgeData",
                          help="Purge files default 90 days, customize with -d",
                          action="store_true", default=False)
        parser.add_option("-d","--days", dest="purgeDataDays",
                          help="Set how many days back to purge data")
        (self.opts, args) = parser.parse_args()
        self.buildDB = self.opts.buildDB
        self.server_init = self.opts.server_init
        self.purgeData = self.opts.purgeData
        self.purgeDataDays = self.opts.purgeDataDays

    def run(self):
        """ Make sure necessary directories and configuration is setup
        prior to running the fingerprint
        """
        if os.getuid() is not 0:
            raise RuntimeError, "You must be root(0), instead you are id(%d)" % (os.getuid())
        if not os.path.isdir(os.path.dirname(settings["DATABASE"])):
            os.makedirs(os.path.dirname(settings["DATABASE"]))
        if not os.path.isdir(settings["DEBUGS"]):
            os.makedirs(settings["DEBUGS"])

        # if autopurge is enabled lets clean up some stale data
        if AUTOPURGE:
            self.casLog.debug('Autopurge enabled, purging stale data')
            purgeHandler = PurgeHandler(int(PURGELIMIT), self.casLog).run()

        if self.purgeData:
            ans = raw_input("You are about to purge data, is this what you " \
                                "really want to do? [Y/y/N/n]: ")
            if ans=='Y' or ans=='y':
                if not self.purgeDataDays:
                    self.purgeDataDays = PURGELIMIT
                self.casLog.info("Beginning Purge going back %s day(s)" % (self.purgeDataDays,))
                purgeHandler = PurgeHandler(int(self.purgeDataDays), self.casLog).run()
                raise SystemExit(self.casLog.info("Purge finished"))
            else:
                raise SystemExit(self.casLog.info("Purge cancelled"))

        if self.buildDB:
            self.casLog.info("Starting CAS DB instance.")
            dbHandler = CasDatabaseHandler(self.casLog).run()
        elif self.server_init:
            self.casLog.info("Building CAS Server DB instance.")
            if not os.path.isfile(os.path.expanduser("~/.ssh/known_hosts")):
                raise SystemExit(self.casLog.info("Unable to read ssh hosts keys, " \
                    "please make sure ssh client is configured properly"))
            else:
                serverHandler = CasServerHandler(self.casLog).run()
        else:
            raise SystemExit(self.casLog.info("Missing options, please run with --help."))

if __name__=="__main__":
    app = CasAdminApplication(sys.argv[1:])
    sys.exit(app.run())