2017-05-31 00:21:23 -04:00
|
|
|
'''
|
2017-06-02 02:26:37 -04:00
|
|
|
Sets up root logger for whole program, including console, gluster, and gmail
|
|
|
|
|
2017-05-30 02:11:15 -04:00
|
|
|
Logger conventions
|
2017-05-31 00:21:23 -04:00
|
|
|
- CRITICAL: for things that cause crashes. only level with gmail
|
2017-05-30 02:11:15 -04:00
|
|
|
- ERROR: for things that cause startup/shutdown issues
|
|
|
|
- WARNING: for recoverable issues that may cause future problems
|
|
|
|
- INFO: state changes and sensor readings
|
|
|
|
- DEBUG: all extraneous crap
|
2017-05-31 00:21:23 -04:00
|
|
|
'''
|
|
|
|
|
2017-06-02 02:26:37 -04:00
|
|
|
import logging, os
|
|
|
|
from subprocess import run, PIPE, CalledProcessError
|
|
|
|
from logging.handlers import TimedRotatingFileHandler, SMTPHandler
|
|
|
|
from auxilary import mkdirSafe
|
|
|
|
|
2017-05-29 21:53:08 -04:00
|
|
|
def _formatConsole(gluster = False):
|
2017-05-31 00:21:23 -04:00
|
|
|
'''
|
|
|
|
formats console output depending on whether we have gluster
|
|
|
|
'''
|
2017-05-29 21:53:08 -04:00
|
|
|
c = '' if gluster else '[CONSOLE ONLY] '
|
2017-05-29 21:48:01 -04:00
|
|
|
fmt = logging.Formatter('[%(name)s] [%(levelname)s] ' + c + '%(message)s')
|
2017-06-03 18:11:58 -04:00
|
|
|
console.setFormatter(fmt)
|
2017-05-29 21:48:01 -04:00
|
|
|
|
2017-05-29 21:15:38 -04:00
|
|
|
class GlusterFSHandler(TimedRotatingFileHandler):
|
2017-05-31 00:21:23 -04:00
|
|
|
'''
|
|
|
|
Logic to mount timed rotating file within a gluster volume. Note that this
|
|
|
|
class will mount itself automatically. Note that the actual filepaths for
|
2017-06-03 18:37:24 -04:00
|
|
|
logging are hardcoded here
|
2017-05-31 00:21:23 -04:00
|
|
|
'''
|
2017-05-23 01:18:46 -04:00
|
|
|
def __init__(self, server, volume, mountpoint, options=None):
|
2017-05-22 01:44:16 -04:00
|
|
|
if not os.path.exists(mountpoint):
|
|
|
|
raise FileNotFoundError
|
|
|
|
|
2017-06-02 00:15:05 -04:00
|
|
|
self.mountpoint = mountpoint
|
2017-05-29 21:15:38 -04:00
|
|
|
self._server = server
|
|
|
|
self._volume = volume
|
|
|
|
self._options = options
|
|
|
|
|
|
|
|
self._mount()
|
2017-05-31 00:54:00 -04:00
|
|
|
|
|
|
|
logdest = mountpoint + '/logs'
|
|
|
|
mkdirSafe(logdest, logger)
|
2017-05-29 21:15:38 -04:00
|
|
|
|
|
|
|
super().__init__(logdest + '/pyledriver-log', when='midnight')
|
|
|
|
|
|
|
|
fmt = logging.Formatter('[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s')
|
|
|
|
self.setFormatter(fmt)
|
|
|
|
|
|
|
|
def _mount(self):
|
2017-06-02 00:15:05 -04:00
|
|
|
if os.path.ismount(self.mountpoint):
|
2017-05-31 00:21:23 -04:00
|
|
|
# this assumes that the already-mounted device is the one intended
|
2017-06-02 00:15:05 -04:00
|
|
|
logger.warning('Device already mounted at {}'.format(self.mountpoint))
|
2017-05-23 01:18:46 -04:00
|
|
|
else:
|
2017-05-29 21:15:38 -04:00
|
|
|
dst = self._server + ':/' + self._volume
|
2017-06-02 00:15:05 -04:00
|
|
|
cmd = ['mount', '-t', 'glusterfs', dst, self.mountpoint]
|
2017-05-29 21:15:38 -04:00
|
|
|
if self._options:
|
|
|
|
cmd[1:1] = ['-o', self._options]
|
2017-05-23 01:18:46 -04:00
|
|
|
self._run(cmd)
|
2017-06-02 00:15:05 -04:00
|
|
|
self.isMounted = True
|
2017-05-22 01:44:16 -04:00
|
|
|
|
2017-05-29 21:15:38 -04:00
|
|
|
def _unmount(self):
|
2017-06-02 00:15:05 -04:00
|
|
|
self._run(['umount', self.mountpoint])
|
|
|
|
self.isMounted = False
|
2017-05-22 01:44:16 -04:00
|
|
|
|
|
|
|
def _run(self, cmd):
|
|
|
|
try:
|
|
|
|
run(cmd, check=True, stdout=PIPE, stderr=PIPE)
|
|
|
|
except CalledProcessError as e:
|
2017-05-29 21:15:38 -04:00
|
|
|
stderr = e.stderr.decode('ascii').rstrip()
|
2017-05-31 00:26:28 -04:00
|
|
|
logger.error(stderr)
|
2017-05-23 01:43:39 -04:00
|
|
|
raise SystemExit
|
2017-05-29 21:15:38 -04:00
|
|
|
|
|
|
|
def close(self):
|
2017-05-31 00:21:23 -04:00
|
|
|
'''
|
|
|
|
Close file and dismount (must be in this order). Called when
|
|
|
|
'removeHandler' is invoked
|
|
|
|
'''
|
|
|
|
TimedRotatingFileHandler.close(self)
|
2017-05-29 21:15:38 -04:00
|
|
|
self._unmount()
|
2017-05-29 21:53:08 -04:00
|
|
|
|
2017-05-31 00:21:23 -04:00
|
|
|
'''
|
2017-06-02 02:26:37 -04:00
|
|
|
Init sequence (order is very essential)
|
2017-05-31 00:21:23 -04:00
|
|
|
'''
|
2017-06-02 02:26:37 -04:00
|
|
|
# 1) init console output (this will go to journald) and format as console only
|
2017-05-31 00:21:23 -04:00
|
|
|
console = logging.StreamHandler()
|
|
|
|
_formatConsole(gluster = False)
|
|
|
|
|
|
|
|
rootLogger = logging.getLogger()
|
|
|
|
rootLogger.setLevel(logging.DEBUG)
|
|
|
|
rootLogger.addHandler(console)
|
|
|
|
|
2017-06-02 02:26:37 -04:00
|
|
|
# 2) init the module level logger so we can log anything that happens as we build the other loggers
|
2017-05-31 00:26:28 -04:00
|
|
|
logger = logging.getLogger(__name__)
|
2017-05-31 00:21:23 -04:00
|
|
|
|
2017-06-03 18:37:24 -04:00
|
|
|
# 3) init glusterfs, any errors here will go to console output
|
|
|
|
from config import configFile
|
2017-06-03 18:11:58 -04:00
|
|
|
glusterConf = configFile['gluster']
|
2017-05-22 02:32:19 -04:00
|
|
|
|
2017-06-03 18:11:58 -04:00
|
|
|
if glusterConf['server'] != 'example.com':
|
|
|
|
gluster = GlusterFSHandler(**glusterConf)
|
|
|
|
rootLogger.addHandler(gluster)
|
|
|
|
_formatConsole(gluster = True)
|
|
|
|
else:
|
|
|
|
logger.error('Gluster not configured. Please update config/pyledriver.yaml')
|
|
|
|
raise SystemExit
|
2016-12-30 02:51:56 -05:00
|
|
|
|
2017-06-03 18:37:24 -04:00
|
|
|
# 4) import gmail, this must come here as it uses loggers for some of its setup
|
2017-05-31 00:41:42 -04:00
|
|
|
from gmail import gmail, GmailHandler
|
2017-05-31 00:21:23 -04:00
|
|
|
|
2017-06-03 18:37:24 -04:00
|
|
|
# 5) init gmail handler
|
2017-05-31 00:21:23 -04:00
|
|
|
gmail = GmailHandler(gmail['username'], gmail['passwd'], gmail['recipientList'],
|
|
|
|
'harrison4hegemon - critical error')
|
|
|
|
gmail.setLevel(logging.CRITICAL)
|
|
|
|
rootLogger.addHandler(gmail)
|
|
|
|
|
|
|
|
'''
|
|
|
|
Clean up
|
|
|
|
'''
|
2017-05-29 21:48:01 -04:00
|
|
|
def unmountGluster():
|
2017-06-03 18:11:58 -04:00
|
|
|
try:
|
|
|
|
rootLogger.removeHandler(gluster)
|
|
|
|
_formatConsole(gluster = False)
|
|
|
|
except NameError:
|
|
|
|
pass
|