Пример #1
0
    def page(self):
        html.open_div(id_="ldap")
        html.open_table()
        html.open_tr()

        html.open_td()
        html.begin_form("connection", method="POST")
        html.prevent_password_auto_completion()
        vs = self._valuespec()
        vs.render_input("connection", self._connection_cfg)
        vs.set_focus("connection")
        html.hidden_fields()
        html.end_form()
        html.close_td()

        html.open_td(style="padding-left:10px;vertical-align:top")
        html.h2(_('Diagnostics'))
        if not html.request.var('_test') or not self._connection_id:
            html.show_message(
                HTML(
                    '<p>%s</p><p>%s</p>' %
                    (_('You can verify the single parts of your ldap configuration using this '
                       'dialog. Simply make your configuration in the form on the left side and '
                       'hit the "Save & Test" button to execute the tests. After '
                       'the page reload, you should see the results of the test here.'),
                     _('If you need help during configuration or experience problems, please refer '
                       'to the <a target="_blank" '
                       'href="https://checkmk.com/checkmk_multisite_ldap_integration.html">'
                       'LDAP Documentation</a>.'))))
        else:
            connection = userdb.get_connection(self._connection_id)
            assert isinstance(connection, LDAPUserConnector)

            for address in connection.servers():
                html.h3("%s: %s" % (_('Server'), address))
                with table_element('test', searchable=False) as table:
                    for title, test_func in self._tests():
                        table.row()
                        try:
                            state, msg = test_func(connection, address)
                        except Exception as e:
                            state = False
                            msg = _('Exception: %s') % html.render_text("%s" % e)
                            logger.exception("error testing LDAP %s for %s", title, address)

                        if state:
                            img = html.render_icon("success", _('Success'))
                        else:
                            img = html.render_icon("failed", _("Failed"))

                        table.cell(_("Test"), title)
                        table.cell(_("State"), img)
                        table.cell(_("Details"), msg)

            connection.disconnect()

        html.close_td()
        html.close_tr()
        html.close_table()
        html.close_div()
Пример #2
0
    def _show_main_menu_content(self) -> None:
        for menu_item in self._get_main_menu_items():
            if isinstance(menu_item.icon, dict):
                active_icon: Icon = {
                    "icon": menu_item.icon["icon"] + "_active",
                    "emblem": menu_item.icon["emblem"]
                }
            else:
                active_icon = menu_item.icon + "_active"

            html.open_li()
            html.popup_trigger(
                (html.render_icon(menu_item.icon) +
                 html.render_icon(active_icon, class_="active") +
                 html.render_div(menu_item.title)),
                ident="mega_menu_" + menu_item.name,
                method=MethodInline(self._get_mega_menu_content(menu_item)),
                cssclass=menu_item.name,
                popup_group="main_menu_popup",
                hover_switch_delay=150,  # ms
                onopen=menu_item.onopen,
            )
            html.div("",
                     id_="popup_shadow",
                     onclick="cmk.popup_menu.close_popup()")
            html.close_li()
Пример #3
0
    def _get_popup_trigger_content(self, active_icon: Icon, menu_item: MainMenuItem) -> HTML:
        content = html.render_icon(menu_item.icon) + html.render_icon(active_icon, class_="active")

        if not user.get_attribute("nav_hide_icons_title"):
            content += html.render_div(menu_item.title)

        return content
Пример #4
0
 def render_addto_popup_entry(cls, type_name, name, title):
     html.open_li()
     html.open_a(
         href="javascript:void(0)",
         onclick="cmk.popup_menu.pagetype_add_to_container('%s', '%s');cmk.utils.reload_sidebar();"
         % (type_name, name))
     html.render_icon(type_name)
     html.write_text(title)
     html.close_a()
     html.close_li()
Пример #5
0
 def _show_main_menu_content(self) -> None:
     for menu_item in self._get_main_menu_items():
         html.open_li()
         html.popup_trigger(
             (html.render_icon(menu_item.icon_name) + html.render_icon(
                 menu_item.icon_name + "_active", class_="active") +
              html.render_div(menu_item.title)),
             ident="mega_menu_" + menu_item.name,
             method=MethodInline(self._get_mega_menu_content(menu_item)),
             cssclass=menu_item.name,
             popup_group="main_menu_popup",
             hover_switch_delay=150,  # ms
             onopen=menu_item.onopen,
         )
         html.close_li()
