Ejemplo n.º 1
0
    def _activation_status(self):
        with table_element("site-status",
                           searchable=False,
                           sortable=False,
                           css="activation") as table:

            for site_id, site in sort_sites(
                    cmk.gui.watolib.changes.activation_sites()):
                table.row()

                site_status, status = self._get_site_status(site_id, site)

                is_online = self._site_is_online(status)
                is_logged_in = self._site_is_logged_in(site_id, site)
                has_foreign = self._site_has_foreign_changes(site_id)
                can_activate_all = not has_foreign or config.user.may(
                    "wato.activateforeign")

                # Disable actions for offline sites and not logged in sites
                if not is_online or not is_logged_in:
                    can_activate_all = False

                need_restart = self._is_activate_needed(site_id)
                need_sync = self.is_sync_needed(site_id)
                need_action = need_restart or need_sync

                # Activation checkbox
                table.cell("", css="buttons")
                if can_activate_all:
                    html.checkbox("site_%s" % site_id,
                                  cssclass="site_checkbox")

                # Iconbuttons
                table.cell(_("Actions"), css="buttons")

                if config.user.may("wato.sites"):
                    edit_url = watolib.folder_preserving_link([
                        ("mode", "edit_site"), ("edit", site_id)
                    ])
                    html.icon_button(edit_url,
                                     _("Edit the properties of this site"),
                                     "edit")

                # State
                if can_activate_all and need_sync:
                    html.icon_button(
                        url="javascript:void(0)",
                        id_="activate_%s" % site_id,
                        cssclass="activate_site",
                        title=
                        _("This site is not update and needs a replication. Start it now."
                          ),
                        icon="need_replicate",
                        onclick=
                        "cmk.activation.activate_changes(\"site\", \"%s\")" %
                        site_id)

                if can_activate_all and need_restart:
                    html.icon_button(
                        url="javascript:void(0)",
                        id_="activate_%s" % site_id,
                        cssclass="activate_site",
                        title=
                        _("This site needs a restart for activating the changes. Start it now."
                          ),
                        icon="need_restart",
                        onclick=
                        "cmk.activation.activate_changes(\"site\", \"%s\")" %
                        site_id)

                if can_activate_all and not need_action:
                    html.icon("siteuptodate", _("This site is up-to-date."))

                site_url = site.get("multisiteurl")
                if site_url:
                    html.icon_button(
                        site_url,
                        _("Open this site's local web user interface"),
                        "url",
                        target="_blank")

                table.text_cell(_("Site"),
                                site.get("alias", site_id),
                                css="narrow nobr")

                # Livestatus
                table.cell(_("Status"), css="narrow nobr")
                html.status_label(content=status,
                                  status=status,
                                  title=_("This site is %s") % status)

                # Livestatus-/Checkmk-Version
                table.cell(_("Version"),
                           site_status.get("livestatus_version", ""),
                           css="narrow nobr")

                table.cell(_("Changes"),
                           "%d" % len(self._changes_of_site(site_id)),
                           css="number narrow nobr")

                table.cell(_("Progress"), css="repprogress")
                html.open_div(id_="site_%s_status" % site_id, class_=["msg"])
                html.close_div()
                html.open_div(id_="site_%s_progress" % site_id,
                              class_=["progress"])
                html.close_div()

                table.cell(_("Details"), css="details")
                html.open_div(id_="site_%s_details" % site_id)

                last_state = self._last_activation_state(site_id)

                if not is_logged_in:
                    html.write_text(_("Is not logged in.") + " ")

                if not last_state:
                    html.write_text(_("Has never been activated"))
                elif (need_action and last_state["_state"]
                      == cmk.gui.watolib.activate_changes.STATE_SUCCESS):
                    html.write_text(_("Activation needed"))
                else:
                    if html.request.has_var("_finished"):
                        label = _("State")
                    else:
                        label = _("Last state")

                    html.write_text("%s: %s. " %
                                    (label, last_state["_status_text"]))
                    if last_state["_status_details"]:
                        html.write(last_state["_status_details"])

                    html.javascript(
                        "cmk.activation.update_site_activation_state(%s);" %
                        json.dumps(last_state))

                html.close_div()
Ejemplo n.º 2
0
 def _show_tag_list(self) -> None:
     with table_element("tag_usage", _("Tags")) as table:
         for tag_group in self._effective_config.tag_groups:
             for tag in tag_group.tags:
                 self._show_tag_row(table, tag_group, tag)
Ejemplo n.º 3
0
 def _show_aux_tag_list(self) -> None:
     with table_element("aux_tag_usage", _("Auxiliary tags")) as table:
         for aux_tag in self._effective_config.aux_tag_list.get_tags():
             self._show_aux_tag_row(table, aux_tag)
