Ejemplo n.º 1
0
 def test_set(self):
     conf = Configuration()
     self.assertFalse(conf.get('Logging', 'trace'))
     conf.set('trace', True, 'Logging')
     self.assertTrue(conf.get('Logging', 'trace'))
     conf.set('trace', False, 'Logging')
     self.assertFalse(conf.get('Logging', 'trace'))
Ejemplo n.º 2
0
 def _log_line_count(self):
     conf = Configuration()
     if os.path.isfile(conf.get('Logging', 'file')):
         fil = open(conf.get('Logging', 'file'), 'r')
         filContent = fil.read().splitlines()
         fil.close()
         del fil
         ctn = 0
         for line in filContent:
             ctn += 1
         del filContent
         del conf
         return ctn
     else:
         del conf
         return 0
Ejemplo n.º 3
0
 def test_defaults(self):
     conf = Configuration()
     self.assertEqual(
         conf.get('Connectivity', 'MongoDB').get('host'), 'localhost')
     self.assertEqual(
         conf.get('Connectivity', 'MongoDB').get('port'), 27017)
     self.assertEqual(conf.get('Logging', 'mode'), 'filesystem')
     self.assertEqual(conf.get('Logging', 'verbose'), False)
     self.assertEqual(conf.get('Logging', 'file'),
                      conf.greaseDir + 'log' + conf.fs_sep + 'grease.log')
     self.assertEqual(conf.get('Configuration', 'dir'),
                      conf.greaseDir + 'etc' + conf.fs_sep)
     self.assertEqual(conf.get('Sourcing', 'dir'),
                      conf.greaseDir + 'etc' + conf.fs_sep)
Ejemplo n.º 4
0
 def test_initialization(self):
     conf = Configuration()
     self.assertTrue(conf.get('Connectivity', 'MongoDB'))
Ejemplo n.º 5
0
 def test_config_is_false_before_startup(self):
     self.assertFalse(Configuration.get('MongoDB', 'host'))
Ejemplo n.º 6
0
 def test_get_section(self):
     conf = Configuration()
     # test for section that should have stuff
     self.assertTrue(conf.get('Notifications'))
     # Section that is empty
     self.assertFalse(conf.get('Additional'))
Ejemplo n.º 7
0
 def test_default(self):
     conf = Configuration()
     self.assertTrue(conf.get('FakeSection', default=True))
     self.assertTrue(conf.get('Connectivity', 'MongoDB'))
Ejemplo n.º 8
0
 def test_no_key(self):
     conf = Configuration()
     self.assertDictEqual({'MongoDB': {
         'host': 'localhost',
         'port': 27017
     }}, conf.get('Connectivity'))
