Exemple #1
0
    def buttons(self):
        super(ModeEditHost, self).buttons()

        host_status_button(self._host.name(), "hoststatus")

        html.context_button(
            _("Services"),
            watolib.folder_preserving_link([("mode", "inventory"),
                                            ("host", self._host.name())]),
            "services")
        if watolib.has_agent_bakery() and config.user.may(
                'wato.download_agents'):
            html.context_button(
                _("Monitoring Agent"),
                watolib.folder_preserving_link([("mode", "agent_of_host"),
                                                ("host", self._host.name())]),
                "agents")

        if config.user.may('wato.rulesets'):
            html.context_button(
                _("Parameters"),
                watolib.folder_preserving_link([("mode", "object_parameters"),
                                                ("host", self._host.name())]),
                "rulesets")
            if self._is_cluster():
                html.context_button(
                    _("Clustered Services"),
                    watolib.folder_preserving_link([
                        ("mode", "edit_ruleset"),
                        ("varname", "clustered_services")
                    ]), "rulesets")

        if not watolib.Folder.current().locked_hosts():
            if config.user.may("wato.rename_hosts"):
                html.context_button(
                    self._is_cluster() and _("Rename cluster")
                    or _("Rename host"),
                    watolib.folder_preserving_link([("mode", "rename_host"),
                                                    ("host", self._host.name())
                                                    ]), "rename_host")
            html.context_button(
                self._is_cluster() and _("Delete cluster") or _("Delete host"),
                html.makeactionuri([("delete", "1")]), "delete")

        if not self._is_cluster():
            html.context_button(
                _("Diagnostic"),
                watolib.folder_preserving_link([("mode", "diag_host"),
                                                ("host", self._host.name())]),
                "diagnose")
        html.context_button(_("Update DNS Cache"),
                            html.makeactionuri([("_update_dns_cache", "1")]),
                            "update")
Exemple #2
0
 def buttons(self):
     html.context_button(_("Folder"),
                         watolib.Folder.current().url(), "back")
Exemple #3
0
    def buttons(self):
        global_buttons()
        if not self._folder.is_disk_folder():
            html.context_button(_("Back"), self._folder.parent().url(), "back")
            html.context_button(_("Refine search"),
                                self._folder.url([("mode", "search")]),
                                "search")
            return

        if config.user.may("wato.rulesets") or config.user.may("wato.seeall"):
            html.context_button(
                _("Rulesets"),
                watolib.folder_preserving_link([("mode", "ruleeditor")]),
                "rulesets")
            html.context_button(
                _("Manual checks"),
                watolib.folder_preserving_link([("mode", "static_checks")]),
                "static_checks")
        if self._folder.may("read"):
            html.context_button(_("Folder properties"),
                                self._folder.edit_url(backfolder=self._folder),
                                "edit")
        if not self._folder.locked_subfolders() and config.user.may(
                "wato.manage_folders") and self._folder.may("write"):
            html.context_button(_("New folder"),
                                self._folder.url([("mode", "newfolder")]),
                                "newfolder")
        if not self._folder.locked_hosts() and config.user.may(
                "wato.manage_hosts") and self._folder.may("write"):
            html.context_button(_("New host"),
                                self._folder.url([("mode", "newhost")]), "new")
            html.context_button(_("New cluster"),
                                self._folder.url([("mode", "newcluster")]),
                                "new_cluster")
            html.context_button(_("Bulk import"),
                                self._folder.url([("mode", "bulk_import")]),
                                "bulk_import")
        if config.user.may("wato.services"):
            html.context_button(
                _("Bulk discovery"),
                self._folder.url([("mode", "bulkinventory"), ("all", "1")]),
                "inventory")
        if config.user.may("wato.rename_hosts"):
            html.context_button(
                _("Bulk renaming"),
                self._folder.url([("mode", "bulk_rename_host")]),
                "rename_host")
        if config.user.may("wato.custom_attributes"):
            html.context_button(
                _("Custom attributes"),
                watolib.folder_preserving_link([("mode", "host_attrs")]),
                "custom_attr")
        if not self._folder.locked_hosts() and config.user.may(
                "wato.parentscan") and self._folder.may("write"):
            html.context_button(
                _("Parent scan"),
                self._folder.url([("mode", "parentscan"), ("all", "1")]),
                "parentscan")
        folder_status_button()
        if config.user.may("wato.random_hosts"):
            html.context_button(_("Random hosts"),
                                self._folder.url([("mode", "random_hosts")]),
                                "random")
        html.context_button(
            _("Search"), watolib.folder_preserving_link([("mode", "search")]),
            "search")

        if config.user.may("wato.dcd_connections"):
            html.context_button(
                _("Dynamic config"),
                watolib.folder_preserving_link([("mode", "dcd_connections")]),
                "dcd_connections")