Ejemplo n.º 4
0
    def _show_patterns(self):
        import cmk.gui.logwatch as logwatch

        collection = watolib.SingleRulesetRecursively("logwatch_rules")
        collection.load()
        ruleset = collection.get("logwatch_rules")

        html.h3(_("Logfile patterns"))
        if ruleset.is_empty():
            html.open_div(class_="info")
            html.write_text(
                "There are no logfile patterns defined. You may create "
                'logfile patterns using the <a href="%s">Rule Editor</a>.' %
                watolib.folder_preserving_link([
                    ("mode", "edit_ruleset"),
                    ("varname", "logwatch_rules"),
                ]))
            html.close_div()

        # Loop all rules for this ruleset
        already_matched = False
        abs_rulenr = 0
        for folder, rulenr, rule in ruleset.get_rules():
            # Check if this rule applies to the given host/service
            if self._hostname:
                service_desc = self._get_service_description(
                    self._hostname, "logwatch", self._item)

                # If hostname (and maybe filename) try match it
                rule_matches = rule.matches_host_and_item(
                    watolib.Folder.current(), self._hostname, self._item,
                    service_desc)
            else:
                # If no host/file given match all rules
                rule_matches = True

            with foldable_container(
                    treename="rule",
                    id_=str(abs_rulenr),
                    isopen=True,
                    title=HTML("<b>Rule #%d</b>" % (abs_rulenr + 1)),
                    indent=False,
            ), table_element("pattern_editor_rule_%d" % abs_rulenr,
                             sortable=False,
                             css="logwatch") as table:
                abs_rulenr += 1

                # TODO: What's this?
                pattern_list = rule.value
                if isinstance(pattern_list, dict):
                    pattern_list = pattern_list["reclassify_patterns"]

                # Each rule can hold no, one or several patterns. Loop them all here
                for state, pattern, comment in pattern_list:
                    match_class = ""
                    disp_match_txt = HTML("")
                    match_img = ""
                    if rule_matches:
                        # Applies to the given host/service
                        matched = re.search(pattern, self._match_txt)
                        if matched:

                            # Prepare highlighted search txt
                            match_start = matched.start()
                            match_end = matched.end()
                            disp_match_txt = (
                                escape_html_permissive(
                                    self._match_txt[:match_start]) +
                                html.render_span(
                                    self._match_txt[match_start:match_end],
                                    class_="match") + escape_html_permissive(
                                        self._match_txt[match_end:]))

                            if not already_matched:
                                # First match
                                match_class = "match first"
                                match_img = "match"
                                match_title = _(
                                    "This logfile pattern matches first and will be used for "
                                    "defining the state of the given line.")
                                already_matched = True
                            else:
                                # subsequent match
                                match_class = "match"
                                match_img = "imatch"
                                match_title = _(
                                    "This logfile pattern matches but another matched first."
                                )
                        else:
                            match_img = "nmatch"
                            match_title = _(
                                "This logfile pattern does not match the given string."
                            )
                    else:
                        # rule does not match
                        match_img = "nmatch"
                        match_title = _("The rule conditions do not match.")

                    table.row()
                    table.cell(_("Match"))
                    html.icon("rule%s" % match_img, match_title)

                    cls: List[str] = []
                    if match_class == "match first":
                        cls = [
                            "state%d" % logwatch.level_state(state),
                            "fillbackground"
                        ]
                    table.cell(_("State"),
                               html.render_span(logwatch.level_name(state)),
                               css=cls)
                    table.cell(_("Pattern"), html.render_tt(pattern))
                    table.cell(_("Comment"), comment)
                    table.cell(_("Matched line"), disp_match_txt)

                table.row(fixed=True)
                table.cell(colspan=5)
                edit_url = watolib.folder_preserving_link([
                    ("mode", "edit_rule"),
                    ("varname", "logwatch_rules"),
                    ("rulenr", rulenr),
                    ("item", watolib.mk_repr(self._item).decode()),
                    ("rule_folder", folder.path()),
                    ("rule_id", rule.id),
                ])
                html.icon_button(edit_url, _("Edit this rule"), "edit")
Ejemplo n.º 5
0
    def page(self):
        with table_element("roles") as table:

            users = userdb.load_users()
            for rid, role in sorted(self._roles.items(),
                                    key=lambda a: (a[1]["alias"], a[0])):
                table.row()

                # Actions
                table.cell(_("Actions"), css="buttons")
                edit_url = watolib.folder_preserving_link([("mode",
                                                            "edit_role"),
                                                           ("edit", rid)])
                clone_url = make_action_link([("mode", "roles"),
                                              ("_clone", rid)])
                delete_url = make_confirm_link(
                    url=make_action_link([("mode", "roles"),
                                          ("_delete", rid)]),
                    message=_("Do you really want to delete the role %s?") %
                    rid,
                )
                html.icon_button(edit_url, _("Properties"), "edit")
                html.icon_button(clone_url, _("Clone"), "clone")
                if not role.get("builtin"):
                    html.icon_button(delete_url, _("Delete this role"),
                                     "delete")

                # ID
                table.cell(_("Name"), rid)

                # Alias
                table.cell(_("Alias"), role["alias"])

                # Type
                table.cell(
                    _("Type"),
                    _("builtin") if role.get("builtin") else _("custom"))

                # Modifications
                table.cell(
                    _("Modifications"),
                    html.render_span(
                        str(len(role["permissions"])),
                        title=
                        _("That many permissions do not use the factory defaults."
                          ),
                    ),
                )

                # Users
                table.cell(
                    _("Users"),
                    HTML(", ").join([
                        html.render_a(
                            user.get("alias", user_id),
                            watolib.folder_preserving_link([
                                ("mode", "edit_user"), ("edit", user_id)
                            ]),
                        ) for (user_id, user) in users.items()
                        if rid in user["roles"]
                    ]),
                )
