Example #1
0
    def _getSession(self, content):
        traphost = content['action_destination']
        port = content['port']
        destination = '%s:%s' % (traphost, port)

        if not traphost or port <= 0:
            log.error("%s: SNMP trap host information %s is incorrect ",
                      destination)
            return None

        community = content['community']
        version = content['version']

        session = self._sessions.get(destination, None)
        if session is None:
            log.debug("Creating SNMP trap session to %s", destination)

            # Test that the hostname and port are sane.
            try:
                getaddrinfo(traphost, port)
            except Exception:
                raise ActionExecutionException(
                    "The destination %s is not resolvable." % destination)

            session = netsnmp.Session(
                ('-%s' % version, '-c', community, destination))
            session.open()
            self._sessions[destination] = session

        return session
Example #2
0
    def executeBatch(self, notification, signal, targets):
        log.debug("Executing %s action for targets: %s", self.name, targets)
        self.setupAction(notification.dmd)

        data = _signalToContextDict(signal, self.options.get('zopeurl'), notification, self.guidManager)
        if signal.clear:
            log.debug('This is a clearing signal.')
            subject = processTalSource(notification.content['clear_subject_format'], **data)
            body = processTalSource(notification.content['clear_body_format'], **data)
        else:
            subject = processTalSource(notification.content['subject_format'], **data)
            body = processTalSource(notification.content['body_format'], **data)

        log.debug('Sending this subject: %s' % subject)
        log.debug('Sending this body: %s' % body)

        plain_body = MIMEText(self._stripTags(body))
        email_message = plain_body

        if notification.content['body_content_type'] == 'html':
            email_message = MIMEMultipart('related')
            email_message_alternative = MIMEMultipart('alternative')
            email_message_alternative.attach(plain_body)

            html_body = MIMEText(body.replace('\n', '<br />\n'))
            html_body.set_type('text/html')
            email_message_alternative.attach(html_body)

            email_message.attach(email_message_alternative)

        host = notification.content['host']
        port = notification.content['port']
        user = notification.content['user']
        password = notification.content['password']
        useTls = notification.content['useTls']
        email_from = notification.content['email_from']

        email_message['Subject'] = subject
        email_message['From'] = email_from
        email_message['To'] = ','.join(targets)
        email_message['Date'] = formatdate(None, True)

        result, errorMsg = sendEmail(
            email_message,
            host, port,
            useTls,
            user, password
        )

        if result:
            log.debug("Notification '%s' sent emails to: %s",
                     notification.id, targets)
        else:
            raise ActionExecutionException(
                "Notification '%s' FAILED to send emails to %s: %s" %
                (notification.id, targets, errorMsg)
            )
Example #3
0
    def executeOnTarget(self, notification, signal, target):
        self.setupAction(notification.dmd)

        log.debug('Executing action: %s on %s', self.name, target)

        if signal.clear:
            command = notification.content['clear_body_format']
        else:
            command = notification.content['body_format']

        log.debug('Executing this command: %s', command)

        actor = signal.event.occurrence[0].actor
        device = None
        if actor.element_uuid:
            device = self.guidManager.getObject(actor.element_uuid)

        component = None
        if actor.element_sub_uuid:
            component = self.guidManager.getObject(actor.element_sub_uuid)

        user_env_format = notification.content['user_env_format']
        env = dict( envvar.split('=') for envvar in user_env_format.split(';') if '=' in envvar)

        environ = {'dev': device, 'component': component, 'dmd': notification.dmd,
                   'env': env}
        data = _signalToContextDict(signal, self.options.get('zopeurl'), notification, self.guidManager)
        environ.update(data)

        if environ.get('evt', None):
            environ['evt'] = self._escapeEvent(environ['evt'])

        if environ.get('clearEvt', None):
            environ['clearEvt'] = self._escapeEvent(environ['clearEvt'])

        environ['user'] = getattr(self.dmd.ZenUsers, target, None)

        try:
            command = processTalSource(command, **environ)
        except Exception:
            raise ActionExecutionException('Unable to perform TALES evaluation on "%s" -- is there an unescaped $?' % command)

        log.debug('Executing this compiled command: "%s"' % command)
        _protocol = EventCommandProtocol(command)

        log.debug('Queueing up command action process.')
        self.processQueue.queueProcess(
            '/bin/sh',
                ('/bin/sh', '-c', command),
            env=environ['env'],
            processProtocol=_protocol,
            timeout=int(notification.content['action_timeout']),
            timeout_callback=_protocol.timedOut
        )
 def _processTalExpression(self, value, environ):
     if type(value) is str or type(value) is unicode:
         if '${' not in value:
             return value
         try:
             return processTalSource(value, **environ)
         except Exception:
             raise ActionExecutionException(
                 'Unable to perform TALES evaluation on "%s" -- is there an unescaped $?'
                 % value)
     else:
         return value