Exemple #4
0
def button_all_logfiles():
    html.context_button(_("All Logfiles"), html.makeuri([('site', ''), ('host', ''), ('file', '')]))
Exemple #5
0
def render_bi_availability(title, aggr_rows):
    config.user.need_permission("general.see_availability")

    av_mode = html.request.var("av_mode", "availability")
    avoptions = get_availability_options_from_url("bi")
    if av_mode == "timeline":
        title = _("Timeline of") + " " + title
    else:
        title = _("Availability of") + " " + title

    if html.output_format != "csv_export":
        html.body_start(title)
        html.top_heading(title)
        html.begin_context_buttons()
        html.toggle_button("avoptions", False, "painteroptions",
                           _("Configure details of the report"))
        html.context_button(_("Status View"), html.makeuri([("mode", "status")]), "status")
        if config.reporting_available() and config.user.may("general.reporting"):
            html.context_button(_("Export as PDF"), html.makeuri([], filename="report_instant.py"),
                                "report")
        if av_mode == "availability" and config.user.may("general.csv_export"):
            html.context_button(_("Export as CSV"), html.makeuri([("output_format", "csv_export")]),
                                "download_csv")

        if av_mode == "timeline":
            html.context_button(_("Availability"), html.makeuri([("av_mode", "availability")]),
                                "availability")

        elif len(aggr_rows) == 1:
            aggr_name = aggr_rows[0]["aggr_name"]
            aggr_group = aggr_rows[0]["aggr_group"]
            timeline_url = html.makeuri([("av_mode", "timeline"), ("av_aggr_name", aggr_name),
                                         ("av_aggr_group", aggr_group)])
            html.context_button(_("Timeline"), timeline_url, "timeline")
        html.end_context_buttons()

        avoptions = render_availability_options("bi")

    if not html.has_user_errors():
        logrow_limit = avoptions["logrow_limit"]
        if logrow_limit == 0:
            livestatus_limit = None
        else:
            livestatus_limit = (len(aggr_rows) * logrow_limit)

        spans = []

        # iterate all aggregation rows
        timewarpcode = ""

        try:
            timewarp = int(html.request.var("timewarp"))
        except (ValueError, TypeError):
            timewarp = None

        has_reached_logrow_limit = False
        timeline_containers, fetched_rows = availability.get_timeline_containers(
            aggr_rows, avoptions, timewarp,
            livestatus_limit + 1 if livestatus_limit is not None else None)
        if livestatus_limit and fetched_rows > livestatus_limit:
            has_reached_logrow_limit = True

        for timeline_container in timeline_containers:
            tree = timeline_container.aggr_tree
            these_spans = timeline_container.timeline
            timewarp_tree_state = timeline_container.timewarp_state

            spans += these_spans

            # render selected time warp for the corresponding aggregation row (should be matched by only one)
            if timewarp and timewarp_tree_state:
                state, assumed_state, node, _subtrees = timewarp_tree_state
                eff_state = state
                if assumed_state is not None:
                    eff_state = assumed_state
                row = {
                    "aggr_tree": tree,
                    "aggr_treestate": timewarp_tree_state,
                    "aggr_state": state,  # state disregarding assumptions
                    "aggr_assumed_state": assumed_state,  # is None, if there are no assumptions
                    "aggr_effective_state": eff_state,  # is assumed_state, if there are assumptions, else real state
                    "aggr_name": node["title"],
                    "aggr_output": eff_state["output"],
                    "aggr_hosts": node["reqhosts"],
                    "aggr_function": node["func"],
                    "aggr_group": html.request.var("aggr_group"),
                }

                renderer = bi.FoldableTreeRendererTree(row,
                                                       omit_root=False,
                                                       expansion_level=bi.load_ex_level(),
                                                       only_problems=False,
                                                       lazy=False)
                tdclass, htmlcode = renderer.css_class(), renderer.render()

                with html.plugged():
                    # TODO: SOMETHING IS WRONG IN HERE (used to be the same situation in original code!)
                    # FIXME: WHAT is wrong in here??

                    html.open_h3()
                    # render icons for back and forth
                    button_back_shown = False
                    button_forth_shown = False
                    if int(these_spans[0]["from"]) == timewarp:
                        html.disabled_icon_button("back_off")
                        button_back_shown = True

                    previous_span = None
                    for span in these_spans:
                        if not button_back_shown and int(
                                span["from"]) == timewarp and previous_span is not None:
                            html.icon_button(
                                html.makeuri([("timewarp", str(int(previous_span["from"])))]),
                                _("Jump one phase back"), "back")
                            button_back_shown = True
                        # Multiple followup spans can have the same "from" time
                        # We only show one forth-arrow with an actual time difference
                        elif not button_forth_shown and previous_span and int(
                                previous_span["from"]) == timewarp and int(
                                    span["from"]) != timewarp:
                            html.icon_button(html.makeuri([("timewarp", str(int(span["from"])))]),
                                             _("Jump one phase forth"), "forth")
                            button_forth_shown = True
                        previous_span = span
                    if not button_forth_shown:
                        html.disabled_icon_button("forth_off")

                    html.write_text("   ")
                    html.icon_button(html.makeuri([("timewarp", "")]), _("Close Timewarp"),
                                     "closetimewarp")
                    html.write_text("%s %s" %
                                    (_("Timewarp to "),
                                     time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(timewarp))))
                    html.close_h3()

                    html.open_table(class_=["data", "table", "timewarp"])
                    html.open_tr(class_=["data", "odd0"])
                    html.open_td(class_=tdclass)
                    html.write_html(htmlcode)
                    html.close_td()
                    html.close_tr()
                    html.close_table()

                    timewarpcode += html.drain()

        # Note: 'spans_by_object' returns two arguments which are used by
        # all availability views but not by BI. There we have to take
        # only complete aggregations
        av_rawdata = availability.spans_by_object(spans, None)[0]
        av_data = availability.compute_availability("bi", av_rawdata, avoptions)

        # If we abolish the limit we have to fetch the data again
        # with changed logrow_limit = 0, which means no limit
        if has_reached_logrow_limit:
            text = _(
                "Your query matched more than %d log entries. "
                "<b>Note:</b> The shown data does not necessarily reflect the "
                "matched entries and the result might be incomplete. ") % avoptions["logrow_limit"]
            text += html.render_a(_('Repeat query without limit.'),
                                  html.makeuri([("_unset_logrow_limit", "1")]))
            html.show_warning(text)

        if html.output_format == "csv_export" and config.user.may("general.csv_export"):
            output_availability_csv("bi", av_data, avoptions)
            return

        html.write(timewarpcode)
        do_render_availability("bi", av_rawdata, av_data, av_mode, None, avoptions)

    html.bottom_footer()
    html.body_end()