Ejemplo n.º 6
0
    def _show_user_list(self):
        visible_custom_attrs = [
            (name, attr) for name, attr in userdb.get_user_attributes() if attr.show_in_table()
        ]

        users = userdb.load_users()

        entries = users.items()

        html.begin_form("bulk_delete_form", method="POST")

        roles = userdb.load_roles()
        timeperiods = watolib.timeperiods.load_timeperiods()
        contact_groups = load_contact_group_information()

        with table_element("users", None, empty_text=_("No users are defined yet.")) as table:
            online_threshold = time.time() - config.user_online_maxage
            for uid, user in sorted(entries, key=lambda x: x[1].get("alias", x[0]).lower()):
                table.row()

                # Checkboxes
                table.cell(html.render_input("_toggle_group",
                                             type_="button",
                                             class_="checkgroup",
                                             onclick="cmk.selection.toggle_all_rows();",
                                             value='X'),
                           sortable=False,
                           css="checkbox")

                if uid != config.user.id:
                    html.checkbox("_c_user_%s" % ensure_str(base64.b64encode(uid.encode("utf-8"))))

                user_connection_id = cleanup_connection_id(user.get('connector'))
                connection = get_connection(user_connection_id)

                # Buttons
                table.cell(_("Actions"), css="buttons")
                if connection:  # only show edit buttons when the connector is available and enabled
                    edit_url = watolib.folder_preserving_link([("mode", "edit_user"),
                                                               ("edit", uid)])
                    html.icon_button(edit_url, _("Properties"), "edit")

                    clone_url = watolib.folder_preserving_link([("mode", "edit_user"),
                                                                ("clone", uid)])
                    html.icon_button(clone_url, _("Create a copy of this user"), "clone")

                delete_url = make_action_link([("mode", "users"), ("_delete", uid)])
                html.icon_button(delete_url, _("Delete"), "delete")

                notifications_url = watolib.folder_preserving_link([("mode", "user_notifications"),
                                                                    ("user", uid)])
                if watolib.load_configuration_settings().get("enable_rulebased_notifications"):
                    html.icon_button(notifications_url, _("Custom notification table of this user"),
                                     "notifications")

                # ID
                table.cell(_("ID"), uid)

                # Online/Offline
                if config.save_user_access_times:
                    last_seen = user.get('last_seen', 0)
                    if last_seen >= online_threshold:
                        title = _('Online')
                        img_txt = 'online'
                    elif last_seen != 0:
                        title = _('Offline')
                        img_txt = 'offline'
                    elif last_seen == 0:
                        title = _('Never logged in')
                        img_txt = 'inactive'

                    title += ' (%s %s)' % (render.date(last_seen), render.time_of_day(last_seen))
                    table.cell(_("Act."))
                    html.icon(title, img_txt)

                    table.cell(_("Last seen"))
                    if last_seen != 0:
                        html.write_text("%s %s" %
                                        (render.date(last_seen), render.time_of_day(last_seen)))
                    else:
                        html.write_text(_("Never logged in"))

                if cmk_version.is_managed_edition():
                    table.cell(_("Customer"), managed.get_customer_name(user))

                # Connection
                if connection:
                    table.cell(_("Connection"),
                               '%s (%s)' % (connection.short_title(), user_connection_id))
                    locked_attributes = userdb.locked_attributes(user_connection_id)
                else:
                    table.cell(_("Connection"),
                               "%s (%s) (%s)" % (_("UNKNOWN"), user_connection_id, _("disabled")),
                               css="error")
                    locked_attributes = []

                # Authentication
                if "automation_secret" in user:
                    auth_method = _("Automation")
                elif user.get("password") or 'password' in locked_attributes:
                    auth_method = _("Password")
                else:
                    auth_method = "<i>%s</i>" % _("none")
                table.cell(_("Authentication"), auth_method)

                table.cell(_("State"))
                if user.get("locked", False):
                    html.icon(_('The login is currently locked'), 'user_locked')

                if "disable_notifications" in user and isinstance(user["disable_notifications"],
                                                                  bool):
                    disable_notifications_opts = {"disable": user["disable_notifications"]}
                else:
                    disable_notifications_opts = user.get("disable_notifications", {})

                if disable_notifications_opts.get("disable", False):
                    html.icon(_('Notifications are disabled'), 'notif_disabled')

                # Full name / Alias
                table.text_cell(_("Alias"), user.get("alias", ""))

                # Email
                table.text_cell(_("Email"), user.get("email", ""))

                # Roles
                table.cell(_("Roles"))
                if user.get("roles", []):
                    role_links = [(watolib.folder_preserving_link([("mode", "edit_role"),
                                                                   ("edit", role)]),
                                   roles[role].get("alias")) for role in user["roles"]]
                    html.write_html(
                        HTML(", ").join(
                            html.render_a(alias, href=link) for (link, alias) in role_links))

                # contact groups
                table.cell(_("Contact groups"))
                cgs = user.get("contactgroups", [])
                if cgs:
                    cg_aliases = [
                        contact_groups[c]['alias'] if c in contact_groups else c for c in cgs
                    ]
                    cg_urls = [
                        watolib.folder_preserving_link([("mode", "edit_contact_group"),
                                                        ("edit", c)]) for c in cgs
                    ]
                    html.write_html(
                        HTML(", ").join(
                            html.render_a(content, href=url)
                            for (content, url) in zip(cg_aliases, cg_urls)))
                else:
                    html.i(_("none"))

                #table.cell(_("Sites"))
                #html.write(vs_authorized_sites().value_to_text(user.get("authorized_sites",
                #                                                vs_authorized_sites().default_value())))

                # notifications
                if not watolib.load_configuration_settings().get("enable_rulebased_notifications"):
                    table.cell(_("Notifications"))
                    if not cgs:
                        html.i(_("not a contact"))
                    elif not user.get("notifications_enabled", True):
                        html.write_text(_("disabled"))
                    elif user.get("host_notification_options", "") == "" and \
                         user.get("service_notification_options", "") == "":
                        html.write_text(_("all events disabled"))
                    else:
                        tp = user.get("notification_period", "24X7")
                        if tp not in timeperiods:
                            tp = tp + _(" (invalid)")
                        elif tp not in watolib.timeperiods.builtin_timeperiods():
                            url = watolib.folder_preserving_link([("mode", "edit_timeperiod"),
                                                                  ("edit", tp)])
                            tp = html.render_a(timeperiod_spec_alias(timeperiods[tp], tp), href=url)
                        else:
                            tp = timeperiod_spec_alias(timeperiods[tp], tp)
                        html.write(tp)

                # the visible custom attributes
                for name, attr in visible_custom_attrs:
                    vs = attr.valuespec()
                    table.cell(escaping.escape_attribute(_u(vs.title())))
                    html.write(vs.value_to_text(user.get(name, vs.default_value())))

        html.button("_bulk_delete_users", _("Bulk Delete"), "submit", style="margin-top:10px")
        html.hidden_fields()
        html.end_form()

        if not load_contact_group_information():
            url = "wato.py?mode=contact_groups"
            html.open_div(class_="info")
            html.write(
                _("Note: you haven't defined any contact groups yet. If you <a href='%s'>"
                  "create some contact groups</a> you can assign users to them und thus "
                  "make them monitoring contacts. Only monitoring contacts can receive "
                  "notifications.") % url)
            html.write(" you can assign users to them und thus "
                       "make them monitoring contacts. Only monitoring contacts can receive "
                       "notifications.")
            html.close_div()
