Exemple #1
0
def _query_site(connection, host_name: str) -> str:
    with detailed_connection(connection) as conn:
        site_id = Query([Hosts.name],
                        Hosts.name.equals(host_name)).first_value(conn)
        if not isinstance(site_id, str):
            raise QueryException
    return site_id
Exemple #2
0
def delete_downtime(connection, downtime_id):
    """Delete a scheduled downtime based upon the downtime id"""
    with detailed_connection(connection) as conn:
        entry = Query(
            [Downtimes.is_service],
            Downtimes.id == downtime_id,
        ).fetchone(conn)
    if entry["is_service"]:
        del_service_downtime(connection, downtime_id, entry["site"])
    else:
        del_host_downtime(connection, downtime_id, entry["site"])
Exemple #3
0
def delete_downtime_with_query(connection, query):
    """Delete scheduled downtimes based upon a query"""
    q = Query([Downtimes.id, Downtimes.is_service]).filter(query)

    with detailed_connection(connection) as conn:
        downtimes = [(row["site"], row["id"], row["is_service"])
                     for row in q.iterate(conn)]

    for site_id, downtime_id, is_service in downtimes:
        if is_service:
            del_service_downtime(connection, downtime_id, site_id)
        else:
            del_host_downtime(connection, downtime_id, site_id)
Exemple #4
0
def schedule_services_downtimes_with_query(
    connection,
    query: QueryExpression,
    start_time: dt.datetime,
    end_time: dt.datetime,
    recur: RecurMode = "fixed",
    duration: int = 0,
    user_id: str = "",
    comment: str = "",
):
    """Schedule downtimes for services based upon a query"""

    q = Query(
        [Services.description, Services.host_name],
        query,
    )
    with detailed_connection(connection) as conn:
        result = [(row["site"], row["host_name"], row["description"])
                  for row in q.iterate(conn)]

    if not result:
        raise QueryException

    for site_id, host_name, service_description in result:
        if not comment:
            downtime_comment = f"Downtime for service {service_description}@{host_name}"
        else:
            downtime_comment = comment

        schedule_service_downtime(
            connection,
            site_id=site_id,
            host_name=host_name,
            service_description=service_description,
            start_time=start_time,
            end_time=end_time,
            recur=recur,
            duration=duration,
            user_id=user_id,
            comment=downtime_comment,
        )
Exemple #5
0
def acknowledge_servicegroup_problem(
    connection,
    servicegroup_name: str,
    sticky: bool = False,
    notify: bool = False,
    persistent: bool = False,
    user: str = "",
    comment: str = "",
):
    """Acknowledge the problems of the current services of the servicegroup

    When acknowledging a problem, further notifications for the respective services are disabled, as
    long as a specific service doesn't change state. At state change, notifications are re-enabled.

    Args:
        connection:
            A livestatus connection object.

        servicegroup_name:
            The host-name for which this acknowledgement is for.

        sticky:
            If set, only a state-change of the service to an OK state will discard the
            acknowledgement. Otherwise it will be discarded on any state-change. Defaults to False.

        notify:
            If set, notifications will be sent out to the configured contacts. Defaults to False.

        persistent:
            If set, the comment will persist a restart. Defaults to False.

        user:
        comment:
            If set, this comment will be stored alongside the acknowledgement.

    Raises:
        ValueError:
            When the servicegroup could not be found.

    """
    with detailed_connection(connection) as conn:
        group_entries = Query(
            [tables.Servicegroups.members],
            tables.Servicegroups.name.equals(servicegroup_name),
        ).fetchall(conn)

    acknowledgement = 2 if sticky else 1  # 1: normal, 2: sticky

    for entry in group_entries:
        site_id = entry["site"]
        for host_name, service_description in entry["members"]:
            send_command(
                connection,
                "ACKNOWLEDGE_SVC_PROBLEM",
                [
                    host_name,
                    service_description,
                    acknowledgement,
                    int(notify),
                    int(persistent),
                    user,
                    comment,
                ],
                site_id=site_id,
            )