Exemple #6
0
    def buttons(self):
        global_buttons()
        html.context_button(_("New user"), watolib.folder_preserving_link([("mode", "edit_user")]),
                            "new")
        if config.user.may("wato.custom_attributes"):
            html.context_button(_("Custom attributes"),
                                watolib.folder_preserving_link([("mode", "user_attrs")]),
                                "custom_attr")
        if userdb.sync_possible():
            if not self._job_snapshot.is_active():
                html.context_button(_("Sync users"), html.makeactionuri([("_sync", 1)]),
                                    "replicate")
                html.context_button(_("Last sync result"), self._job.detail_url(),
                                    "background_job_details")

        if config.user.may("general.notify"):
            html.context_button(_("Notify users"), 'notify.py', "notification")
        html.context_button(_("LDAP connections"),
                            watolib.folder_preserving_link([("mode", "ldap_config")]), "ldap")
Exemple #7
0
def show_file(site, host_name, file_name):
    int_filename = form_file_to_int(file_name)

    html.header(_("Logfiles of Host %s: %s") % (host_name, file_name))
    html.begin_context_buttons()
    html.context_button(_("Services"), services_url(site, host_name), 'services')
    html.context_button(_("All Logfiles of Host"), html.makeuri([('file', '')]))
    button_all_logfiles()
    html.context_button(_("Analyze patterns"), analyse_url(site, host_name, file_name), 'analyze')

    if html.request.var('_hidecontext', 'no') == 'yes':
        hide_context_label = _('Show Context')
        hide_context_param = 'no'
        hide = True
    else:
        hide_context_label = _('Hide Context')
        hide_context_param = 'yes'
        hide = False

    try:
        log_chunks = parse_file(site, host_name, int_filename, hide)
    except Exception as e:
        if config.debug:
            raise
        html.end_context_buttons()
        html.show_error(_("Unable to show logfile: <b>%s</b>") % e)
        html.footer()
        return

    if log_chunks is None:
        html.end_context_buttons()
        html.show_error(_("The logfile does not exist."))
        html.footer()
        return

    if log_chunks == []:
        html.end_context_buttons()
        html.show_message(_("This logfile contains no unacknowledged messages."))
        html.footer()
        return

    ack_button(site, host_name, int_filename)
    html.context_button(hide_context_label, html.makeuri([('_hidecontext', hide_context_param)]))

    html.end_context_buttons()

    html.open_div(id_="logwatch")
    for log in log_chunks:
        html.open_div(class_=["chunk"])
        html.open_table(class_=["section"])
        html.open_tr()
        html.td(form_level(log['level']), class_=form_level(log['level']))
        html.td(form_datetime(log['datetime']), class_="date")
        html.close_tr()
        html.close_table()

        for line in log['lines']:
            html.open_p(class_=line['class'])
            html.icon_button(analyse_url(site, host_name, file_name, line['line']),
                             _("Analyze this line"), "analyze")
            html.write_text(line['line'].replace(" ", "&nbsp;").replace("\1", "<br>"))
            html.close_p()

        html.close_div()

    html.close_div()
    html.footer()