Ejemplo n.º 7
0
    def _show_patterns(self):
        import cmk.gui.logwatch as logwatch
        collection = watolib.SingleRulesetRecursively("logwatch_rules")
        collection.load()
        ruleset = collection.get("logwatch_rules")

        html.h3(_('Logfile Patterns'))
        if ruleset.is_empty():
            html.open_div(class_="info")
            html.write_text(
                'There are no logfile patterns defined. You may create '
                'logfile patterns using the <a href="%s">Rule Editor</a>.' %
                watolib.folder_preserving_link([
                    ('mode', 'edit_ruleset'),
                    ('varname', 'logwatch_rules'),
                ]))
            html.close_div()

        # Loop all rules for this ruleset
        already_matched = False
        abs_rulenr = 0
        for folder, rulenr, rule in ruleset.get_rules():
            # Check if this rule applies to the given host/service
            if self._hostname:
                service_desc = self._get_service_description(
                    self._hostname, "logwatch", self._item)

                # If hostname (and maybe filename) try match it
                rule_matches = rule.matches_host_and_item(
                    watolib.Folder.current(), self._hostname, self._item,
                    service_desc)
            else:
                # If no host/file given match all rules
                rule_matches = True

            html.begin_foldable_container("rule",
                                          "%s" % abs_rulenr,
                                          True,
                                          HTML("<b>Rule #%d</b>" %
                                               (abs_rulenr + 1)),
                                          indent=False)
            with table_element("pattern_editor_rule_%d" % abs_rulenr,
                               sortable=False) as table:
                abs_rulenr += 1

                # TODO: What's this?
                pattern_list = rule.value
                if isinstance(pattern_list, dict):
                    pattern_list = pattern_list["reclassify_patterns"]

                # Each rule can hold no, one or several patterns. Loop them all here
                for state, pattern, comment in pattern_list:
                    match_class = ''
                    disp_match_txt = HTML('')
                    match_img = ''
                    if rule_matches:
                        # Applies to the given host/service
                        reason_class = 'reason'

                        matched = re.search(pattern, self._match_txt)
                        if matched:

                            # Prepare highlighted search txt
                            match_start = matched.start()
                            match_end = matched.end()
                            disp_match_txt = html.render_text(self._match_txt[:match_start]) \
                                             + html.render_span(self._match_txt[match_start:match_end], class_="match")\
                                             + html.render_text(self._match_txt[match_end:])

                            if not already_matched:
                                # First match
                                match_class = 'match first'
                                match_img = 'match'
                                match_title = _(
                                    'This logfile pattern matches first and will be used for '
                                    'defining the state of the given line.')
                                already_matched = True
                            else:
                                # subsequent match
                                match_class = 'match'
                                match_img = 'imatch'
                                match_title = _(
                                    'This logfile pattern matches but another matched first.'
                                )
                        else:
                            match_img = 'nmatch'
                            match_title = _(
                                'This logfile pattern does not match the given string.'
                            )
                    else:
                        # rule does not match
                        reason_class = 'noreason'
                        match_img = 'nmatch'
                        match_title = _('The rule conditions do not match.')

                    table.row(css=reason_class)
                    table.cell(_('Match'))
                    html.icon(match_title, "rule%s" % match_img)

                    cls = ''
                    if match_class == 'match first':
                        cls = 'svcstate state%d' % logwatch.level_state(state)
                    table.cell(_('State'), logwatch.level_name(state), css=cls)
                    table.cell(_('Pattern'), html.render_tt(pattern))
                    table.cell(_('Comment'), html.render_text(comment))
                    table.cell(_('Matched line'), disp_match_txt)

                table.row(fixed=True)
                table.cell(colspan=5)
                edit_url = watolib.folder_preserving_link([
                    ("mode", "edit_rule"),
                    ("varname", "logwatch_rules"),
                    ("rulenr", rulenr),
                    ("host", self._hostname),
                    ("item", watolib.mk_repr(self._item)),
                    ("rule_folder", folder.path()),
                ])
                html.icon_button(edit_url, _("Edit this rule"), "edit")

            html.end_foldable_container()