Пример #6
0
    def _show_popup(self, entry: PageMenuEntry) -> None:
        assert isinstance(entry.item, PageMenuPopup)

        if entry.name is None:
            raise ValueError("Missing \"name\" attribute on entry \"%s\"" % entry.title)

        classes = ["page_menu_popup"] + html.normalize_css_spec(entry.item.css_classes)
        if isinstance(entry.item, PageMenuSidePopup):
            classes.append("side_popup")

        popup_id = "popup_%s" % entry.name
        html.open_div(id_=popup_id, class_=classes)

        html.open_div(class_="head")
        html.h3(entry.title)
        html.a(html.render_icon("close"),
               class_="close_popup",
               href="javascript:void(0)",
               onclick="cmk.page_menu.close_popup(this)")
        html.close_div()

        if (isinstance(entry.item, PageMenuSidePopup) and entry.item.content and
                "side_popup_content" not in entry.item.content):
            raise RuntimeError(
                "Add a div container with the class \"side_popup_content\" to the popup content")

        html.open_div(class_="content")
        html.write(HTML(entry.item.content))
        html.close_div()
        html.close_div()

        if isinstance(entry.item, PageMenuSidePopup):
            html.final_javascript("cmk.page_menu.side_popup_add_simplebar_scrollbar(%s);" %
                                  json.dumps(popup_id))
Пример #7
0
    def page(self) -> None:
        html.h3(_("Upload Icon"))
        html.p(
            _("Allowed are single PNG image files with a maximum size of 80x80 px."
              ))

        html.begin_form('upload_form', method='POST')
        self._vs_upload().render_input('_upload_icon', None)
        html.hidden_fields()
        html.end_form()

        icons = sorted(self._load_custom_icons().items())
        with table_element("icons", _("Custom Icons")) as table:
            for icon_name, category_name in icons:
                table.row()

                table.cell(_("Actions"), css="buttons")
                delete_url = make_action_link([("mode", "icons"),
                                               ("_delete", icon_name)])
                html.icon_button(delete_url, _("Delete this Icon"), "delete")

                table.cell(_("Icon"),
                           html.render_icon(icon_name),
                           css="buttons")
                table.text_cell(_("Name"), icon_name)
                table.text_cell(_("Category"),
                                IconSelector.category_alias(category_name))
Пример #8
0
def render_object_ref_as_icon(
        object_ref: Optional[ObjectRef]) -> Optional[HTML]:
    if object_ref is None:
        return None

    url, title = _get_object_reference(object_ref)
    if not url:
        return None

    icons = {
        ObjectRefType.Host: "host",
        ObjectRefType.Folder: "folder",
        ObjectRefType.User: "******",
        ObjectRefType.Rule: "rule",
        ObjectRefType.Ruleset: "rulesets",
    }

    return html.render_a(
        content=html.render_icon(
            icons.get(object_ref.object_type, "link"),
            title="%s: %s" %
            (object_ref.object_type.name, title) if title else None,
        ),
        href=url,
    )
Пример #9
0
    def render(self, what, row, tags, custom_vars):
        url_vars = [
            ('host', row['host_name']),
        ]

        if row.get('site'):
            url_vars.append(('site', row['site']))

        if what == 'service':
            url_vars.append(('service', row['service_description']))

        if html.request.has_var('display_options'):
            url_vars.append(
                ('display_options', html.request.var('display_options')))
        if html.request.has_var('_display_options'):
            url_vars.append(
                ('_display_options', html.request.var('_display_options')))
        url_vars.append(('_back_url', makeuri(request, [])))

        return html.render_popup_trigger(
            html.render_icon('menu',
                             _('Open the action menu'),
                             cssclass="iconbutton"),
            'action_menu',
            MethodAjax(endpoint='action_menu', url_vars=url_vars),
        )
Пример #10
0
def render_metrics_table(translated_metrics, host_name, service_description):
    output = "<table class=metricstable>"
    for metric_name, metric in sorted(translated_metrics.items(),
                                      key=lambda x: x[1]["title"]):
        output += "<tr>"
        output += "<td class=color>%s</td>" % render_color_icon(
            metric["color"])
        output += "<td>%s:</td>" % metric["title"]
        output += "<td class=value>%s</td>" % metric["unit"]["render"](
            metric["value"])
        if cmk_graphs_possible():
            output += "<td>"
            output += html.render_popup_trigger(
                html.render_icon("custom_graph",
                                 title=_("Add this metric to dedicated graph"),
                                 cssclass="iconbutton"),
                ident="add_metric_to_graph_" + host_name + ";" +
                service_description,
                what="add_metric_to_graph",
                url_vars=[
                    ("host", host_name),
                    ("service", service_description),
                    ("metric", metric_name),
                ])
            output += "</td>"
        output += "</tr>"
    output += "</table>"
    return output
