def show_alert_threshold(self, obj):
     """
     show :attr:`ldap_probe.models.ADNodePerfBucket.alert_threshold`
     in the `Django admin` interface
     """
     try:
         return utils.show_milliseconds(
             obj.performance_bucket.alert_threshold)
     except AttributeError:
         return None
def _raise_ldap_alert(subscription, level, instance_pk):
    """
    invoke the email sending mechanism for an `LDAP` alert

    This is an unusual usage for :class:`ssl_cert_tracker.lib.Email`.
    The data is not exactly tabular and most of the email data must be
    provided using :attr:`ssl_cert_tracker.lib.Email.extra_context` entries
    because it is not generated at the database level but at the `Python`
    level.

    :arg subscription: the subscription required for addressing and
        rendering the email object
    :type subscription: :class:`p_soc_auto_base.models.Subscription`

    :arg str level: the level of the alert

    :arg int instance_pk: the primary key of the
        :class:`ldap_probe.models.LdapProbeLog` that is subject to the alert

    :returns: an interpretation of the return value of the
        :meth:`ssl_cert_tracker.lib.Email.send` operation

    :raises: generic :exc:`exceptions.Exception` for whatever error is
        raised by :meth:`ssl_cert_tracker.lib.Email.send`
    """
    data = apps.get_model('ldap_probe.ldapprobelog').objects.filter(
        id=instance_pk)

    ldap_probe = data.get()

    if ldap_probe.ad_orion_node:
        change_url_args = {
            'admin_view': 'admin:ldap_probe_orionadnode_change',
            'obj_pk': ldap_probe.ad_orion_node.pk,
            'obj_anchor_name': str(ldap_probe.ad_orion_node)
        }
    else:
        change_url_args = {
            'admin_view': 'admin:ldap_probe_nonorionadnode_change',
            'obj_pk': ldap_probe.ad_node.pk,
            'obj_anchor_name': str(ldap_probe.ad_node)
        }

    try:
        ret = Email.send_email(
            data=data, subscription=subscription, add_csv=False,
            level=level, node=ldap_probe.node, errors=ldap_probe.errors,
            created_on=ldap_probe.created_on,
            probe_url=ldap_probe.absolute_url,
            orion_url=ldap_probe.ad_node_orion_url,
            # TODO why doesn't this have its own function?
            node_url=get_absolute_admin_change_url(**change_url_args),
            bucket=ldap_probe.node_perf_bucket.name,
            avg_warn_threshold=utils.show_milliseconds(
                ldap_probe.node_perf_bucket.avg_warn_threshold),
            avg_err_threshold=utils.show_milliseconds(
                ldap_probe.node_perf_bucket.avg_err_threshold),
            alert_threshold=utils.show_milliseconds(
                ldap_probe.node_perf_bucket.alert_threshold))
    except Exception as error:
        LOG.exception(error)
        raise error

    if ldap_probe.failed:
        return_specification = 'error alert for'

    elif ldap_probe.perf_alert:
        return_specification = 'performance alert for'

    else:
        return_specification = 'performance warning for'

    if not ret:
        LOG.error('could not raise %s %s', return_specification, ldap_probe)

    LOG.debug('raised %s %s', return_specification, ldap_probe)
def dispatch_ldap_perf_report(
        data_source, bucket, anon, level, **time_delta_args):
    """
    task that generates a performance degradation report via email for the
    arguments used to invoke it

    Under normal circumstances, this task will always be invoked via
    a `Celery group()
    <https://docs.celeryproject.org/en/latest/userguide/canvas.html#groups>`__
    call.

    :arg str data_source: the named of the model containing information
        about `AD` nodes using the 'app_lable.model_name' convention

    :arg str bucket: the value of the
        :attr:`ldap_probe.models.ADNodePerfBucket.performance_bucket` field;
        this will be used to retrieve the applicable thresholds from the
        :class:`ldap_probe.models.ADNodePerfBucket` instance

    :arg bool anon: look for full bind or anonymous bind probe data

    :arg str level: the performance degradation level

    :arg time_delta_args: optional named arguments that are used to
            initialize a :class:`datetime.timedelta` object

            If not present, the method will use the period defined by the
            :class:`citrus_borg.dynamic_preferences_registry.LdapReportPeriod`
            user preference

    :returns: information about the arguments used to call the task and the
        result of :meth:`ssl_cert_tracker.lib.Email.send`
    :rtype: str

    :raises:

        :exc:`Exception` if the data for the report cannot be generated of
        the email cannot be sent.

        If the send operation raises an :exc:`smtplib.SMTPConnectError`,
        the task execution will be retried up to 3 times before the
        exception is allowed to propagate.
    """
    LOG.debug(
        ('invoking ldap probes report with data_source: %s, bucket: %s,'
         ' anon: %s, level: %s, time_delta_args: %s'),
        data_source, bucket, anon, level, time_delta_args)

    try:
        (now, time_delta, subscription, data, threshold, no_nodes) = \
            apps.get_model(data_source).report_perf_degradation(
                bucket=bucket, anon=anon, level=level, **time_delta_args
                )
    except Exception as error:
        LOG.exception(
            ('invoking ldap probes report with data_source: %s,'
             ' bucket: %s, anon: %s, level: %s, time_delta_args: %s'
             ' raises error %s'),
            data_source, bucket, anon, level, time_delta_args, error)
        raise error

    if no_nodes:
        LOG.warning('there are no AD network nodes for %s', bucket)

    if not get_preference('ldapprobe__ldap_perf_send_good_news') and not data:
        LOG.info('there is no performance degradation for %s', bucket)
        return

    subscription = Subscription.get_subscription(subscription)
    full = 'full bind' in subscription.subscription.lower()
    orion = 'non orion' not in subscription.subscription.lower()
    threshold = utils.show_milliseconds(threshold)

    if Email.send_email(
            data=data, subscription=subscription, level=level, now=now,
            time_delta=time_delta, full=full, orion=orion, bucket=bucket,
            threshold=threshold):
        LOG.info('dispatched LDAP probes performance degradation report with '
                 'data_source: %s, anon: %s, bucket: %s, level: %s, '
                 'time_delta_args: %s',
                 data_source, anon, bucket, level, time_delta_args)
        return

    LOG.warning('could not dispatch LDAP probes performance degradation report'
                ' with data_source: %s, anon: %s, bucket: %s, level: %s,'
                ' time_delta_args: %s',
                data_source, anon, bucket, level, time_delta_args)