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 servicegroup. 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: """ members: List[List[str]] = Query( [tables.Servicegroups.members], tables.Servicegroups.name.equals(servicegroup_name), ).value(connection) for host_name, service_description in members: schedule_service_downtime( connection, 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_name for _host_name, _ in members]) schedule_host_downtime( connection, host_name=host_names, start_time=start_time, end_time=end_time, recur=recur, trigger_id=trigger_id, duration=duration, user_id=user_id, comment=comment, )
def schedule_hostgroup_host_downtime( connection, hostgroup_name: 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 = '', ): """Schedules downtime for all hosts in a given hostgroup. Args: connection: A LiveStatus connection object. hostgroup_name: The name of the hostgroup. A downtime will be scheduled for all hosts in this hostgroup. 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. 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: See Also: * https://assets.nagios.com/downloads/nagioscore/docs/externalcmds/cmdinfo.php?command_id=123 """ members: List[str] = Query([tables.Hostgroups.members], tables.Hostgroups.name.equals(hostgroup_name)).value(connection) schedule_host_downtime( connection, host_name=members, start_time=start_time, end_time=end_time, include_all_services=include_all_services, recur=recur, trigger_id=trigger_id, duration=duration, user_id=user_id, comment=comment, )
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 service group 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 service group 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, )
def host_is_monitored(host_name: str) -> bool: return bool( Query([Hosts.name], Hosts.name == host_name).first_value(sites.live()))
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, )
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
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)
def set_acknowledgement_on_hosts(params): """Set acknowledgement on related hosts""" body = params["body"] live = sites.live() sticky = body["sticky"] notify = body["notify"] persistent = body["persistent"] comment = body["comment"] acknowledge_type = body["acknowledge_type"] if acknowledge_type == "host": name = body["host_name"] host_state = Query([Hosts.state], Hosts.name == name).value(live) if not host_state: raise ProblemException( status=422, title=f"Host {name!r} has no problem.", ) acknowledge_host_problem( live, name, sticky=sticky, notify=notify, persistent=persistent, user=user.ident, comment=comment, ) elif acknowledge_type == "hostgroup": host_group = body["hostgroup_name"] try: acknowledge_hostgroup_problem( live, host_group, sticky=sticky, notify=notify, persistent=persistent, user=user.ident, comment=comment, ) except ValueError: raise ProblemException( 400, title="Host group could not be found.", detail=f"Unknown host group: {host_group}", ) elif acknowledge_type == "host_by_query": query = body["query"] hosts = Query([Hosts.name], query).fetchall(live) if not hosts: raise ProblemException( status=422, title="The provided query returned no monitored hosts", ) for host in hosts: acknowledge_host_problem( live, host.name, sticky=sticky, notify=notify, persistent=persistent, user=user.ident, comment=comment, ) else: raise ProblemException( status=400, title="Unhandled acknowledge-type.", detail= f"The acknowledge-type {acknowledge_type!r} is not supported.", ) return http.Response(status=204)
def set_acknowledgement_on_services(params): """Set acknowledgement on related services""" body = params["body"] live = sites.live() sticky = body["sticky"] notify = body["notify"] persistent = body["persistent"] comment = body["comment"] acknowledge_type = body["acknowledge_type"] if acknowledge_type == "service": description = unquote(body["service_description"]) host_name = body["host_name"] service = Query( [Services.host_name, Services.description, Services.state], And(Services.host_name == host_name, Services.description == description), ).first(live) if not service: raise ProblemException( status=400, title= f"Service {description!r}@{host_name!r} could not be found.", ) if not service.state: raise ProblemException( status=422, title=f"Service {description!r}@{host_name!r} has no problem.", ) acknowledge_service_problem( live, service.host_name, service.description, sticky=sticky, notify=notify, persistent=persistent, user=user.ident, comment=comment, ) elif acknowledge_type == "servicegroup": service_group = body["servicegroup_name"] try: acknowledge_servicegroup_problem( live, service_group, sticky=sticky, notify=notify, persistent=persistent, user=user.ident, comment=comment, ) except ValueError: raise ProblemException( status=400, title="Service group could not be found.", detail=f"Unknown service group: {service_group}", ) elif acknowledge_type == "service_by_query": services = Query( [Services.host_name, Services.description, Services.state], body["query"], ).fetchall(live) if not services: raise ProblemException( status=422, title="No services with problems found.", detail="All queried services are OK.", ) for service in services: if not service.state: continue acknowledge_service_problem( live, service.host_name, service.description, sticky=sticky, notify=notify, persistent=persistent, user=user.ident, comment=comment, ) else: raise ProblemException( status=400, title="Unhandled acknowledge-type.", detail= f"The acknowledge-type {acknowledge_type!r} is not supported.", ) return http.Response(status=204)
def set_acknowledgement_on_services(params): """Set acknowledgement on related services""" body = params['body'] live = sites.live() sticky = body['sticky'] notify = body['notify'] persistent = body['persistent'] comment = body['comment'] acknowledge_type = body['acknowledge_type'] if acknowledge_type == 'service': description = unquote(body['service_description']) host_name = body['host_name'] service = Query( [Services.host_name, Services.description, Services.state], And(Services.host_name == host_name, Services.description == description)).first(live) if not service: raise ProblemException( status=400, title= f'Service {description!r}@{host_name!r} could not be found.', ) if not service.state: raise ProblemException( status=422, title=f'Service {description!r}@{host_name!r} has no problem.', ) acknowledge_service_problem( live, service.host_name, service.description, sticky=sticky, notify=notify, persistent=persistent, user=config.user.ident, comment=comment, ) elif acknowledge_type == 'servicegroup': service_group = body['servicegroup_name'] try: acknowledge_servicegroup_problem( live, service_group, sticky=sticky, notify=notify, persistent=persistent, user=config.user.ident, comment=comment, ) except ValueError: raise ProblemException( status=400, title="Servicegroup could not be found.", detail=f"Unknown servicegroup: {service_group}", ) elif acknowledge_type == 'service_by_query': services = Query( [Services.host_name, Services.description, Services.state], body['query'], ).fetchall(live) if not services: raise ProblemException( status=422, title='No services with problems found.', detail='All queried services are OK.', ) for service in services: if not service.state: continue acknowledge_service_problem( live, service.host_name, service.description, sticky=sticky, notify=notify, persistent=persistent, user=config.user.ident, comment=comment, ) else: raise ProblemException( status=400, title="Unhandled acknowledge-type.", detail= f"The acknowledge-type {acknowledge_type!r} is not supported.", ) return http.Response(status=204)
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, )