Example #1
0
    def _eventit(self, agent, data):
        """Send a read-only password event failed/okay event if
           the user has done setup with a chance to
           configure one and appropriate."""

        # user '0', likely 'palette'
        entry = UserProfile.get(self.server.environment.envid, 0)
        # Potentially send an event only after the user has
        # finished with the "Setup" page (the passowrd will then be
        # there).

        if not entry.hashed_password:
            return

        notification = self.server.notifications.get("dbreadonly")

        if success(data):
            if notification.color == 'red':
                adata = agent.todict()
                self.server.event_control.gen(
                    EventControl.READONLY_DBPASSWORD_OKAY, adata)
                notification.modification_time = func.now()
                notification.color = 'green'
                notification.description = None
                meta.Session.commit()
        else:
            # Failed
            if notification.color != 'red':
                if data['error'].find(
                    "A password is required for this connection.") != -1 or \
                    data['error'].find(agent.odbc.READONLY_ERROR_TEXT) \
                                                                    != -1 or \
                    data['error'].find("password authentication failed") != -1:

                    adata = agent.todict()
                    self.server.event_control.gen(
                        EventControl.READONLY_DBPASSWORD_FAILED, adata)
                    notification.modification_time = func.now()
                    notification.color = 'red'
                    notification.description = None
                    meta.Session.commit()
            return
Example #2
0
    def send(self, event_entry, data, recipient=None, eventid=None):
        """Send an alert.
            Arguments:
                key:    The key to look up.
                data:   A Dictionary with the event information.
        """
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-return-statements

        subject = event_entry.email_subject
        if subject == None:
            subject = event_entry.subject

        if subject.find("%") != -1:
            # Use the data dict for template substitution.
            try:
                subject = subject % data
            except (ValueError, KeyError) as ex:
                subject = "Email Template subject conversion failure: " + \
                    str(ex) + \
                    "subject: " + subject + \
                    ", data: " + str(data)

        message = event_entry.email_message
        if message:
            try:
                mako_template = Template(message)
                message = mako_template.render(**data)
            except StandardError:
                message = "Email mako template message conversion failure: " + \
                    exceptions.text_error_template().render() + \
                    "\ntemplate: " + message + \
                        "\ndata: " + str(data)
        else:
            message = self.make_default_message(event_entry, subject, data)

        if not message:
            # message is empty, set it to be the subject
            message = subject

        if recipient:
            # Force to only one test recipient.
            # It is sent even if alerts are disabled.
            to_emails = [recipient]
        else:
            if not self.system[SystemKeys.ALERTS_ENABLED]:
                logger.info("Alerts disabled.  Not sending: Subject: %s, %s",
                            subject, message)
                return

            to_emails = []

            if event_entry.publisher_visibility:
                to_emails = self.publisher_email(data)
            if event_entry.admin_visibility:
                to_emails += self.admin_emails(event_entry)

        # Remove any duplicates
        to_emails = list(set(to_emails))

        bcc = None
        if self.system[SystemKeys.ALERTS_ADMIN_ENABLED] and not recipient:
            # Get the diagnostics email and bcc it there if it exists.
            entry = UserProfile.get(self.envid, 0)
            if entry and entry.email != None and entry.email != "":
                bcc = [entry.email]

        if not to_emails and not bcc:
            logger.debug(
                "No admin users exist with enabled email addresses. "
                "Not sending: Subject: %s, Message: %s", subject, message)
            return

        # Send only PHONE-HOME related events if their palette license
        # has expired.
        if event_entry.key not in [
                EventControl.PHONE_HOME_FAILED, EventControl.PHONE_HOME_OK,
                EventControl.EMAIL_TEST
        ]:
            entry = Domain.getone()
            if entry.expiration_time and \
                            datetime.utcnow() > entry.expiration_time:
                logger.debug(
                    "License expired. " +
                    "Not sending: Subject: %s, Message: %s", subject, message)
                return

            if entry.contact_time:
                silence_time = (datetime.utcnow() - \
                                        entry.contact_time).total_seconds()
                max_silence_time = self.system[SystemKeys.MAX_SILENCE_TIME]
                if silence_time > max_silence_time and max_silence_time != -1:
                    logger.debug(
                        "Phonehome contact time is %d > %d. " +
                        "Not sending: Subject: %s, Message: %s", silence_time,
                        max_silence_time, subject, message)
                    return

        if self.email_limit_manager.email_limit_reached(event_entry, eventid):
            return

        sendit = True
        #        print '\n------------event key is', event_entry.key
        if self.system[SystemKeys.EMAIL_MUTE_RECONNECT_SECONDS]:
            # Potentially mute the connect or reconnect emails.
            if event_entry.key == EventControl.AGENT_DISCONNECT:
                self._mute_dis_check(data, to_emails, bcc, subject, message)
                # If the event is emailed, it is done there,
                # after a delay
                return

            elif event_entry.key in [
                    EventControl.AGENT_COMMUNICATION,
                    EventControl.INIT_STATE_STARTED,
                    EventControl.INIT_STATE_STOPPED,
                    EventControl.INIT_STATE_DEGRADED
            ]:
                sendit = self._mute_reconn_check(data)

        if sendit:
            self._do_send(to_emails, bcc, subject, message)