Exemple #8
0
 def buttons(self):
     html.context_button(
         _("Back"),
         watolib.folder_preserving_link([("mode", "host_attrs")]), "back")
Exemple #9
0
 def buttons(self):
     global_buttons()
     html.context_button(
         _("Back"),
         watolib.folder_preserving_link([("mode", "ldap_config")]), "back")
Exemple #10
0
 def buttons(self):
     global_buttons()
     html.context_button(_("Folder"), self._folder.url(), "back")
Exemple #11
0
 def buttons(self):
     html.context_button(
         _("Back"),
         html.makeuri_contextless([
             ("mode", self._mode_type.list_mode_name())
         ]), "back")
Exemple #12
0
 def buttons(self):
     back_url = html.get_url_input("back", "")
     if back_url:
         html.context_button(_("Back"), back_url, "back")
     else:
         global_buttons()
Exemple #13
0
 def buttons(self):
     if self._back_url():
         html.context_button(_("Back"), self._back_url(), "back")
Exemple #14
0
 def buttons(self):
     global_buttons()
     html.context_button(
         _("Matrix"),
         watolib.folder_preserving_link([("mode", "role_matrix")]),
         "matrix")
Exemple #15
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  # noqa: F401 # pylint: disable=unused-variable,redefined-outer-name
                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
Exemple #16
0
 def buttons(self):
     html.context_button(_("Abort"), watolib.folder_preserving_link([("mode", "globalvars")]),
                         "abort")
Exemple #17
0
 def buttons(self):
     html.context_button(
         _("All groups"),
         watolib.folder_preserving_link([
             ("mode", "%s_groups" % self.type_name)
         ]), "back")
Exemple #18
0
 def buttons(self):
     html.context_button(
         _("Abort"),
         watolib.folder_preserving_link([("mode", "edit_site_globals"),
                                         ("site", self._site_id)]), "abort")
Exemple #19
0
 def buttons(self):
     html.context_button(_("Back"), self._folder.url(), "back")
Exemple #20
0
 def buttons(self):
     global_buttons()
     html.context_button(
         _("New tag group"), watolib.folder_preserving_link([("mode", "edit_tag")]), "new")
     html.context_button(
         _("New aux tag"), watolib.folder_preserving_link([("mode", "edit_auxtag")]), "new")
Exemple #21
0
def do_log_ack(site, host_name, file_name):
    logs_to_ack = []
    if not host_name and not file_name:  # all logs on all hosts
        for this_site, this_host, logs in all_logs():
            for int_filename in logs:
                file_display = form_file_to_ext(int_filename)
                logs_to_ack.append((this_site, this_host, int_filename, file_display))
        ack_msg = _('all logfiles on all hosts')

    elif host_name and not file_name:  # all logs on one host
        for int_filename in logfiles_of_host(site, host_name):
            file_display = form_file_to_ext(int_filename)
            logs_to_ack.append((site, host_name, int_filename, file_display))
        ack_msg = _('all logfiles of host %s') % host_name

    elif host_name and file_name:  # one log on one host
        int_filename = form_file_to_int(file_name)
        logs_to_ack = [(site, host_name, int_filename, form_file_to_ext(int_filename))]
        ack_msg = _('the log file %s on host %s') % (file_name, host_name)

    else:
        for this_site, this_host, logs in all_logs():
            file_display = form_file_to_ext(file_name)
            if file_name in logs:
                logs_to_ack.append((this_site, this_host, file_name, file_display))
        ack_msg = _('log file %s on all hosts') % file_name

    html.header(_("Acknowledge %s") % html.render_text(ack_msg))

    html.begin_context_buttons()
    button_all_logfiles()
    if host_name:
        html.context_button(_("All Logfiles of Host"), html.makeuri([('file', '')]))
    if host_name and file_name:
        html.context_button(_("Back to Logfile"), html.makeuri([]))
    html.end_context_buttons()

    ack = html.request.var('_ack')
    if not html.confirm(
            _("Do you really want to acknowledge %s by <b>deleting</b> all stored messages?") %
            ack_msg):
        html.footer()
        return

    if not config.user.may("general.act"):
        html.h1(_('Permission denied'), class_=["error"])
        html.div(_('You are not allowed to acknowledge %s') % ack_msg, class_=["error"])
        html.footer()
        return

    # filter invalid values
    if ack != '1':
        raise MKUserError('_ack', _('Invalid value for ack parameter.'))

    for this_site, this_host, int_filename, display_name in logs_to_ack:
        try:
            acknowledge_logfile(this_site, this_host, int_filename, display_name)
        except Exception as e:
            html.show_error(
                _('The log file <tt>%s</tt> of host <tt>%s</tt> could not be deleted: %s.') %
                (display_name, this_host, e))
            html.footer()
            return

    html.show_message(
        '<b>%s</b><p>%s</p>' %
        (_('Acknowledged %s') % ack_msg, _('Acknowledged all messages in %s.') % ack_msg))
    html.footer()