Пример #11
0
def render_metrics_table(translated_metrics, host_name, service_description):
    # type: (TranslatedMetrics, str, str) -> str
    # TODO: Don't paste together strings by hand, use our HTML utilities.
    output = "<table class=metricstable>"
    for metric_name, metric in sorted(translated_metrics.items(), key=lambda x: x[1]["title"]):
        output += "<tr>"
        output += "<td class=color>%s</td>" % render_color_icon(metric["color"])
        output += "<td>%s:</td>" % metric["title"]
        output += "<td class=value>%s</td>" % metric["unit"]["render"](metric["value"])
        if not cmk_version.is_raw_edition():
            output += "<td>"
            output += str(
                html.render_popup_trigger(
                    html.render_icon("custom_graph",
                                     title=_("Add this metric to dedicated graph"),
                                     cssclass="iconbutton"),
                    ident="add_metric_to_graph_" + host_name + ";" + str(service_description),
                    what="add_metric_to_graph",
                    url_vars=[
                        ("host", host_name),
                        ("service", service_description),
                        ("metric", metric_name),
                    ]))
            output += "</td>"
        output += "</tr>"
    output += "</table>"
    return output
Пример #12
0
    def _pnp_icon(self, row, what):
        url = self._pnp_graph_icon_link(row, what)

        if not metrics.cmk_graphs_possible(row["site"]):
            # Directly ask PNP for all data, don't try to use the new graph fetching mechanism
            # to keep the number of single requests low
            force_pnp_graphing = True
        else:
            # Don't show the icon with Check_MK graphing. The hover makes no sense and there is no
            # mobile view for graphs, so the graphs on the bottom of the host/service view are enough
            # for the moment.
            if html.is_mobile():
                return

            force_pnp_graphing = False

        return html.render_a(
            content=html.render_icon('pnp', ''),
            href=url,
            onmouseout="cmk.hover.hide()",
            onmouseover=
            "cmk.graph_integration.show_hover_graphs(event, %s, %s, %s, %s, %s);"
            % (
                json.dumps(row['site']),
                json.dumps(row["host_name"]),
                json.dumps(row.get('service_description', '_HOST_')),
                json.dumps(self._pnp_popup_url(row, what)),
                json.dumps(force_pnp_graphing),
            ))
Пример #13
0
 def _show_content(self, page_state: PageState) -> None:
     html.div(page_state.text, class_="text_container")
     if page_state.icon_name:
         html.div(
             html.render_icon(page_state.icon_name, id_="page_state_icon"),
             class_="icon_container",
         )
Пример #14
0
    def _show_move_to_folder_action(self, obj):
        if isinstance(obj, watolib.Host):
            what = "host"
            what_title = _("host")
            ident = obj.name()
            style = None
        else:
            what = "folder"
            what_title = _("folder")
            ident = obj.path()
            style = "display:none"

        html.popup_trigger(
            html.render_icon("move",
                             title=_("Move this %s to another folder") %
                             what_title,
                             cssclass="iconbutton"),
            ident="move_" + obj.name(),
            what="move_to_folder",
            url_vars=[
                ("what", what),
                ("ident", ident),
                ("back_url", html.makeactionuri([])),
            ],
            style=style,
        )
Пример #15
0
    def page(self) -> None:
        html.p(
            _("Here you can add icons, for example to use them in bookmarks or "
              "in custom actions of views. Allowed are single PNG image files "
              "with a maximum size of 80x80 px. Custom actions have to be defined "
              "in the global settings and can be used in the custom icons rules "
              "of hosts and services."))

        html.begin_form('upload_form', method='POST')
        self._vs_upload().render_input('_upload_icon', None)
        html.hidden_fields()
        html.end_form()

        icons = sorted(self._load_custom_icons().items())
        with table_element("icons", _("Custom Icons")) as table:
            for icon_name, category_name in icons:
                table.row()

                table.cell(_("Actions"), css="buttons")
                delete_url = make_confirm_link(
                    url=make_action_link([("mode", "icons"),
                                          ("_delete", icon_name)]),
                    message=_(
                        "Do you really want to delete the icon <b>%s</b>?") %
                    icon_name,
                )
                html.icon_button(delete_url, _("Delete this Icon"), "delete")

                table.cell(_("Icon"),
                           html.render_icon(icon_name),
                           css="buttons")
                table.cell(_("Name"), icon_name)
                table.cell(_("Category"),
                           IconSelector.category_alias(category_name))