Ejemplo n.º 9
0
class Logging(object):
    """Application Logging for GREASE

    This is the primary configuration source for GREASE logging. All log information will be passed here to
    enable centralized log aggregation

    Attributes:
        _conf (Configuration): This is an instance of the Config to enable configuring loggers
        _logger (logging.Logger): This is the actual logger for GREASE
        _formatter (logging.Formatter): This is the log formatter
        _notifications (Notifications): Notifications instance
        foreground (bool): If set will override config and print all log messages

    """

    _conf = None
    _logger = None
    _formatter = None
    _notifications = None
    foreground = False

    def __init__(self, Config=None):
        if isinstance(Config, Configuration):
            self._conf = Config
        else:
            self._conf = Configuration()
        self._notifications = Notifications(self.getConfig())
        self.ProvisionLoggers()

    def getConfig(self):
        """Getter for Configuration

        Returns:
            Configuration: The loaded configuration object

        """
        return self._conf

    def getNotification(self):
        """Get Notification Class

        Returns:
            Notifications: The current Notifications instance

        """
        return self._notifications

    def TriageMessage(self, message, additional=None, verbose=False, trace=False, notify=False, level=logging.DEBUG):
        """Central message handler

        Args:
            message (str): Message to Log
            additional (object): Additional information to log
            verbose (bool): To be printed if verbose is enabled
            trace (bool): To be printed if trace is enabled
            notify (bool): If true will pass through notification system
            level (int): Log Level

        Returns:
            bool: Log Success

        """
        # first prevent verbose processing
        if verbose and not self._conf.get('Logging', 'verbose'):
            return True
        # prevent trace processing
        if trace and not self._conf.get('Logging', 'trace'):
            return True
        # create a pre-message
        if level is 0:
            preMsg = "TRACE"
        elif level is logging.DEBUG:
            preMsg = "DEBUG"
        elif level is logging.INFO:
            preMsg = "INFO"
        elif level is logging.WARNING:
            preMsg = "WARNING"
        elif level is logging.ERROR:
            preMsg = "ERROR"
        elif level is logging.CRITICAL:
            preMsg = "CRITICAL"
        else:
            preMsg = "UNSET"
        if verbose:
            preMsg = "VERBOSE::{0}".format(preMsg)
        if trace:
            preMsg = "TRACE::{0}".format(preMsg)
        if additional:
            message = "{0}::{1}::{2}::{3}".format(preMsg, self._conf.NodeIdentity, message, additional)
        else:
            message = "{0}::{1}::{2}".format(preMsg, self._conf.NodeIdentity, message)
        # Foreground mode print log messages
        if self._conf.get('Logging', 'foreground') or self.foreground:
            print("{0}::{1}".format(datetime.utcnow(), message))
        # actually log the message
        if level is 0:
            self._logger.log(logging.DEBUG, message)
        else:
            self._logger.log(level, message)
        # notify if needed
        if notify:
            return bool(self._notifications.SendMessage(message, level))
        return True

    def trace(self, message, additional=None, verbose=False, trace=True, notify=False):
        """Trace Messages

        Use this method for logging tracing (enhanced debug) statements

        Args:
            message (str): Message to log
            additional (object): Additional information to log. Note: object must be able to transform to string
            verbose (bool): Print only if verbose mode
            trace (bool): Print only if trace mode
            notify (bool): Run through the notification management system

        Returns:
            bool: Message is logged

        """
        return bool(self.TriageMessage(
            message,
            additional=additional,
            verbose=verbose,
            trace=trace,
            notify=notify,
            level=0
        ))

    def debug(self, message, additional=None, verbose=False, trace=False, notify=False):
        """Debug Messages

        Use this method for logging debug statements

        Args:
            message (str): Message to log
            additional (object): Additional information to log. Note: object must be able to transform to string
            verbose (bool): Print only if verbose mode
            trace (bool): Print only if trace mode
            notify (bool): Run through the notification management system

        Returns:
            bool: Message is logged

        """
        return bool(self.TriageMessage(
            message,
            additional=additional,
            verbose=verbose,
            trace=trace,
            notify=notify,
            level=logging.DEBUG
        ))

    def info(self, message, additional=None, verbose=False, trace=False, notify=False):
        """Info Messages

        Use this method for logging info statements

        Args:
            message (str): Message to log
            additional (object): Additional information to log. Note: object must be able to transform to string
            verbose (bool): Print only if verbose mode
            trace (bool): Print only if trace mode
            notify (bool): Run through the notification management system

        Returns:
            bool: Message is logged

        """
        return bool(self.TriageMessage(
            message,
            additional=additional,
            verbose=verbose,
            trace=trace,
            notify=notify,
            level=logging.INFO
        ))

    def warning(self, message, additional=None, verbose=False, trace=False, notify=False):
        """Warning Messages

        Use this method for logging warning statements

        Args:
            message (str): Message to log
            additional (object): Additional information to log. Note: object must be able to transform to string
            verbose (bool): Print only if verbose mode
            trace (bool): Print only if trace mode
            notify (bool): Run through the notification management system

        Returns:
            bool: Message is logged

        """
        return bool(self.TriageMessage(
            message,
            additional=additional,
            verbose=verbose,
            trace=trace,
            notify=notify,
            level=logging.WARNING
        ))

    def error(self, message, additional=None, verbose=False, trace=False, notify=True):
        """Error Messages

        Use this method for logging error statements

        Args:
            message (str): Message to log
            additional (object): Additional information to log. Note: object must be able to transform to string
            verbose (bool): Print only if verbose mode
            trace (bool): Print only if trace mode
            notify (bool): Run through the notification management system

        Returns:
            bool: Message is logged

        """
        return bool(self.TriageMessage(
            message,
            additional=additional,
            verbose=verbose,
            trace=trace,
            notify=notify,
            level=logging.ERROR
        ))

    def critical(self, message, additional=None, verbose=False, trace=False, notify=True):
        """Critical Messages

        Use this method for logging critical statements

        Args:
            message (str): Message to log
            additional (object): Additional information to log. Note: object must be able to transform to string
            verbose (bool): Print only if verbose mode
            trace (bool): Print only if trace mode
            notify (bool): Run through the notification management system

        Returns:
            bool: Message is logged

        """
        return bool(self.TriageMessage(
            message,
            additional=additional,
            verbose=verbose,
            trace=trace,
            notify=notify,
            level=logging.CRITICAL
        ))

    def ProvisionLoggers(self):
        """Loads Log Handler & Config

        Returns:
            None: Simple loader, Nothing needed

        """
        if self._conf.get('Logging', 'ConfigurationFile'):
            if os.path.isfile(self._conf.get('Logging', 'ConfigurationFile')):
                config.fileConfig(self._conf.get('Logging', 'ConfigurationFile'))
                self._logger = logging.getLogger('GREASE')
            else:
                self.DefaultLogger()
        else:
            self.DefaultLogger()

    def DefaultLogger(self):
        """Default Logging Provisioning

        Returns:
            None: void method to provision class internals

        """
        global GREASE_LOG_HANDLER
        self._logger = logging.getLogger('GREASE')
        self._logger.setLevel(logging.DEBUG)
        self._formatter = logging.Formatter(
            "{"
            "\"timestamp\": \"%(asctime)s.%(msecs)03d\", "
            "\"thread\": \"%(threadName)s\", "
            "\"level\" : \"%(levelname)s\", "
            "\"message\" : \"%(message)s\"}",
            "%Y-%m-%d %H:%M:%S"
        )
        self._formatter.converter = time.gmtime
        if not GREASE_LOG_HANDLER:
            if os.path.isdir(self._conf.greaseDir):
                GREASE_LOG_HANDLER = logging.FileHandler(self._conf.get('Logging', 'file'))
                GREASE_LOG_HANDLER.setLevel(logging.DEBUG)
                GREASE_LOG_HANDLER.setFormatter(self._formatter)
                self._logger.addHandler(GREASE_LOG_HANDLER)
            else:
                GREASE_LOG_HANDLER = logging.StreamHandler()
                GREASE_LOG_HANDLER.setLevel(logging.DEBUG)
                GREASE_LOG_HANDLER.setFormatter(self._formatter)
                self._logger.addHandler(GREASE_LOG_HANDLER)