Exemple #22
0
 def buttons(self):
     html.context_button(
         _("Back"), html.makeuri_contextless([("mode", self.back_mode)]),
         "back")
Exemple #23
0
def render_availability_page(view, context, filterheaders):
    config.user.need_permission("general.see_availability")

    if handle_edit_annotations():
        return

    # We make reports about hosts, services or BI aggregates
    if "service" in view.datasource.infos:
        what = "service"
    elif "aggr_name" in view.datasource.infos:
        what = "bi"
    else:
        what = "host"

    avoptions = get_availability_options_from_url(what)
    time_range, range_title = avoptions["range"]

    # We have two display modes:
    # - Show availability table (stats) "table"
    # - Show timeline                   "timeline"
    # --> controlled by URL variable "av_mode"
    av_mode = html.request.var("av_mode", "table")

    if av_mode == "timeline":
        title = _("Availability Timeline")
    else:
        title = _("Availability")

    # This is combined with the object selection
    # - Show all objects
    # - Show one specific object
    # --> controlled by URL variables "av_site", "av_host" and "av_service"
    # --> controlled by "av_aggr" in case of BI aggregate
    title += " - "
    if html.request.var("av_host"):
        av_object = (html.request.var("av_site"), html.request.var("av_host"),
                     html.request.var("av_service"))
        title += av_object[1]
        if av_object[2]:
            title += " - " + av_object[2]
    elif html.request.var("av_aggr"):
        av_object = (None, None, html.request.var("av_aggr"))
        title += av_object[2]
    else:
        av_object = None
        title += view_title(view.spec)

    # Deletion must take place before computation, since it affects the outcome
    with html.plugged():
        handle_delete_annotations()
        confirmation_html_code = html.drain()

    # Now compute all data, we need this also for CSV export
    if not html.has_user_errors():
        include_long_output = av_mode == "timeline" \
                and "timeline_long_output" in avoptions["labelling"]
        av_rawdata, has_reached_logrow_limit = availability.get_availability_rawdata(
            what,
            context,
            filterheaders,
            view.only_sites,
            av_object=av_object,
            include_output=av_mode == "timeline",
            include_long_output=include_long_output,
            avoptions=avoptions)
        av_data = availability.compute_availability(what, av_rawdata, avoptions)

    # Do CSV ouput
    if html.output_format == "csv_export" and config.user.may("general.csv_export"):
        output_availability_csv(what, av_data, avoptions)
        return

    title += " - " + range_title

    if display_options.enabled(display_options.H):
        html.body_start(title, force=True)

    if display_options.enabled(display_options.T):
        html.top_heading(title)

    html.write(confirmation_html_code)

    # Remove variables for editing annotations, otherwise they will make it into the uris
    html.request.del_vars("anno_")
    if html.request.var("filled_in") == "editanno":
        html.request.del_var("filled_in")

    if display_options.enabled(display_options.B):
        html.begin_context_buttons()
        html.toggle_button(
            "avoptions",
            html.has_user_errors(),
            "painteroptions",
            _("Configure details of the report"),
        )
        html.context_button(
            _("Status View"),
            html.makeuri([("mode", "status")]),
            "status",
        )
        if config.reporting_available() and config.user.may("general.reporting"):
            html.context_button(
                _("Export as PDF"),
                html.makeuri([], filename="report_instant.py"),
                "report",
            )

        if av_mode == "table" and config.user.may("general.csv_export"):
            html.context_button(
                _("Export as CSV"),
                html.makeuri([("output_format", "csv_export")]),
                "download_csv",
            )

        if av_mode == "timeline" or av_object:
            html.context_button(
                _("Availability"),
                html.makeuri([("av_mode", "availability"), ("av_host", ""), ("av_aggr", "")]),
                "availability",
            )
        elif not av_object:
            html.context_button(
                _("Timeline"),
                html.makeuri([("av_mode", "timeline")]),
                "timeline",
            )
        elif av_mode == "timeline" and what != "bi":
            history_url = availability.history_url_of(av_object, time_range)
            html.context_button(
                _("History"),
                history_url,
                "history",
            )

        html.end_context_buttons()

    # Render the avoptions again to get the HTML code, because the HTML vars have changed
    # above (anno_ and editanno_ has been removed, which must not be part of the form
    avoptions = render_availability_options(what)

    if not html.has_user_errors():
        # If we abolish the limit we have to fetch the data again
        # with changed logrow_limit = 0, which means no limit
        if has_reached_logrow_limit:
            text = _(
                "Your query matched more than %d log entries. "
                "<b>Note:</b> The number of shown rows does not necessarily reflect the "
                "matched entries and the result might be incomplete. ") % avoptions["logrow_limit"]
            text += html.render_a(
                _('Repeat query without limit.'),
                html.makeuri([("_unset_logrow_limit", "1"), ("avo_logrow_limit", 0)]))
            html.show_warning(text)

        do_render_availability(what, av_rawdata, av_data, av_mode, av_object, avoptions)

    if display_options.enabled(display_options.Z):
        html.bottom_footer()

    if display_options.enabled(display_options.H):
        html.body_end()