Ejemplo n.º 8
0
    def _show_hosts(self):
        if not self._folder.has_hosts():
            return

        show_checkboxes = html.request.var('show_checkboxes', '0') == '1'

        hostnames = self._folder.hosts().keys()
        hostnames.sort(key=utils.key_num_split)
        search_text = html.request.var("search")

        # Helper function for showing bulk actions. This is needed at the bottom
        # of the table of hosts and - if there are more than just a few - also
        # at the top of the table.
        search_shown = False

        # Show table of hosts in this folder
        html.begin_form("hosts", method="POST")
        with table_element("hosts", title=_("Hosts"), searchable=False,
                           omit_empty_columns=True) as table:

            # Remember if that host has a target folder (i.e. was imported with
            # a folder information but not yet moved to that folder). If at least
            # one host has a target folder, then we show an additional bulk action.
            at_least_one_imported = False
            more_than_ten_items = False
            for num, hostname in enumerate(hostnames):
                if search_text and (search_text.lower() not in hostname.lower()):
                    continue

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

                if effective.get("imported_folder"):
                    at_least_one_imported = True

                if num == 11:
                    more_than_ten_items = True

            # Compute colspan for bulk actions
            colspan = 6
            for attr in host_attribute_registry.attributes():
                if attr.show_in_table():
                    colspan += 1
            if not self._folder.locked_hosts() and config.user.may(
                    "wato.edit_hosts") and config.user.may("wato.move_hosts"):
                colspan += 1
            if show_checkboxes:
                colspan += 1
            if self._folder.is_search_folder():
                colspan += 1

            # Add the bulk action buttons also to the top of the table when this
            # list shows more than 10 rows
            if more_than_ten_items and \
                (config.user.may("wato.edit_hosts") or config.user.may("wato.manage_hosts")):
                self._bulk_actions(table, at_least_one_imported, True, True, colspan,
                                   show_checkboxes)
                search_shown = True

            contact_group_names = load_contact_group_information()

            host_errors = self._folder.host_validation_errors()
            rendered_hosts = []

            # Now loop again over all hosts and display them
            for hostname in hostnames:
                self._show_host_row(rendered_hosts, table, hostname, search_text, show_checkboxes,
                                    colspan, host_errors, contact_group_names)

            if config.user.may("wato.edit_hosts") or config.user.may("wato.manage_hosts"):
                self._bulk_actions(table, at_least_one_imported, False, not search_shown, colspan,
                                   show_checkboxes)

        html.hidden_fields()
        html.end_form()

        selected = config.user.get_rowselection(weblib.selection_id(),
                                                'wato-folder-/' + self._folder.path())

        row_count = len(rendered_hosts)
        headinfo = "%d %s" % (row_count, _("host") if row_count == 1 else _("hosts"))
        html.javascript("cmk.utils.update_header_info(%s);" % json.dumps(headinfo))

        if show_checkboxes:
            selection_properties = {
                "page_id": "wato-folder-%s" % ('/' + self._folder.path()),
                "selection_id": weblib.selection_id(),
                "selected_rows": selected,
            }
            html.javascript('cmk.selection.init_rowselect(%s);' %
                            (json.dumps(selection_properties)))
Ejemplo n.º 9
0
    def _preview(self) -> None:
        html.begin_form("preview", method="POST")
        self._preview_form()

        attributes = self._attribute_choices()

        # first line could be missing in situation of import error
        csv_reader = self._open_csv_file()
        if not csv_reader:
            return  # don't try to show preview when CSV could not be read

        html.h2(_("Preview"))
        attribute_list = "<ul>%s</ul>" % "".join(
            ["<li>%s (%s)</li>" % a for a in attributes if a[0] is not None])
        html.help(
            _("This list shows you the first 10 rows from your CSV file in the way the import is "
              "currently parsing it. If the lines are not splitted correctly or the title line is "
              "not shown as title of the table, you may change the import settings above and try "
              "again.") + "<br><br>" +
            _("The first row below the titles contains fields to specify which column of the "
              "CSV file should be imported to which attribute of the created hosts. The import "
              "progress is trying to match the columns to attributes automatically by using the "
              "titles found in the title row (if you have some). "
              "If you use the correct titles, the attributes can be mapped automatically. The "
              "currently available attributes are:") + attribute_list +
            _("You can change these assignments according to your needs and then start the "
              "import by clicking on the <i>Import</i> button above."))

        # Wenn bei einem Host ein Fehler passiert, dann wird die Fehlermeldung zu dem Host angezeigt, so dass man sehen kann, was man anpassen muss.
        # Die problematischen Zeilen sollen angezeigt werden, so dass man diese als Block in ein neues CSV-File eintragen kann und dann diese Datei
        # erneut importieren kann.
        if self._has_title_line:
            try:
                headers = list(next(csv_reader))
            except StopIteration:
                headers = []  # nope, there is no header
        else:
            headers = []

        rows = list(csv_reader)

        # Determine how many columns should be rendered by using the longest column
        num_columns = max([len(r) for r in [headers] + rows])

        with table_element(sortable=False,
                           searchable=False,
                           omit_headers=not self._has_title_line) as table:

            # Render attribute selection fields
            table.row()
            for col_num in range(num_columns):
                header = headers[col_num] if len(headers) > col_num else None
                table.cell(escape_html_permissive(header))
                attribute_varname = "attribute_%d" % col_num
                if request.var(attribute_varname):
                    attribute_method = request.get_ascii_input_mandatory(
                        attribute_varname)
                else:
                    attribute_method = self._try_detect_default_attribute(
                        attributes, header)
                    request.del_var(attribute_varname)

                html.dropdown("attribute_%d" % col_num,
                              attributes,
                              deflt=attribute_method,
                              autocomplete="off")

            # Render sample rows
            for row in rows:
                table.row()
                for cell in row:
                    table.cell(None, cell)

        html.end_form()