Ejemplo n.º 10
0
class Notifications(object):
    """Notification Router for third party resources

    This is the class to handle all notifications to third party resources

    Attributes:
        _conf (Configuration): Configuration Object
        hipchat_url (str): This is the hipchat API url
        hipchat_token (str): set this to override the config for the auth token
        hipchat_room (str): set this to override the config for the room

    """

    _conf = None
    # HipChat Configuration
    hipchat_url = "https://api.hipchat.com/v2/room/"
    hipchat_token = None
    hipchat_room = None

    def __init__(self, Config=None):
        if Config and isinstance(Config, Configuration):
            self._conf = Config
        else:
            self._conf = Configuration()

    def SendMessage(self, message, level=DEBUG, channel=None):
        """Send Message to configured channels

        This method is the main point of contact with Notifications in GREASE. This will handle routing to all
        configured channels. Use `level` to define what level the message is. This can impact whether a message is
        sent as well as if the message sent will have special attributes (EX: red text). Use `channel` to route
        around sending to multiple channels if the message traditionally would go to multiple, instead going only
        to the selected one.

        Note:
            if you use the channel argument and the channel is not found you will receive False back

        Args:
            message (str): Message to send
            level (int): Level of message to be sent
            channel (str): Specific channel to notify

        Returns:
            bool: Success of sending

        """
        if channel \
                and 'enabled' in self._conf.get('Notifications', channel, {}) \
                and self._conf.get('Notifications', channel, {}).get('enabled'):
            return bool(self._route_notification(channel, message, level))
        else:
            # Capture object for notification channel statuses
            NotificationStatus = []
            NotificationChannels = self._conf.get('Notifications', default={})  # type: dict
            # Loop through those channels
            for Notifier, Config in NotificationChannels.items():
                # ensure channel is enabled
                if 'enabled' in Config and Config.get('enabled'):
                    # loop through the channels
                    NotificationStatus.append(bool(self._route_notification(Notifier, message, level)))
            # make the list unique
            NotificationStatus = list(set(NotificationStatus))
            if len(NotificationStatus) > 1:
                # we got at least one true and at least one false
                return False
            elif len(NotificationStatus) is 1:
                # return what the categorical state was
                return bool(NotificationStatus[0])
            else:
                # nothing was configured to run return true
                return True

    def _route_notification(self, channel, message, level):
        """Handle actual calling of notification channels

        Args:
            channel (str): Channel to notify
            message (str): Message to send
            level (int): Level to send at

        Returns:
            bool: Method success status

        """
        if channel == "HipChat":
            return self.send_hipchat_message(message, level)
        elif channel == "Slack":
            return self.send_slack_message(message)
        else:
            return False

    def send_hipchat_message(self, message, level, color=None):
        """Send a hipchat message

        Args:
            message (str): Message to send to hipchat
            level (int): message level
            color (str): color of message

        Returns:
            bool: API response status

        """
        if not color:
            if level is DEBUG:
                color = 'grey'
            elif level is INFO:
                color = 'purple'
            elif level is WARNING:
                color = 'yellow'
            elif level is ERROR:
                color = 'red'
            elif level is CRITICAL:
                color = 'red'
            else:
                color = 'grey'
        if self.hipchat_room and self.hipchat_token:
            url = "{0}{1}/notification?auth_token={2}".format(
                self.hipchat_url,
                self.hipchat_room,
                self.hipchat_token
            )
        else:
            url = "{0}{1}/notification?auth_token={2}".format(
                self.hipchat_url,
                self._conf.get('Notifications', 'HipChat').get('room'),
                self._conf.get('Notifications', 'HipChat').get('token')
            )
        try:
            response = requests.post(
                url=url,
                data={
                    'message': message,
                    'color': color
                },
                verify=False
                )
            if response.status_code == 204:
                return True
            else:
                return False
        except HTTPError:
            return False

    def send_slack_message(self, message):
        """Send a slack message to slack channel using webhook url in the configuration

        Args:
            message (str): Message to send to Slack

        Returns:
            bool: API response status

        """

        webhook_url = self._conf.get('Notifications', 'Slack').get('webhookURL')
        slack_data = {'text': message}

        try:
            response = requests.post(
                webhook_url, data=json.dumps(slack_data),
                headers={'Content-Type': 'application/json'}
            )
            return True
        except HTTPError:
            return False