Example #5
0
    def processEventFields(self, data, content, name):
        log.debug('[research] process TAL expressions')

        try:
            content = processTalSource(content, **data)
            log.debug('[research] %s : %s' % (name, content))
        except Exception:
            log.debug('[research] unable to process : %s' % (name))
            raise ActionExecutionException(
                '[research] failed to process TAL in %s' % (name))

        if (content == 'None'):
            content = ''

        return content
    def _performRequest(self, body, environ):
        """
        Actually performs the request to PagerDuty's Event API.

        Raises:
            ActionExecutionException: Some error occurred while contacting
            PagerDuty's Event API (e.g., API down, invalid service key).
        """

        bodyWithProcessedTalesExpressions = self._processTalExpressions(
            body, environ)
        bodyWithProcessedTalesExpressions['payload'][
            'severity'] = EVENT_MAPPING[
                bodyWithProcessedTalesExpressions['payload']['severity']]
        requestBody = json.dumps(bodyWithProcessedTalesExpressions)

        headers = {'Content-Type': 'application/json'}
        req = urllib2.Request(EVENT_API_URI, requestBody, headers)
        try:
            # bypass default handler SVC-1819
            opener = urllib2.build_opener()
            f = opener.open(req, None, API_TIMEOUT_SECONDS)
        except urllib2.URLError as e:
            if hasattr(e, 'reason'):
                msg = 'Failed to contact the PagerDuty server: %s' % (e.reason)
                raise ActionExecutionException(msg)
            elif hasattr(e, 'code'):
                msg = 'The PagerDuty server couldn\'t fulfill the request: HTTP %d (%s)' % (
                    e.code, e.msg)
                raise ActionExecutionException(msg)
            else:
                raise ActionExecutionException('Unknown URLError occurred')

        response = f.read()
        log.debug('PagerDuty response: %s', response)
        f.close()
    def execute(self, notification, signal):
        """
        Sets up the execution environment and POSTs to PagerDuty's Event API.
        """
        log.debug('Executing Pagerduty Events API action: %s', self.name)

        self.setupAction(notification.dmd)

        if signal.clear:
            eventType = EventType.RESOLVE
        elif signal.event.status == STATUS_ACKNOWLEDGED:
            eventType = EventType.ACKNOWLEDGE
        else:
            eventType = EventType.TRIGGER

        # Set up the TALES environment
        environ = {'dmd': notification.dmd, 'env': None}

        actor = signal.event.occurrence[0].actor

        device = None
        if actor.element_uuid:
            device = self.guidManager.getObject(actor.element_uuid)
        environ.update({'dev': device})

        component = None
        if actor.element_sub_uuid:
            component = self.guidManager.getObject(actor.element_sub_uuid)
        environ.update({'component': component})

        data = _signalToContextDict(signal, self.options.get('zopeurl'),
                                    notification, self.guidManager)
        environ.update(data)

        try:
            detailsList = json.loads(notification.content['details'])
        except ValueError:
            raise ActionExecutionException('Invalid JSON string in details')

        details = dict()
        for kv in detailsList:
            details[kv['key']] = kv['value']

        details['zenoss'] = {
            'version': ZENOSS_VERSION,
            'zenpack_version': zenpack_version(),
        }

        payload = {
            'severity': '${evt/severity}',
            'class': '${evt/eventClass}',
            'custom_details': details,
        }
        body = {
            'event_action': eventType,
            'dedup_key': data['evt'].evid,
            'payload': payload
        }

        for prop in REQUIRED_PROPERTIES:
            if prop in notification.content:
                payload.update({prop: notification.content[prop]})
            else:
                raise ActionExecutionException(
                    "Required property '%s' not found" % prop)

        if NotificationProperties.SERVICE_KEY in notification.content:
            body.update({'routing_key': notification.content['serviceKey']})
        else:
            raise ActionExecutionException(
                "API Key for PagerDuty service was not found. "
                "Did you configure a notification correctly?")

        self._performRequest(body, environ)