Пример #16
0
    def render(self, what, row, tags, custom_vars):
        url_vars = [
            ("host", row["host_name"]),
        ]

        if row.get("site"):
            url_vars.append(("site", row["site"]))

        if what == "service":
            url_vars.append(("service", row["service_description"]))

        if request.has_var("display_options"):
            url_vars.append(
                ("display_options", request.var("display_options")))
        if request.has_var("_display_options"):
            url_vars.append(
                ("_display_options", request.var("_display_options")))
        url_vars.append(("_back_url", makeuri(request, [])))

        return html.render_popup_trigger(
            html.render_icon("menu",
                             _("Open the action menu"),
                             cssclass="iconbutton"),
            "action_menu",
            MethodAjax(endpoint="action_menu", url_vars=url_vars),
        )
Пример #17
0
    def render(self, what, row, tags, custom_vars):
        img = row[what + '_icon_image']
        if not img:
            return

        if img.endswith('.png'):
            img = img[:-4]

        return html.render_icon(img)
Пример #18
0
    def _show_main_menu_content(self) -> None:
        html.open_li()
        html.popup_trigger(
            html.render_icon("main_search") + html.render_div(_("Search")),
            "mega_menu_search",
            method=MethodInline(self._get_search_menu_content()),
        )
        html.close_li()

        for menu_item in self._get_main_menu_items():
            html.open_li()
            html.popup_trigger(
                html.render_icon(menu_item.icon_name) +
                html.render_div(menu_item.title),
                ident="mega_menu_" + menu_item.name,
                method=MethodInline(self._get_mega_menu_content(menu_item)),
                cssclass=menu_item.name,
            )
            html.close_li()
Пример #19
0
def DocumentationURL():
    return TextAscii(
        title=_("Documentation URL"),
        help=HTML(
            _("An optional URL pointing to documentation or any other page. This will be displayed "
              "as an icon %s and open a new page when clicked. "
              "You can use either global URLs (beginning with <tt>http://</tt>), absolute local urls "
              "(beginning with <tt>/</tt>) or relative URLs (that are relative to <tt>check_mk/</tt>)."
              ) % html.render_icon("url")),
        size=80,
    )
Пример #20
0
    def _show_subtree(self, tree, path, show_host):
        if self._is_leaf(tree):
            self._show_leaf(tree, show_host)
            return

        html.open_span(class_="title")

        is_empty = len(tree[3]) == 0
        if is_empty:
            mc = None
        else:
            mc = self._get_mousecode(path)

        css_class = "open" if self._is_open(path) else "closed"

        with self._show_node(tree,
                             show_host,
                             mousecode=mc,
                             img_class=css_class):
            if tree[2].get("icon"):
                html.write_html(html.render_icon(tree[2]["icon"]))
                html.write_text("&nbsp;")

            if tree[2].get("docu_url"):
                html.icon_button(
                    tree[2]["docu_url"],
                    _("Context information about this rule"),
                    "url",
                    target="_blank",
                )
                html.write_text("&nbsp;")

            html.write_text(tree[2]["title"])

        if not is_empty:
            html.open_ul(
                id_="%d:%s" %
                (self._expansion_level or 0, self._path_id(path)),
                class_=["subtree", css_class],
            )

            if not self._omit_content(path):
                for node in tree[3]:
                    if not node[2].get("hidden"):
                        new_path = path + [node[2]["title"]]
                        html.open_li()
                        self._show_subtree(node, new_path, show_host)
                        html.close_li()

            html.close_ul()

        html.close_span()
Пример #21
0
    def page(self):
        if not self._folder.may("read"):
            html.show_message(
                html.render_icon("autherr", cssclass="authicon") + " " +
                self._folder.reason_why_may_not("read"))

        self._folder.show_locking_information()
        self._show_subfolders_of()
        if self._folder.may("read"):
            self._show_hosts()

        if not self._folder.has_hosts():
            if self._folder.is_search_folder():
                html.show_message(_("No matching hosts found."))
            elif not self._folder.has_subfolders() and self._folder.may("write"):
                self._show_empty_folder_menu()