Ejemplo n.º 11
0
class Mongo(object):
    """MongoDB Connection Class

    Attributes:
        _client (pymongo.MongoClient): The actual PyMongo Connection
        _config (Configuration): Configuration Object

    """

    _client = None
    _config = None

    def __init__(self, Config=None):
        if Config and isinstance(Config, Configuration):
            self._config = Config
        else:
            self._config = Configuration()
        self._client = self._generate_client()

    def Client(self):
        """get the connection client

        Returns:
            pymongo.MongoClient: Returns the mongoDB connection client

        """
        return self._client

    def Close(self):
        """Close PyMongo Connection

        Returns:
            None: Void Method to close connection

        """
        self._client.close()

    def _generate_client(self):
        """Creates a PyMongo Client

        Returns:
            pymongo.MongoClient: Mongo Connection

        """
        mongoConf = self._config.get('Connectivity', 'MongoDB')  # type: dict
        if mongoConf.get('username') and mongoConf.get('password'):
            return pymongo.MongoClient(
                "mongodb://{0}:{1}@{2}:{3}/{4}".format(
                    mongoConf.get('username', ''),
                    mongoConf.get('password', ''),
                    mongoConf.get('host', 'localhost'),
                    mongoConf.get('port', 27017),
                    mongoConf.get('db', 'grease')
                ),
                w=1
            )
        else:
            return pymongo.MongoClient(
                host=mongoConf.get('host', 'localhost'),
                port=mongoConf.get('port', 27017),
                w=1
            )