Exemple #24
0
    def page_edit(cls):
        back_url = html.get_url_input("back", cls.list_url())

        cls.load()
        cls.need_overriding_permission("edit")

        # Three possible modes:
        # "create" -> create completely new page
        # "clone"  -> like new, but prefill form with values from existing page
        # "edit"   -> edit existing page
        mode = html.request.var('mode', 'edit')
        if mode == "create":
            title = cls.phrase("create")
            page_dict = {
                "name": cls.default_name(),
                "topic": cls.default_topic(),
            }
        else:
            # Load existing page. visual from disk - and create a copy if 'load_user' is set
            page_name = html.request.var("load_name")
            if mode == "edit":
                title = cls.phrase("edit")

                owner_user_id = UserId(
                    html.request.get_unicode_input_mandatory("owner", config.user.id))
                if owner_user_id == config.user.id:
                    page = cls.find_my_page(page_name)
                else:
                    page = cls.find_foreign_page(owner_user_id, page_name)

                if page is None:
                    raise MKUserError(None,
                                      _("The requested %s does not exist") % cls.phrase("title"))

                # TODO FIXME: Looks like a hack
                cls.remove_instance((owner_user_id, page_name))  # will be added later again
            else:  # clone
                title = cls.phrase("clone")
                load_user = html.request.get_unicode_input(
                    "load_user")  # FIXME: Change varname to "owner"

                try:
                    page = cls.instance((load_user, page_name))
                except KeyError:
                    raise MKUserError(None,
                                      _("The requested %s does not exist") % cls.phrase("title"))
            page_dict = page.internal_representation()

        html.header(title)
        html.begin_context_buttons()
        html.context_button(_("Back"), back_url, "back")
        html.end_context_buttons()

        parameters, keys_by_topic = cls._collect_parameters(mode)
        vs = Dictionary(
            title=_("General Properties"),
            render='form',
            optional_keys=False,
            elements=parameters,
            headers=keys_by_topic,
        )

        def validate(page_dict):
            owner_user_id = UserId(html.request.get_unicode_input_mandatory(
                "owner", config.user.id))
            page_name = page_dict["name"]
            if owner_user_id == config.user.id:
                page = cls.find_my_page(page_name)
            else:
                page = cls.find_foreign_page(owner_user_id, page_name)
            if page:
                raise MKUserError(
                    "_p_name",
                    _("You already have an element with the ID <b>%s</b>") % page_dict["name"])

        new_page_dict = forms.edit_valuespec(vs,
                                             page_dict,
                                             validate=validate,
                                             focus="_p_title",
                                             method="POST")
        if new_page_dict is not None:
            # Take over keys from previous value that are specific to the page type
            # and not edited here.
            if mode in ("edit", "clone"):
                for key, value in page_dict.items():
                    new_page_dict.setdefault(key, value)

            owner = UserId(html.request.get_unicode_input_mandatory("owner", config.user.id))
            new_page_dict["owner"] = owner
            new_page = cls(new_page_dict)

            cls.add_page(new_page)
            cls.save_user_instances(owner)
            if mode == "create":
                redirect_url = new_page.after_create_url() or back_url
            else:
                redirect_url = back_url

            html.immediate_browser_redirect(0.5, redirect_url)
            html.show_message(_('Your changes haven been saved.'))
            # Reload sidebar.TODO: This code logically belongs to PageRenderer. How
            # can we simply move it there?
            # TODO: This is not true for all cases. e.g. the BookmarkList is not
            # of type PageRenderer but has a dedicated sidebar snapin. Maybe
            # the best option would be to make a dedicated method to decide whether
            # or not to reload the sidebar.
            if new_page_dict.get("hidden") in [ None, False ] \
               or new_page_dict.get("hidden") != page_dict.get("hidden"):
                html.reload_sidebar()

        else:
            html.show_localization_hint()

        html.footer()
        return