Ejemplo n.º 10
0
 def _show_table(self, entries):
     with table_element(self._mode_type.type_name(), self._table_title()) as table:
         for ident, entry in sorted(entries.items(), key=lambda e: e[1]["title"]):
             table.row()
             self._show_row(table, ident, entry)
Ejemplo n.º 11
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()
Ejemplo n.º 12
0
def show_annotations(annotations, av_rawdata, what, avoptions, omit_service):
    annos_to_render = get_relevant_annotations(annotations, av_rawdata, what, avoptions)
    render_date = get_annotation_date_render_function(annos_to_render, avoptions)

    with table_element(title=_("Annotations"), omit_if_empty=True) as table:
        for (site_id, host, service), annotation in annos_to_render:
            table.row()
            table.cell("", css="buttons")
            anno_vars = [
                ("anno_site", site_id),
                ("anno_host", host),
                ("anno_service", service or ""),
                ("anno_from", int(annotation["from"])),
                ("anno_until", int(annotation["until"])),
            ]
            edit_url = html.makeuri(anno_vars)
            html.icon_button(edit_url, _("Edit this annotation"), "edit")
            del_anno: 'HTTPVariables' = [("_delete_annotation", "1")]
            delete_url = html.makeactionuri(del_anno + anno_vars)
            html.icon_button(delete_url, _("Delete this annotation"), "delete")

            if not omit_service:
                if "omit_host" not in avoptions["labelling"]:
                    host_url = "view.py?" + html.urlencode_vars([("view_name", "hoststatus"),
                                                                 ("site", site_id), ("host", host)])
                    table.cell(_("Host"), html.render_a(host, host_url))

                if what == "service":
                    if service:
                        service_url = "view.py?" + html.urlencode_vars([("view_name", "service"),
                                                                        ("site", site_id),
                                                                        ("host", host),
                                                                        ("service", service)])
                        # TODO: honor use_display_name. But we have no display names here...
                        service_name = service
                        table.cell(_("Service"), html.render_a(service_name, service_url))
                    else:
                        table.cell(_("Service"), "")  # Host annotation in service table

            table.cell(_("From"), render_date(annotation["from"]), css="nobr narrow")
            table.cell(_("Until"), render_date(annotation["until"]), css="nobr narrow")
            table.cell("", css="buttons")
            if annotation.get("downtime") is True:
                html.icon(_("This period has been reclassified as a scheduled downtime"),
                          "downtime")
            elif annotation.get("downtime") is False:
                html.icon(
                    _("This period has been reclassified as a not being a scheduled downtime"),
                    "nodowntime")
            recl_host_state = annotation.get("host_state")
            if recl_host_state is not None:
                html.icon(
                    _("This period has been reclassified in host state to state: %s" %
                      host_state_name(recl_host_state)), "status")
            recl_svc_state = annotation.get("service_state")
            if recl_svc_state is not None:
                html.icon(
                    _("This period has been reclassified in service state to state: %s" %
                      service_state_name(recl_svc_state)), "status")

            table.cell(_("Annotation"), html.render_text(annotation["text"]))
            table.cell(_("Author"), annotation["author"])
            table.cell(_("Entry"), render_date(annotation["date"]), css="nobr narrow")
            if not cmk_version.is_raw_edition():
                table.cell(_("Hide in report"),
                           _("Yes") if annotation.get("hide_from_report") else _("No"))
Ejemplo n.º 13
0
def _render_availability_timeline(what: AVObjectType, av_entry: AVEntry, avoptions: AVOptions,
                                  timeline_nr: int) -> None:
    html.open_h3()
    html.write("%s %s" % (_("Timeline of"), availability.object_title(what, av_entry)))
    html.close_h3()

    timeline_rows = av_entry["timeline"]

    if not timeline_rows:
        html.div(_("No information available"), class_="info")
        return

    timeline_layout = availability.layout_timeline(
        what,
        timeline_rows,
        av_entry["considered_duration"],
        avoptions,
        "standalone",
    )

    render_timeline_bar(timeline_layout, "standalone", timeline_nr)

    # Table with detailed events
    with table_element("av_timeline", "", css="timelineevents", sortable=False,
                       searchable=False) as table:
        for row_nr, row in enumerate(timeline_layout["table"]):
            table.row(
                id_="timetable_%d_entry_%d" % (timeline_nr, row_nr),
                onmouseover="cmk.availability.timetable_hover(%d, %d, 1);" % (timeline_nr, row_nr),
                onmouseout="cmk.availability.timetable_hover(%d, %d, 0);" % (timeline_nr, row_nr))

            table.cell(_("Links"), css="buttons")
            if what == "bi":
                url = html.makeuri([("timewarp", str(int(row["from"])))])
                if html.request.var("timewarp") and html.request.get_integer_input_mandatory(
                        "timewarp") == int(row["from"]):
                    html.disabled_icon_button("timewarp_off")
                else:
                    html.icon_button(url,
                                     _("Time warp - show BI aggregate during this time period"),
                                     "timewarp")
            else:
                url = html.makeuri([("anno_site", av_entry["site"]),
                                    ("anno_host", av_entry["host"]),
                                    ("anno_service", av_entry["service"]),
                                    ("anno_from", str(row["from"])),
                                    ("anno_until", str(row["until"]))])
                html.icon_button(url, _("Create an annotation for this period"), "annotation")

            table.cell(_("From"), row["from_text"], css="nobr narrow")
            table.cell(_("Until"), row["until_text"], css="nobr narrow")
            table.cell(_("Duration"), row["duration_text"], css="narrow number")
            table.cell(_("State"), row["state_name"], css=row["css"] + " state narrow")

            if "omit_timeline_plugin_output" not in avoptions["labelling"]:
                table.cell(_("Last Known Plugin Output"),
                           format_plugin_output(row.get("log_output", ""), row))

            if "timeline_long_output" in avoptions["labelling"]:
                table.cell(_("Last Known Long Output"),
                           format_plugin_output(row.get("long_log_output", ""), row))

    # Legend for timeline
    if "display_timeline_legend" in avoptions["labelling"]:
        render_timeline_legend(what)