Пример #22
0
def render_graph_add_to_icon_for_popup(graph_artwork, graph_data_range, graph_render_options):
    icon_html = html.render_icon('menu', _('Add this graph to...'))
    element_type_name = "pnpgraph"

    # Data will be transferred via URL and Javascript magic eventually
    # to our function popup_add_element (htdocs/reporting.py)
    # argument report_name --> provided by popup system
    # further arguments:
    return html.render_popup_trigger(
        content=icon_html,
        ident='add_visual',
        method=MethodAjax(endpoint='add_visual', url_vars=[("add_type", "pnpgraph")]),
        data=[
            element_type_name, None,
            graph_ajax_context(graph_artwork, graph_data_range, graph_render_options)
        ],
        style="z-index:2")  # Ensures that graph canvas does not cover it
Пример #23
0
    def _pnp_icon(self, row, what):
        url = self._graph_icon_link(row, what)

        # Don't show the icon with Checkmk graphing. The hover makes no sense and there is no
        # mobile view for graphs, so the graphs on the bottom of the host/service view are enough
        # for the moment.
        if html.is_mobile():
            return

        return html.render_a(
            content=html.render_icon('graph', ''),
            href=url,
            onmouseout="cmk.hover.hide()",
            onmouseover="cmk.graph_integration.show_hover_graphs(event, %s, %s, %s);" % (
                json.dumps(row['site']),
                json.dumps(row["host_name"]),
                json.dumps(row['service_description'] if what == "service" else '_HOST_'),
            ))
Пример #24
0
        def render_list(ids, links):
            n = 0
            for entry in links:
                n += 1
                try:
                    if isinstance(entry[1], type(True)):
                        idss = ids + [str(n)]
                        id_ = '/'.join(idss)
                        html.begin_foldable_container("customlinks",
                                                      id_,
                                                      isopen=entry[1],
                                                      title=entry[0],
                                                      icon="foldable_sidebar")
                        render_list(idss, entry[2])
                        html.end_foldable_container()
                    elif isinstance(entry[1], str):
                        frame = entry[3] if len(entry) > 3 else "main"

                        if len(entry) > 2 and entry[2]:
                            icon_file = entry[2]

                            # Old configs used files named "link_<name>.gif". Those .gif files have
                            # been removed from Checkmk. Replacing such images with the default icon
                            if icon_file.endswith(".gif"):
                                icon_name = "link"
                            else:
                                icon_name = icon_file.rsplit(".",
                                                             1)[0].replace(
                                                                 "icon_", "")
                        else:
                            icon_name = "link"

                        linktext = HTML(
                            html.render_icon(icon_name) + " " + entry[0])

                        simplelink(linktext, entry[1], frame)
                    else:
                        html.write_text(
                            _("Second part of tuple must be list or string, not %s\n"
                              ) % str(entry[1]))
                except Exception as e:
                    html.write_text(
                        _("invalid entry %s: %s<br>\n") % (entry, e))
Пример #25
0
    def _show_popup(self, entry: PageMenuEntry) -> None:
        assert isinstance(entry.item, PageMenuPopup)

        if entry.name is None:
            raise ValueError('Missing "name" attribute on entry "%s"' % entry.title)

        classes: List[Optional[str]] = ["page_menu_popup"]
        classes += entry.item.css_classes
        if isinstance(entry.item, PageMenuSidePopup):
            classes.append("side_popup")

        popup_id = "popup_%s" % entry.name
        html.open_div(id_=popup_id, class_=classes)

        html.open_div(class_="head")
        html.h3(entry.title)
        html.a(
            html.render_icon("close"),
            class_="close_popup",
            href="javascript:void(0)",
            onclick="cmk.page_menu.close_popup(this)",
        )
        html.close_div()

        if (
            isinstance(entry.item, PageMenuSidePopup)
            and entry.item.content
            and "side_popup_content" not in entry.item.content
        ):
            raise RuntimeError(
                'Add a div container with the class "side_popup_content" to the popup content'
            )

        html.open_div(class_="content")
        html.write_html(entry.item.content)
        html.close_div()
        html.close_div()

        if isinstance(entry.item, PageMenuSidePopup):
            html.final_javascript(
                "cmk.page_menu.side_popup_add_simplebar_scrollbar(%s);" % json.dumps(popup_id)
            )