Example #3
0
    def gen(self, key, data=None, userid=None, site_id=None, timestamp=None):
        # pylint: disable=too-many-arguments
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-branches
        """Generate an event.
            Arguments:
                key:    The key to look up.

                data:   A Dictionary with all of the event information.
                        Recognized keys:
                            - From http response:
                                stdout
                                stderr
                                xid
                                pid
                                exit-status
                                run-status
                                timestamp
                            - Sometimes added:
                                error
                                info
                            - Available from AgentConnection:
                                displayname
                                agent_type
                                uuid
                                auth, which has:
                                    hostname
                                    ip-address
                                    version
                                    listen-port
                                    install-dir
        """

        if data == None:
            data = {}

        if 'enabled' in data and not data['enabled']:
            logger.debug("Agent is disabled so no event will be " + \
                         "generated.  key: %s, data: %s", key, data)
            return

        event_entry = self.get_event_control_entry(key)
        if event_entry:
            subject = event_entry.subject
            event_description = event_entry.event_description
        else:
            logger.error("No such event key: %s. data: %s\n", key, str(data))
            return

        # add all system table entries to the data dictionary.
        data = dict(data.items() + \
                    self.system.todict(include_defaults=True).items())

        logger.debug(key + " DATA: " + str(data))

        if 'exit-status' in data:
            data['exit_status'] = data['exit-status']
            del data['exit-status']

        # FIXME: remove when browser-aware timezone support is available.
        if timestamp is None:
            timestamp = datetime.datetime.now(tz=tz.tzlocal())
            logger.debug(key + " timestamp : " + timestamp.strftime(DATEFMT))
        data['timestamp'] = timestamp.strftime(DATEFMT)

        # The userid for other events is the Palette "userid".
        profile = None
        if not 'username' in data and userid != None:
            profile = UserProfile.get(self.envid, userid)

        if not profile is None:
            data['username'] = profile.display_name()
            data['userid'] = profile.userid
            if profile.email:
                data['email'] = profile.email

        if userid:
            # userid passed to us has higher precedence than any
            # lookup we did, above.
            data['userid'] = userid

        if not 'username' in data:
            data['username'] = mako.runtime.UNDEFINED

        data['event_type'] = event_entry.event_type
        data['event_type_label'] = event_entry.event_type_label
        data['event_label'] = event_entry.event_label
        data['event_label_desc'] = event_entry.event_label_desc
        data['admin_visibility'] = event_entry.admin_visibility
        data['publisher_visiblity'] = event_entry.publisher_visibility

        # set server-url(s)
        data['server_url'] = self.system[SystemKeys.SERVER_URL]

        url = self.server.public_url()
        if url:
            data['tableau_server_url'] = url

        if not 'environment' in data:
            data['environment'] = self.server.environment.name

        if 'site_id' in data and 'site' not in data:
            site = Site.get_name_by_id(self.envid, data['site_id'])
            if not site is None:
                data['site'] = site
        if 'project_id' in data and 'project' not in data:
            project = Project.get_name_by_id(self.envid, data['project_id'])
            if not project is None:
                data['project'] = project

        # Create the row to get the eventid before doing subject/description
        # substitution.
        session = meta.DBSession()
        entry = EventEntry(complete=False, key='incomplete')
        # set the timestamp here in case it has tzinfo.
        entry.timestamp = timestamp
        session.add(entry)
        session.commit()

        data['eventid'] = entry.eventid

        # Use the data dict for template substitution.
        try:
            subject = subject % data
        except (ValueError, KeyError) as ex:
            subject = "Template subject conversion failure: " + str(ex) + \
                      "subject: " + subject + \
                      ", data: " + str(data)

        if event_description:
            try:
                mako_template = Template(event_description,
                                         default_filters=['h'])
                event_description = mako_template.render(**data)
            except MakoException:
                event_description = \
                    "Mako template message conversion failure: " + \
                        exceptions.text_error_template().render() + \
                            "\ntemplate: " + event_description + \
                            "\ndata: " + str(data)
            except TypeError as ex:
                event_description = \
                    "Mako template message conversion failure: " + \
                    str(ex) + \
                        "\ntemplate: " + event_description + \
                        "\ndata: " + str(data)
        else:
            event_description = self.make_default_description(data)

        event_description = re.sub("(\n|\r\n){3,}", "\n\n", event_description)
        if not event_description.endswith("\n"):
            event_description = event_description + "\n"

        if self.server.event_debug:
            event_description = event_description + "--------\n" + str(data)

        # FIXME: remove when browser-aware timezone support is available.
        if timestamp.tzinfo is None:
            # if not timezone is specified, assume UTC.
            summary = utc2local(timestamp).strftime(DATEFMT)
        else:
            summary = timestamp.strftime(DATEFMT)

        # Log the event to the database
        entry.complete = True
        entry.key = key
        entry.envid = self.envid
        entry.title = subject
        entry.description = event_description
        entry.level = event_entry.level
        entry.icon = event_entry.icon
        entry.color = event_entry.color
        entry.event_type = event_entry.event_type
        entry.summary = summary
        entry.userid = userid
        entry.site_id = site_id
        #entry.timestamp = timestamp

        session.merge(entry)
        session.commit()

        if not event_entry.send_email:
            return

        try:
            self.alert_email.send(event_entry, data, eventid=entry.eventid)
        except StandardError:
            exc_traceback = sys.exc_info()[2]
            tback = ''.join(traceback.format_tb(exc_traceback))
            report = "Error: %s.  Traceback: %s" % (sys.exc_info()[1], tback)

            logger.error(
                "alert_email: Failed for event '%s', '"
                "data '%s'.  Will not send email. %s", event_entry.key,
                str(data), report)