Ejemplo n.º 14
0
    def page_list(cls):
        cls.load()

        # custom_columns = []
        # render_custom_buttons = None
        # render_custom_columns = None
        # render_custom_context_buttons = None
        # check_deletable_handler = None

        cls.need_overriding_permission("edit")

        html.header(cls.phrase("title_plural"))
        html.begin_context_buttons()
        html.context_button(cls.phrase("new"), cls.create_url(), "new_" + cls.type_name())

        # TODO: Remove this legacy code as soon as views, dashboards and reports have been
        # moved to pagetypes.py
        html.context_button(_("Views"), "edit_views.py", "view")
        html.context_button(_("Dashboards"), "edit_dashboards.py", "dashboard")

        def has_reporting():
            try:
                # The suppression below is OK, we just want to check if the module is there.
                import cmk.gui.cee.reporting as _dummy  # noqa: F401 # pylint: disable=import-outside-toplevel
                return True
            except ImportError:
                return False

        if has_reporting():
            html.context_button(_("Reports"), "edit_reports.py", "report")

        # ## if render_custom_context_buttons:
        # ##     render_custom_context_buttons()

        for other_type_name, other_pagetype in page_types.items():
            if cls.type_name() != other_type_name:
                html.context_button(
                    other_pagetype.phrase("title_plural").title(), '%ss.py' % other_type_name,
                    other_type_name)
        html.end_context_buttons()

        # Deletion
        delname = html.request.var("_delete")
        if delname and html.transaction_valid():
            owner = UserId(html.request.get_unicode_input_mandatory('_owner', config.user.id))

            try:
                instance = cls.instance((owner, delname))
            except KeyError:
                raise MKUserError(
                    "_delete",
                    _("The %s you are trying to delete "
                      "does not exist.") % cls.phrase("title"))

            if not instance.may_delete():
                raise MKUserError("_delete", _("You are not permitted to perform this action."))

            try:
                if owner != config.user.id:
                    owned_by = _(" (owned by %s)") % owner
                else:
                    owned_by = ""
                c = html.confirm(
                    _("Please confirm the deletion of \"%s\"%s.") % (instance.title(), owned_by))
                if c:
                    cls.remove_instance((owner, delname))
                    cls.save_user_instances(owner)
                    html.reload_sidebar()
                elif c is False:
                    html.footer()
                    return
            except MKUserError as e:
                html.user_error(e)

        # Bulk delete
        if html.request.var("_bulk_delete_my") and html.transaction_valid():
            if cls._bulk_delete_after_confirm("my") is False:
                html.footer()
                return

        elif html.request.var("_bulk_delete_foreign") and html.transaction_valid():
            if cls._bulk_delete_after_confirm("foreign") is False:
                html.footer()
                return

        my_instances, foreign_instances, builtin_instances = cls.get_instances()
        for what, title, instances in [
            ("my", _('Customized'), my_instances),
            ("foreign", _('Owned by other users'), foreign_instances),
            ("builtin", _('Builtin'), builtin_instances),
        ]:
            if not instances:
                continue

            html.open_h3()
            html.write(title)
            html.close_h3()

            if what != "builtin":
                html.begin_form("bulk_delete_%s" % what, method="POST")

            with table_element(limit=None) as table:
                for instance in instances:
                    table.row()

                    if what != "builtin" and instance.may_delete():
                        table.cell(html.render_input(
                            "_toggle_group",
                            type_="button",
                            class_="checkgroup",
                            onclick="cmk.selection.toggle_all_rows(this.form);",
                            value='X'),
                                   sortable=False,
                                   css="checkbox")
                        html.checkbox("_c_%s+%s+%s" % (what, instance.owner(), instance.name()))

                    # Actions
                    table.cell(_('Actions'), css='buttons visuals')

                    # View
                    if isinstance(instance, PageRenderer):
                        html.icon_button(instance.page_url(), _("View"), "new_" + cls.type_name())

                    # Clone / Customize
                    html.icon_button(instance.clone_url(), _("Create a customized copy of this"),
                                     "clone")

                    # Delete
                    if instance.may_delete():
                        html.icon_button(instance.delete_url(), _("Delete!"), "delete")

                    # Edit
                    if instance.may_edit():
                        html.icon_button(instance.edit_url(), _("Edit"), "edit")

                    cls.custom_list_buttons(instance)

                    # Internal ID of instance (we call that 'name')
                    table.cell(_('ID'), instance.name(), css="narrow")

                    # Title
                    table.cell(_('Title'))
                    html.write_text(instance.render_title())
                    html.help(_u(instance.description()))

                    # Custom columns specific to that page type
                    instance.render_extra_columns(table)

                    # ## for title, renderer in custom_columns:
                    # ##     table.cell(title, renderer(visual))

                    # Owner
                    if instance.is_builtin():
                        ownertxt = html.render_i(_("builtin"))
                    else:
                        ownertxt = instance.owner()
                    table.cell(_('Owner'), ownertxt)
                    table.cell(_('Public'), _("yes") if instance.is_public() else _("no"))
                    table.cell(_('Hidden'), _("yes") if instance.is_hidden() else _("no"))

                    # FIXME: WTF?!?
                    # TODO: Haeeh? Another custom columns
                    # ## if render_custom_columns:
                    # ##     render_custom_columns(visual_name, visual)

            if what != "builtin":
                html.button("_bulk_delete_%s" % what,
                            _("Bulk delete"),
                            "submit",
                            style="margin-top:10px")
                html.hidden_fields()
                html.end_form()

        html.footer()
        return