Exemple #6
0
def acknowledge_host_problem(
    connection,
    host_name,
    sticky: bool = False,
    notify: bool = False,
    persistent: bool = False,
    user: str = "",
    comment: str = "",
):
    """Acknowledge the current problem for the given host.

    When acknowledging a problem, notifications for the host are disabled, as long as the
    host doesn't change state. At state change, notifications are re-enabled.

    Args:
        connection:
            A livestatus connection object.

        host_name:
            The host-name for which this acknowledgement is for.

        sticky:
            If set, only a state-change of the host to an UP state will discard the acknowledgement.
            Otherwise it will be discarded on any state-change. Defaults to False.

        notify:
            If set, notifications will be sent out to the configured contacts. Defaults to False.

        persistent:
            If set, the comment will persist a restart. Defaults to False.

        user:
        comment:
            If set, this comment will be stored alongside the acknowledgement.

    Examples:

        >>> from cmk.gui.livestatus_utils.testing import simple_expect
        >>> cmd = "COMMAND [...] ACKNOWLEDGE_HOST_PROBLEM;example.com;1;0;0;;"
        >>> with simple_expect() as live:
        ...     _ = live.expect_query("GET hosts\\nColumns: name\\nFilter: name = example.com")
        ...     _ = live.expect_query(cmd, match_type="ellipsis")
        ...     acknowledge_host_problem(live, 'example.com')

    """
    acknowledgement = 2 if sticky else 1  # 1: normal, 2: sticky

    with detailed_connection(connection) as conn:
        site_id = Query([Hosts.name],
                        Hosts.name.equals(host_name)).first_value(conn)

    return send_command(
        connection,
        "ACKNOWLEDGE_HOST_PROBLEM",
        [
            host_name,
            acknowledgement,
            int(notify),
            int(persistent),
            user,
            comment,
        ],
        site_id=site_id,
    )
Exemple #7
0
def create_service_related_downtime(params):
    """Create a service related scheduled downtime"""
    body = params["body"]
    live = sites.live()

    downtime_type: DowntimeType = body["downtime_type"]

    if downtime_type == "service":
        host_name = body["host_name"]
        with detailed_connection(live) as conn:
            site_id = Query(columns=[Hosts.name], filter_expr=Hosts.name.op("=", host_name)).value(
                conn
            )
        downtime_commands.schedule_service_downtime(
            live,
            site_id,
            host_name=body["host_name"],
            service_description=body["service_descriptions"],
            start_time=body["start_time"],
            end_time=body["end_time"],
            recur=body["recur"],
            duration=body["duration"],
            user_id=user.ident,
            comment=body.get(
                "comment",
                f"Downtime for services {', '.join(body['service_descriptions'])!r}@{body['host_name']!r}",
            ),
        )
    elif downtime_type == "servicegroup":
        downtime_commands.schedule_servicegroup_service_downtime(
            live,
            servicegroup_name=body["servicegroup_name"],
            start_time=body["start_time"],
            end_time=body["end_time"],
            recur=body["recur"],
            duration=body["duration"],
            user_id=user.ident,
            comment=body.get("comment", f"Downtime for servicegroup {body['servicegroup_name']!r}"),
        )
    elif downtime_type == "service_by_query":
        try:
            downtime_commands.schedule_services_downtimes_with_query(
                live,
                query=body["query"],
                start_time=body["start_time"],
                end_time=body["end_time"],
                recur=body["recur"],
                duration=body["duration"],
                user_id=user.ident,
                comment=body.get("comment", ""),
            )
        except QueryException:
            return problem(
                status=422,
                title="Query did not match any service",
                detail="The provided query returned an empty list so no downtime was set",
            )
    else:
        return problem(
            status=400,
            title="Unhandled downtime-type.",
            detail=f"The downtime-type {downtime_type!r} is not supported.",
        )

    return Response(status=204)