Пример #26
0
    def _show_popup(self, entry: PageMenuEntry) -> None:
        assert isinstance(entry.item, PageMenuPopup)

        if entry.name is None:
            raise ValueError("Missing \"name\" attribute on entry \"%s\"" %
                             entry.title)

        html.open_div(id_="popup_%s" % entry.name,
                      class_=["page_menu_popup"] +
                      html.normalize_css_spec(entry.item.css_classes))

        html.open_div(class_="head")
        html.h3(entry.title)
        html.a(html.render_icon("close"),
               class_="close_popup",
               href="javascript:void(0)",
               onclick="cmk.page_menu.close_popup(this)")
        html.close_div()

        html.open_div(class_="content")
        html.write(HTML(entry.item.content))
        html.close_div()

        html.close_div()
Пример #27
0
    def _show_host_row(self, rendered_hosts, table, hostname, search_text,
                       show_checkboxes, colspan, host_errors,
                       contact_group_names):
        if search_text and (search_text.lower() not in hostname.lower()):
            return

        host = self._folder.host(hostname)
        rendered_hosts.append(hostname)
        effective = host.effective_attributes()

        table.row()

        # Column with actions (buttons)

        if show_checkboxes:
            table.cell(html.render_input(
                "_toggle_group",
                type_="button",
                class_="checkgroup",
                onclick="cmk.selection.toggle_all_rows();",
                value='X'),
                       sortable=False,
                       css="checkbox")
            # Use CSS class "failed" in order to provide information about
            # selective toggling inventory-failed hosts for Javascript
            html.input(name="_c_%s" % hostname,
                       type_="checkbox",
                       value=colspan,
                       class_="failed" if host.discovery_failed() else None)
            html.label("", "_c_%s" % hostname)

        table.cell(_("Actions"), css="buttons", sortable=False)
        self._show_host_actions(host)

        # Hostname with link to details page (edit host)
        table.cell(_("Hostname"))
        errors = host_errors.get(hostname, []) + host.validation_errors()
        if errors:
            msg = _("Warning: This host has an invalid configuration: ")
            msg += ", ".join(errors)
            html.icon(msg, "validation_error")
            html.nbsp()

        if host.is_offline():
            html.icon(_("This host is disabled"), "disabled")
            html.nbsp()

        if host.is_cluster():
            html.icon(
                _("This host is a cluster of %s") %
                ", ".join(host.cluster_nodes()), "cluster")
            html.nbsp()

        html.a(hostname, href=host.edit_url())

        # Show attributes
        for attr in host_attribute_registry.attributes():
            if attr.show_in_table():
                attrname = attr.name()
                if attrname in host.attributes():
                    tdclass, tdcontent = attr.paint(
                        host.attributes()[attrname], hostname)
                else:
                    tdclass, tdcontent = attr.paint(effective.get(attrname),
                                                    hostname)
                    tdclass += " inherited"
                table.cell(attr.title(),
                           escaping.escape_attribute(tdcontent),
                           css=tdclass)

        # Am I authorized?
        reason = host.reason_why_may_not("read")
        if not reason:
            icon = "authok"
            title = _("You have permission to this host.")
        else:
            icon = "autherr"
            title = escaping.strip_tags(reason)

        table.cell(_('Auth'),
                   html.render_icon(icon, title),
                   css="buttons",
                   sortable=False)

        # Permissions and Contact groups - through complete recursion and inhertance
        permitted_groups, host_contact_groups, _use_for_services = host.groups(
        )
        table.cell(
            _("Permissions"),
            HTML(", ").join([
                self._render_contact_group(contact_group_names, g)
                for g in permitted_groups
            ]))
        table.cell(
            _("Contact Groups"),
            HTML(", ").join([
                self._render_contact_group(contact_group_names, g)
                for g in host_contact_groups
            ]))

        if not config.wato_hide_hosttags:
            table.cell(_("Tags"), css="tag-ellipsis")
            tag_groups, show_all_code = self._limit_labels(host.tag_groups())
            html.write(
                cmk.gui.view_utils.render_tag_groups(tag_groups,
                                                     "host",
                                                     with_links=False))
            html.write(show_all_code)

        table.cell(_("Explicit labels"), css="tag-ellipsis")
        labels, show_all_code = self._limit_labels(host.labels())
        html.write(
            cmk.gui.view_utils.render_labels(
                labels,
                "host",
                with_links=False,
                label_sources={k: "explicit"
                               for k in labels.keys()}))
        html.write(show_all_code)

        # Located in folder
        if self._folder.is_search_folder():
            table.cell(_("Folder"))
            html.a(host.folder().alias_path(), href=host.folder().url())