Ejemplo n.º 15
0
def render_availability_table(group_title, availability_table, what,
                              avoptions):
    av_table = availability.layout_availability_table(what, group_title,
                                                      availability_table,
                                                      avoptions)

    # TODO: If summary line is activated, then sorting should now move that line to the
    # top. It should also stay at the bottom. This would require an extension to the
    # table.py module.
    with table_element("av_items",
                       av_table["title"],
                       css="availability",
                       searchable=False,
                       limit=None,
                       omit_headers="omit_headers"
                       in avoptions["labelling"]) as table:

        show_urls, show_timeline = False, False
        for row in av_table["rows"]:
            table.row()

            # Column with icons
            timeline_url = None
            if row["urls"]:
                show_urls = True
                table.cell("", css="buttons")
                for image, tooltip, url in row["urls"]:
                    html.icon_button(url, tooltip, image)
                    if image == "timeline":
                        timeline_url = url

            # Column with host/service or aggregate name
            for title, (name, url) in zip(av_table["object_titles"],
                                          row["object"]):
                table.cell(title, html.render_a(name, url))

            if "timeline" in row:
                show_timeline = True
                table.cell(_("Timeline"), css="timeline")
                html.open_a(href=timeline_url)
                render_timeline_bar(row["timeline"], "inline")
                html.close_a()

            # Columns with the actual availability data
            for (title, help_txt), (text, css) in zip(av_table["cell_titles"],
                                                      row["cells"]):
                table.cell(title, text, css=css, help_txt=help_txt)

        if "summary" in av_table:
            table.row(css="summary", fixed=True)
            if show_urls:
                table.cell("", "")  # Empty cell in URLs column
            table.cell("", _("Summary"), css="heading")
            for _x in xrange(1, len(av_table["object_titles"])):
                table.cell("",
                           "")  # empty cells, of more object titles than one
            if show_timeline:
                table.cell("", "")

            for (title, help_txt), (text, css) in zip(av_table["cell_titles"],
                                                      av_table["summary"]):
                table.cell(title,
                           text,
                           css="heading " + css,
                           help_txt=help_txt)
Ejemplo n.º 16
0
    def _show_hosts(self):
        if not self._folder.has_hosts():
            return

        hostnames = sorted(self._folder.hosts().keys(),
                           key=utils.key_num_split)
        search_text = html.request.var("search")

        # Show table of hosts in this folder
        html.begin_form("hosts", method="POST")
        with table_element("hosts",
                           title=_("Hosts"),
                           searchable=False,
                           omit_empty_columns=True) as table:

            # Compute colspan for bulk actions
            colspan = 6
            for attr in host_attribute_registry.attributes():
                if attr.show_in_table():
                    colspan += 1
            if not self._folder.locked_hosts() and config.user.may(
                    "wato.edit_hosts") and config.user.may("wato.move_hosts"):
                colspan += 1
            if self._folder.is_search_folder():
                colspan += 1

            contact_group_names = load_contact_group_information()

            host_errors = self._folder.host_validation_errors()
            rendered_hosts: List[HostName] = []

            # Now loop again over all hosts and display them
            max_hosts = len(hostnames)
            for hostname in hostnames:
                if table.limit_reached:
                    table.limit_hint = max_hosts
                    continue
                self._show_host_row(rendered_hosts, table, hostname,
                                    search_text, colspan, host_errors,
                                    contact_group_names)

        html.hidden_field("selection_id", weblib.selection_id())
        html.hidden_fields()
        html.end_form()

        selected = config.user.get_rowselection(
            weblib.selection_id(), 'wato-folder-/' + self._folder.path())

        row_count = len(hostnames)
        headinfo = "%d %s" % (row_count,
                              _("host") if row_count == 1 else _("hosts"))
        html.javascript("cmk.utils.update_header_info(%s);" %
                        json.dumps(headinfo))

        selection_properties = {
            "page_id": "wato-folder-%s" % ('/' + self._folder.path()),
            "selection_id": weblib.selection_id(),
            "selected_rows": selected,
        }
        html.javascript('cmk.selection.init_rowselect(%s);' %
                        (json.dumps(selection_properties)))