Exemple #25
0
def edit_annotation():
    site_id = html.request.var("anno_site") or ""
    hostname = html.request.var("anno_host")
    service = html.request.var("anno_service") or None
    fromtime = float(html.request.var("anno_from"))
    untiltime = float(html.request.var("anno_until"))
    site_host_svc = (site_id, hostname, service)

    # Find existing annotation with this specification
    annotations = availability.load_annotations()
    annotation = availability.find_annotation(annotations, site_host_svc, fromtime, untiltime)

    if not annotation:
        value = {
            "from": fromtime,
            "until": untiltime,
            "text": "",
        }
    else:
        value = annotation.copy()

    value["host"] = hostname
    value["service"] = service
    value["site"] = site_id

    if html.check_transaction():
        try:
            vs = _vs_annotation()
            value = vs.from_html_vars("_editanno")
            vs.validate_value(value, "_editanno")

            site_host_svc = value["site"], value["host"], value["service"]
            del value["site"]
            del value["host"]
            value["date"] = time.time()
            value["author"] = config.user.id
            availability.update_annotations(site_host_svc, value, replace_existing=annotation)
            html.request.del_var("filled_in")
            return False
        except MKUserError as e:
            html.user_error(e)

    title = _("Edit annotation of ") + hostname
    if service:
        title += "/" + service

    html.body_start(title)
    html.top_heading(title)

    html.begin_context_buttons()
    html.context_button(_("Abort"), html.makeuri([("anno_host", "")]), "abort")
    html.end_context_buttons()

    html.begin_form("editanno", method="GET")
    _vs_annotation().render_input_as_form("_editanno", value)

    html.button("save", _("Save"))

    html.hidden_fields()
    html.end_form()

    html.bottom_footer()
    html.body_end()
    return True
Exemple #26
0
 def context_button_list(cls):
     html.context_button(cls.phrase("title_plural"), cls.list_url(), cls.type_name())
Exemple #27
0
 def buttons(self):
     html.context_button(_("All tags"),
                         watolib.folder_preserving_link([("mode", "tags")]),
                         "back")
Exemple #28
0
 def context_button_edit(self):
     html.context_button(_("Edit"), self.edit_url(), "edit")
Exemple #29
0
 def buttons(self):
     if html.request.has_var("backfolder"):
         back_folder = watolib.Folder.folder(html.request.var("backfolder"))
     else:
         back_folder = self._folder
     html.context_button(_("Back"), back_folder.url(), "back")
