def move(params): """Move a host to another folder""" user.need_permission("wato.edit") user.need_permission("wato.move_hosts") host_name = params["host_name"] host: CREHost = Host.load_host(host_name) _require_host_etag(host) current_folder = host.folder() target_folder: CREFolder = params["body"]["target_folder"] if target_folder is current_folder: return problem( status=400, title="Invalid move action", detail="The host is already part of the specified target folder", ) try: current_folder.move_hosts([host_name], target_folder) except MKUserError as exc: return problem( status=400, title="Problem moving host", detail=exc.message, ) return _serve_host(host, effective_attributes=False)
def bulk_create_hosts(params): """Bulk create hosts""" user.need_permission("wato.edit") body = params["body"] entries = body["entries"] failed_hosts: Dict[HostName, str] = {} succeeded_hosts: List[HostName] = [] folder: CREFolder for folder, grouped_hosts in itertools.groupby( entries, operator.itemgetter("folder")): validated_entries = [] folder.prepare_create_hosts() for host in grouped_hosts: host_name = host["host_name"] attributes = host["attributes"] try: folder.verify_host_details(host_name, attributes) validated_entries.append((host_name, attributes, None)) except (MKUserError, MKAuthException) as e: failed_hosts[host_name] = f"Validation failed: {e}" folder.create_validated_hosts(validated_entries, bake_hosts=False) succeeded_hosts.extend(entry[0] for entry in validated_entries) if params[BAKE_AGENT_PARAM_NAME]: bakery.try_bake_agents_for_hosts(succeeded_hosts) return _bulk_host_action_response( failed_hosts, [Host.load_host(host_name) for host_name in succeeded_hosts])
def bulk_delete(params): """Bulk delete hosts""" user.need_permission("wato.edit") body = params["body"] for host_name in body["entries"]: host = Host.load_host(host_name) host.folder().delete_hosts([host.name()], automation=delete_hosts) return Response(status=204)
def show_host(params) -> Response: """Show a host""" host = Host.load_host(params["host_name"]) return constructors.serve_json( { "site": host.site_id(), "is_cluster": host.is_cluster(), } )
def delete(params): """Delete a host""" user.need_permission("wato.edit") host_name = params["host_name"] # Parameters can't be validated through marshmallow yet. check_hostname(host_name, should_exist=True) host: CREHost = Host.load_host(host_name) host.folder().delete_hosts([host.name()], automation=delete_hosts) return Response(status=204)
def create_host(params): """Create a host""" user.need_permission("wato.edit") body = params["body"] host_name = body["host_name"] folder: CREFolder = body["folder"] # is_cluster is defined as "cluster_hosts is not None" folder.create_hosts([(host_name, body["attributes"], None)], bake_hosts=params[BAKE_AGENT_PARAM_NAME]) host = Host.load_host(host_name) return _serve_host(host, False)
def update_service_phase(params) -> Response: """Update the phase of a service""" body = params["body"] host = Host.load_host(params["host_name"]) target_phase = body["target_phase"] check_type = body["check_type"] service_item = body["service_item"] _update_single_service_phase( SERVICE_DISCOVERY_PHASES[target_phase], host, check_type, service_item, ) return Response(status=204)
def create_cluster_host(params): """Create a cluster host A cluster host groups many hosts (called nodes in this context) into a conceptual cluster. All the services of the individual nodes will be collated on the cluster host.""" user.need_permission("wato.edit") body = params["body"] host_name = body["host_name"] folder: CREFolder = body["folder"] folder.create_hosts([(host_name, body["attributes"], body["nodes"])], bake_hosts=params[BAKE_AGENT_PARAM_NAME]) host = Host.load_host(host_name) return _serve_host(host, effective_attributes=False)
def update_nodes(params): """Update the nodes of a cluster host""" user.need_permission("wato.edit") user.need_permission("wato.edit_hosts") host_name = params["host_name"] body = params["body"] nodes = body["nodes"] host: CREHost = Host.load_host(host_name) _require_host_etag(host) host.edit(host.attributes(), nodes) return constructors.serve_json( constructors.object_sub_property( domain_type="host_config", ident=host_name, name="nodes", value=host.cluster_nodes(), ))
def _get_cluster_nodes(self): if not self._is_cluster(): return None cluster_nodes = self._vs_cluster_nodes().from_html_vars("nodes") self._vs_cluster_nodes().validate_value(cluster_nodes, "nodes") if len(cluster_nodes) < 1: raise MKUserError("nodes_0", _("The cluster must have at least one node")) # Fake a cluster host in order to get calculated tag groups via effective attributes... cluster_computed_datasources = cmk.utils.tags.compute_datasources( Host( Folder.current(), self._host.name(), collect_attributes("cluster", new=False), [], ).tag_groups()) for nr, cluster_node in enumerate(cluster_nodes): if cluster_node == self._host.name(): raise MKUserError( "nodes_%d" % nr, _("The cluster can not be a node of it's own")) if not Host.host_exists(cluster_node): raise MKUserError( "nodes_%d" % nr, _("The node <b>%s</b> does not exist " " (must be a host that is configured with WATO)") % cluster_node, ) node_computed_datasources = cmk.utils.tags.compute_datasources( Host.load_host(cluster_node).tag_groups()) if datasource_differences := cluster_computed_datasources.get_differences_to( node_computed_datasources): raise MKUserError( "nodes_%d" % nr, _("Cluster and nodes must have the same datasource. ") + self._format_datasource_differences( cluster_node, datasource_differences), )
def bulk_update_hosts(params): """Bulk update hosts Please be aware that when doing bulk updates, it is not possible to prevent the [Updating Values]("lost update problem"), which is normally prevented by the ETag locking mechanism. Use at your own risk. """ user.need_permission("wato.edit") user.need_permission("wato.edit_hosts") body = params["body"] entries = body["entries"] succeeded_hosts: List[CREHost] = [] failed_hosts: Dict[HostName, str] = {} for update_detail in entries: host_name = update_detail["host_name"] new_attributes = update_detail["attributes"] update_attributes = update_detail["update_attributes"] remove_attributes = update_detail["remove_attributes"] check_hostname(host_name) host: CREHost = Host.load_host(host_name) if new_attributes: host.edit(new_attributes, None) if update_attributes: host.update_attributes(update_attributes) faulty_attributes = [] for attribute in remove_attributes: if not host.has_explicit_attribute(attribute): faulty_attributes.append(attribute) if faulty_attributes: failed_hosts[ host_name] = f"Failed to remove {', '.join(faulty_attributes)}" continue if remove_attributes: host.clean_attributes(remove_attributes) succeeded_hosts.append(host) return _bulk_host_action_response(failed_hosts, succeeded_hosts)
def show_services(params) -> Response: """Show all services of specific phase""" host = Host.load_host(params["host_name"]) discovery_request = StartDiscoveryRequest( host=host, folder=host.folder(), options=DiscoveryOptions( action="", show_checkboxes=False, show_parameters=False, show_discovered_labels=False, show_plugin_names=False, ignore_errors=True, ), ) discovery_result = get_check_table(discovery_request) return _serve_services( host, discovery_result.check_table, [params["discovery_phase"]], )
def execute(params) -> Response: """Execute a service discovery on a host""" host = Host.load_host(params["host_name"]) body = params["body"] discovery_request = StartDiscoveryRequest( host=host, folder=host.folder(), options=DiscoveryOptions( action=DISCOVERY_ACTION[body["mode"]], show_checkboxes=False, show_parameters=False, show_discovered_labels=False, show_plugin_names=False, ignore_errors=True, ), ) discovery_result = get_check_table(discovery_request) return _serve_services( host, discovery_result.check_table, list(SERVICE_DISCOVERY_PHASES.keys()), )
def update_host(params): """Update a host""" user.need_permission("wato.edit") user.need_permission("wato.edit_hosts") host_name = params["host_name"] body = params["body"] new_attributes = body["attributes"] update_attributes = body["update_attributes"] remove_attributes = body["remove_attributes"] check_hostname(host_name, should_exist=True) host: CREHost = Host.load_host(host_name) _require_host_etag(host) if new_attributes: new_attributes["meta_data"] = host.attributes().get("meta_data", {}) host.edit(new_attributes, None) if update_attributes: host.update_attributes(update_attributes) faulty_attributes = [] for attribute in remove_attributes: if not host.has_explicit_attribute(attribute): faulty_attributes.append(attribute) if remove_attributes: host.clean_attributes( remove_attributes) # silently ignores missing attributes if faulty_attributes: return problem( status=400, title="Some attributes were not removed", detail= f"The following attributes were not removed since they didn't exist: {', '.join(faulty_attributes)}", ) return _serve_host(host, effective_attributes=False)
def rename_host(params): """Rename a host""" user.need_permission("wato.edit") user.need_permission("wato.rename_hosts") if activate_changes.get_pending_changes_info(): return problem( status=409, title="Pending changes are present", detail= "Please activate all pending changes before executing a host rename process", ) host_name = params["host_name"] host: CREHost = Host.load_host(host_name) new_name = params["body"]["new_name"] _, auth_problems = perform_rename_hosts([(host.folder(), host_name, new_name)]) if auth_problems: return problem( status=422, title="Rename process failed", detail= f"It was not possible to rename the host {host_name} to {new_name}", ) return _serve_host(host, effective_attributes=False)
def show_host(params): """Show a host""" host_name = params["host_name"] host: CREHost = Host.load_host(host_name) return _serve_host(host, effective_attributes=params["effective_attributes"])
def _check_host_editing_permissions(host_name: HostName) -> CREHost: host = Host.load_host(host_name) host.need_permission("write") return host