Exemple #8
0
def schedule_host_downtime(
    connection,
    host_entry: Union[str, List[str]],
    start_time: dt.datetime,
    end_time: dt.datetime,
    include_all_services: bool = False,
    recur: RecurMode = "fixed",
    trigger_id: int = 0,
    duration: int = 0,
    user_id: str = "",
    comment: str = "",
):
    """Schedule the downtime of a host.

    Notes:
        If `include_all_services` is set to True, the services table is only queried
        once, instead of len(host_name) times. If a lot of hosts are to be scheduled, this
        will save N queries. Issuing the command is still done sequentially.

    Args:
        connection:
            A livestatus connection object.

        host_entry:
            The host-name for which this downtime is for.

        start_time:
            When the downtime shall begin.

        end_time:
            When the downtime shall end.

        include_all_services:
            If set, downtimes for all services associated with the given host will be scheduled.
            Defaults to False.

        recur:
            The recurring mode of the new downtime. Available modes are:
                * fixed
                * hour
                * day
                * week
                * second_week
                * fourth_week
                * weekday_start
                * weekday_end
                * day_of_month

            This only works when using the Enterprise Editions. Defaults to 'fixed'.

        trigger_id:
            The id of another downtime-entry. If given (other than 0) then this downtime will be
            triggered by the other downtime.

        duration:
            Duration in seconds. When set, the downtime does not begin automatically at a nominated
            time, but when a real problem status appears for the host. Consequencely, the
            start_time/end_time is only the time window in which the scheduled downtime can begin.

        user_id:

        comment:
            A comment which will be added to the downtime.

    See Also:
      * https://assets.nagios.com/downloads/nagioscore/docs/externalcmds/cmdinfo.php?command_id=118
      * https://assets.nagios.com/downloads/nagioscore/docs/externalcmds/cmdinfo.php?command_id=122

    Examples:
        >>> import pytz
        >>> _start_time = dt.datetime(1970, 1, 1, tzinfo=pytz.timezone("UTC"))
        >>> _end_time = dt.datetime(1970, 1, 2, tzinfo=pytz.timezone("UTC"))

        >>> from cmk.gui.livestatus_utils.testing import simple_expect
        >>> from cmk.gui.config import load_config
        >>> from cmk.gui.utils.script_helpers import application_and_request_context
        >>> from cmk.gui.logged_in import SuperUserContext

        >>> cmd = "COMMAND [...] SCHEDULE_HOST_DOWNTIME;example.com;0;86400;16;0;120;;Boom"
        >>> with simple_expect() as live, application_and_request_context(), SuperUserContext():
        ...     load_config()
        ...     _ = live.expect_query("GET hosts\\nColumns: name\\nFilter: name = example.com")
        ...     _ = live.expect_query(cmd, match_type="ellipsis")
        ...     schedule_host_downtime(live,
        ...             'example.com',
        ...             _start_time,
        ...             _end_time,
        ...             recur="day_of_month",
        ...             duration=120,
        ...             comment="Boom")

    """
    if isinstance(host_entry, str):
        hosts = [host_entry]
    elif host_entry:
        hosts = host_entry
    else:
        raise ValueError("List of hosts may not be empty.")

    with detailed_connection(connection) as conn:
        host_entries = [(entry["site"], entry["name"]) for entry in Query(
            [Hosts.name], Or(*[Hosts.name.equals(host)
                               for host in hosts])).fetchall(conn)]

    for _site, _host_name in host_entries:
        _schedule_downtime(
            connection,
            "SCHEDULE_HOST_DOWNTIME",
            _site,
            _host_name,
            None,
            start_time,
            end_time,
            recur,
            trigger_id,
            duration,
            user_id,
            comment,
        )

    if include_all_services:
        with detailed_connection(connection) as conn:
            services = Query(
                [tables.Services.host_name, tables.Services.description],
                Or(*[
                    tables.Services.host_name.equals(_host_name)
                    for _, _host_name in host_entries
                ]),
            ).fetch_values(conn)

        for _site, _host_name, service_description in services:
            schedule_service_downtime(
                connection,
                _site,
                host_name=_host_name,
                service_description=service_description,
                start_time=start_time,
                end_time=end_time,
                recur=recur,
                trigger_id=trigger_id,
                duration=duration,
                user_id=user_id,
                comment=comment,
            )
Exemple #9
0
def schedule_servicegroup_service_downtime(
    connection,
    servicegroup_name: str,
    start_time: dt.datetime,
    end_time: dt.datetime,
    include_hosts: bool = False,
    recur: RecurMode = "fixed",
    trigger_id: int = 0,
    duration: int = 0,
    user_id: str = "",
    comment: str = "",
):
    """Schedules downtime for all hosts, which have services in a given service group.

    Args:
        connection:
            A LiveStatus connection object.

        servicegroup_name:
            The name of the service group. Any host having a service in this group will be
            A downtime will be scheduled for all hosts in this group.

        start_time:
            When the downtime shall begin.

        end_time:
            When the downtime shall end.

        include_hosts:
            When set to True, all hosts will also receive a scheduled downtime, not just their
            services which belong to this service group.

        recur:
            The recurring mode of the new downtime. Available modes are:
                * fixed
                * hour
                * day
                * week
                * second_week
                * fourth_week
                * weekday_start
                * weekday_end
                * day_of_month

            This only works when using the Enterprise Editions. Defaults to 'fixed'.

        trigger_id:
            The id of another downtime-entry. If given (other than 0) then this downtime will be
            triggered by the other downtime.

        duration:
            Duration in seconds. When set, the downtime does not begin automatically at a nominated
            time, but when a real problem status appears for the host. Consequently, the
            start_time/end_time is only the time window in which the scheduled downtime can begin.

        user_id:

        comment:
            A comment which will be added to the downtime.

        connection:

    """
    with detailed_connection(connection) as conn:
        entries = list(
            Query(
                [tables.Servicegroups.members],
                tables.Servicegroups.name.equals(servicegroup_name),
            ).iterate(conn))
    for entry in entries:
        site = entry["site"]
        for host_name, service_description in entry["members"]:
            schedule_service_downtime(
                connection,
                site,
                host_name=host_name,
                service_description=service_description,
                start_time=start_time,
                end_time=end_time,
                recur=recur,
                trigger_id=trigger_id,
                duration=duration,
                user_id=user_id,
                comment=comment,
            )

    if include_hosts:
        host_names = _deduplicate(
            [host for entry in entries for (host, _) in entry["members"]])
        schedule_host_downtime(
            connection,
            host_entry=host_names,
            start_time=start_time,
            end_time=end_time,
            recur=recur,
            trigger_id=trigger_id,
            duration=duration,
            user_id=user_id,
            comment=comment,
        )