Exemple #30
0
def _show_page_user_profile(change_pw):
    start_async_replication = False

    if not config.user.id:
        raise MKUserError(None, _('Not logged in.'))

    if not config.user.may('general.edit_profile') and not config.user.may(
            'general.change_password'):
        raise MKAuthException(
            _("You are not allowed to edit your user profile."))

    if not config.wato_enabled:
        raise MKAuthException(
            _('User profiles can not be edited (WATO is disabled).'))

    success = None
    if html.request.has_var('_save') and html.check_transaction():
        users = userdb.load_users(lock=True)

        try:
            # Profile edit (user options like language etc.)
            if config.user.may('general.edit_profile'):
                if not change_pw:
                    set_lang = html.get_checkbox('_set_lang')
                    language = html.request.var('language')
                    # Set the users language if requested
                    if set_lang:
                        if language == '':
                            language = None
                        # Set custom language
                        users[config.user.id]['language'] = language
                        config.user.language = language
                        html.set_language_cookie(language)

                    else:
                        # Remove the customized language
                        if 'language' in users[config.user.id]:
                            del users[config.user.id]['language']
                        config.user.reset_language()

                    # load the new language
                    cmk.gui.i18n.localize(config.user.language)

                    user = users.get(config.user.id)
                    if config.user.may('general.edit_notifications'
                                       ) and user.get("notifications_enabled"):
                        value = forms.get_input(
                            watolib.get_vs_flexible_notifications(),
                            "notification_method")
                        users[config.user.id]["notification_method"] = value

                    # Custom attributes
                    if config.user.may('general.edit_user_attributes'):
                        for name, attr in userdb.get_user_attributes():
                            if attr.user_editable():
                                if not attr.permission() or config.user.may(
                                        attr.permission()):
                                    vs = attr.valuespec()
                                    value = vs.from_html_vars('ua_' + name)
                                    vs.validate_value(value, "ua_" + name)
                                    users[config.user.id][name] = value

            # Change the password if requested
            password_changed = False
            if config.user.may('general.change_password'):
                cur_password = html.request.var('cur_password')
                password = html.request.var('password')
                password2 = html.request.var('password2', '')

                if change_pw:
                    # Force change pw mode
                    if not cur_password:
                        raise MKUserError(
                            "cur_password",
                            _("You need to provide your current password."))
                    if not password:
                        raise MKUserError(
                            "password", _("You need to change your password."))
                    if cur_password == password:
                        raise MKUserError(
                            "password",
                            _("The new password must differ from your current one."
                              ))

                if cur_password and password:
                    if userdb.hook_login(config.user.id,
                                         cur_password) in [None, False]:
                        raise MKUserError("cur_password",
                                          _("Your old password is wrong."))
                    if password2 and password != password2:
                        raise MKUserError(
                            "password2",
                            _("The both new passwords do not match."))

                    watolib.verify_password_policy(password)
                    users[config.user.id]['password'] = hash_password(password)
                    users[config.user.id]['last_pw_change'] = int(time.time())

                    if change_pw:
                        # Has been changed, remove enforcement flag
                        del users[config.user.id]['enforce_pw_change']

                    # Increase serial to invalidate old cookies
                    if 'serial' not in users[config.user.id]:
                        users[config.user.id]['serial'] = 1
                    else:
                        users[config.user.id]['serial'] += 1

                    password_changed = True

            # Now, if in distributed environment where users can login to remote sites,
            # set the trigger for pushing the new auth information to the slave sites
            # asynchronous
            if config.user.authorized_login_sites():
                start_async_replication = True

            userdb.save_users(users)

            if password_changed:
                # Set the new cookie to prevent logout for the current user
                login.set_auth_cookie(config.user.id)

            success = True
        except MKUserError as e:
            html.add_user_error(e.varname, e)
    else:
        users = userdb.load_users()

    watolib.init_wato_datastructures(with_wato_lock=True)

    # When in distributed setup, display the replication dialog instead of the normal
    # profile edit dialog after changing the password.
    if start_async_replication:
        user_profile_async_replication_page()
        return

    if change_pw:
        title = _("Change Password")
    else:
        title = _("Edit User Profile")

    html.header(title)

    # Rule based notifications: The user currently cannot simply call the according
    # WATO module due to WATO permission issues. So we cannot show this button
    # right now.
    if not change_pw:
        rulebased_notifications = watolib.load_configuration_settings().get(
            "enable_rulebased_notifications")
        if rulebased_notifications and config.user.may(
                'general.edit_notifications'):
            html.begin_context_buttons()
            url = "wato.py?mode=user_notifications_p"
            html.context_button(_("Notifications"), url, "notifications")
            html.end_context_buttons()
    else:
        reason = html.request.var('reason')
        if reason == 'expired':
            html.p(
                _('Your password is too old, you need to choose a new password.'
                  ))
        else:
            html.p(
                _('You are required to change your password before proceeding.'
                  ))

    if success:
        html.reload_sidebar()
        if change_pw:
            html.message(_("Your password has been changed."))
            raise HTTPRedirect(html.request.var('_origtarget', 'index.py'))
        else:
            html.message(_("Successfully updated user profile."))
            # Ensure theme changes are applied without additional user interaction
            html.immediate_browser_redirect(0.5, html.makeuri([]))

    if html.has_user_errors():
        html.show_user_errors()

    user = users.get(config.user.id)
    if user is None:
        html.show_warning(_("Sorry, your user account does not exist."))
        html.footer()
        return

    # Returns true if an attribute is locked and should be read only. Is only
    # checked when modifying an existing user
    locked_attributes = userdb.locked_attributes(user.get('connector'))

    def is_locked(attr):
        return attr in locked_attributes

    html.begin_form("profile", method="POST")
    html.prevent_password_auto_completion()
    html.open_div(class_="wato")
    forms.header(_("Personal Settings"))

    if not change_pw:
        forms.section(_("Name"), simple=True)
        html.write_text(user.get("alias", config.user.id))

    if config.user.may(
            'general.change_password') and not is_locked('password'):
        forms.section(_("Current Password"))
        html.password_input('cur_password', autocomplete="new-password")

        forms.section(_("New Password"))
        html.password_input('password', autocomplete="new-password")

        forms.section(_("New Password Confirmation"))
        html.password_input('password2', autocomplete="new-password")

    if not change_pw and config.user.may('general.edit_profile'):
        select_language(user)

        # Let the user configure how he wants to be notified
        if not rulebased_notifications \
            and config.user.may('general.edit_notifications') \
            and user.get("notifications_enabled"):
            forms.section(_("Notifications"))
            html.help(
                _("Here you can configure how you want to be notified about host and service problems and "
                  "other monitoring events."))
            watolib.get_vs_flexible_notifications().render_input(
                "notification_method", user.get("notification_method"))

        if config.user.may('general.edit_user_attributes'):
            for name, attr in userdb.get_user_attributes():
                if attr.user_editable():
                    vs = attr.valuespec()
                    forms.section(_u(vs.title()))
                    value = user.get(name, vs.default_value())
                    if not attr.permission() or config.user.may(
                            attr.permission()):
                        vs.render_input("ua_" + name, value)
                        html.help(_u(vs.help()))
                    else:
                        html.write(vs.value_to_text(value))

    # Save button
    forms.end()
    html.button("_save", _("Save"))
    html.close_div()
    html.hidden_fields()
    html.end_form()
    html.footer()