Ejemplo n.º 1
0
    def action(self):
        if html.request.var("_action") != "discard":
            return

        if not html.check_transaction():
            return

        if not self._may_discard_changes():
            return

        # TODO: Remove once new changes mechanism has been implemented
        # Now remove all currently pending changes by simply restoring the last automatically
        # taken snapshot. Then activate the configuration. This should revert all pending changes.
        file_to_restore = self._get_last_wato_snapshot_file()

        if not file_to_restore:
            raise MKUserError(None,
                              _('There is no WATO snapshot to be restored.'))

        msg = _("Discarded pending changes (Restored %s)") % file_to_restore

        # All sites and domains can be affected by a restore: Better restart everything.
        watolib.add_change("changes-discarded",
                           msg,
                           domains=watolib.ConfigDomain.enabled_domains(),
                           need_restart=True)

        self._extract_snapshot(file_to_restore)
        cmk.gui.watolib.activate_changes.execute_activate_changes(
            [d.ident for d in watolib.ConfigDomain.enabled_domains()])

        for site_id in cmk.gui.watolib.changes.activation_site_ids():
            self.confirm_site_changes(site_id)

        html.header(self.title(),
                    show_body_start=display_options.enabled(display_options.H),
                    show_top_heading=display_options.enabled(
                        display_options.T))
        html.open_div(class_="wato")

        html.begin_context_buttons()
        home_button()
        html.end_context_buttons()

        html.message(_("Successfully discarded all pending changes."))
        html.javascript("hide_changes_buttons();")
        html.footer()

        return False
Ejemplo n.º 2
0
    def delete_job(self):
        job_id = html.request.var(self.delete_job_var)
        if not job_id:
            return

        job = GUIBackgroundJob(job_id=job_id)
        if not job.is_available():
            return

        html.header("Deletion of job")
        c = html.confirm(_("Delete job %s%s?") % (job_id, self._get_extra_info(job)))
        if c and job.may_delete():
            job.delete()
            self._did_delete_job = True
            html.message(_("Background job has been deleted"))
Ejemplo n.º 3
0
    def _show_diagnose_output(self):
        if not html.request.var('_try'):
            html.message(
                _('You can diagnose the connection to a specific host using this dialog. '
                  'You can either test whether your current configuration is still working '
                  'or investigate in which ways a host can be reached. Simply configure the '
                  'connection options you like to try on the right side of the screen and '
                  'press the "Test" button. The results will be displayed here.'
                  ))
            return

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

        # TODO: Insert any vs_host valuespec validation
        #       These tests can be called with invalid valuespec settings...
        # TODO: Replace hard coded icon paths with dynamic ones to old or new theme
        for ident, title in ModeDiagHost.diag_host_tests():
            html.h3(title)
            html.open_table(class_=["data", "test"])
            html.open_tr(class_=["data", "odd0"])

            html.open_td(class_="icons")
            html.open_div()
            html.icon(title=None, icon="reload", id_="%s_img" % ident)
            html.open_a(href="")
            html.icon(title=_('Retry this test'),
                      icon="reload",
                      cssclass="retry",
                      id_="%s_retry" % ident)
            html.close_a()
            html.close_div()
            html.close_td()

            html.open_td()
            html.div('', class_="log", id="%s_log" % ident)
            html.close_td()

            html.close_tr()
            html.close_table()
            html.javascript(
                'cmk.host_diagnose.start_test(%s, %s, %s)' %
                (json.dumps(ident), json.dumps(self._hostname),
                 json.dumps(html.transaction_manager.fresh_transid())))
Ejemplo n.º 4
0
    def page(self):
        self._folder.show_breadcrump()

        if not self._folder.may("read"):
            html.message(
                html.render_icon("autherr", cssclass="authicon") + " " +
                self._folder.reason_why_may_not("read"))

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

        if not self._folder.has_hosts():
            if self._folder.is_search_folder():
                html.message(_("No matching hosts found."))
            elif not self._folder.has_subfolders() and self._folder.may("write"):
                self._show_empty_folder_menu()
Ejemplo n.º 5
0
    def stop_job(self):
        job_id = html.request.var(self.stop_job_var)
        if not job_id:
            return

        job = GUIBackgroundJob(job_id)
        if not job.is_available():
            return

        html.header("Interuption of job")
        if self.confirm_dialog_opened() and not job.is_running():
            html.message(_("No longer able to stop job. Background job just finished."))
            return

        c = html.confirm(_("Stop job %s%s?") % (job_id, self._get_extra_info(job)))
        if c and job.may_stop():
            job.stop()
            self._did_stop_job = True
            html.message(_("Background job has been stopped"))
Ejemplo n.º 6
0
    def page(self):
        job_id = html.request.var("job_id")

        job = gui_background_job.GUIBackgroundJob(job_id)
        if not job.exists():
            html.message(_("Background job info is not available"))
            return

        try:
            # Race condition, the job might get deleted during snapshot generation
            job_snapshot = job.get_status_snapshot()
        except Exception:
            html.message(_("Background job info is not available"))
            logger.error(traceback.format_exc())
            return

        job_manager = gui_background_job.GUIBackgroundJobManager()
        job_manager.show_job_details_from_snapshot(job_snapshot)
        if job_snapshot.is_running():
            html.immediate_browser_redirect(1, "")
Ejemplo n.º 7
0
    def _end(self):
        if not self.rows and self.options["omit_if_empty"]:
            return

        if self.options["output_format"] == "csv":
            self._write_csv(
                csv_separator=html.request.var("csv_separator", ";"))
            return

        if self.title:
            if self.options["foldable"]:
                html.begin_foldable_container(
                    treename="table",
                    id_=self.id,
                    isopen=True,
                    indent=False,
                    title=html.render_h3(self.title,
                                         class_=["treeangle", "title"]))
            else:
                html.open_h3()
                html.write(self.title)
                html.close_h3()

        if self.help:
            html.help(self.help)

        if not self.rows:
            html.div(self.empty_text, class_="info")
            return

        # Controls whether or not actions are available for a table
        rows, actions_enabled, actions_visible, search_term, user_opts = self._evaluate_user_opts(
        )

        # Apply limit after search / sorting etc.
        num_rows_unlimited = len(rows)
        limit = self.limit
        if limit is not None:
            # only use rows up to the limit plus the fixed rows
            rows = [
                rows[i] for i in range(num_rows_unlimited)
                if i < limit or rows[i][3]
            ]
            # Display corrected number of rows
            num_rows_unlimited -= len([r for r in rows if r[3]])

        # Render header
        self._write_table(rows, actions_enabled, actions_visible, search_term)

        if self.title and self.options["foldable"]:
            html.end_foldable_container()

        if limit is not None and num_rows_unlimited > limit:
            html.message(
                _('This table is limited to show only %d of %d rows. '
                  'Click <a href="%s">here</a> to disable the limitation.') %
                (limit, num_rows_unlimited, html.makeuri([('limit', 'none')])))

        if actions_enabled:
            config.user.save_file("tableoptions", user_opts)
        return
Ejemplo n.º 8
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.button("_save", _("Save"))
        html.button("_test", _("Save & Test"))
        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.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)
            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(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.º 9
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') % html.render_text(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 = html.render_text(
            _('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 = html.render_text(_('log file %s on all hosts') % file_name)

    html.header(_("Acknowledge %s") % 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.message('<b>%s</b><p>%s</p>' %
                 (_('Acknowledged %s') % ack_msg,
                  _('Acknowledged all messages in %s.') % ack_msg))
    html.footer()
Ejemplo n.º 10
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

    elif log_chunks == []:
        html.end_context_buttons()
        html.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()
Ejemplo n.º 11
0
def page_crashed(what):
    # Do not reveal crash context information to unauthenticated users or not permitted
    # users to prevent disclosure of internal information
    if not config.user.may("general.see_crash_reports"):
        html.header(_("Internal error"))
        html.show_error("<b>%s:</b> %s" %
                        (_("Internal error"), sys.exc_info()[1]))
        html.p(
            _("An internal error occurred while processing your request. "
              "You can report this issue to your Check_MK administrator. "
              "Detailed information can be found in <tt>var/log/web.log</tt>.")
        )
        html.footer()
        return

    if what == "check":
        site = html.request.var("site")
        host = html.request.var("host")
        service = html.request.var("service")

        tardata = get_crash_report_archive_as_string(site, host, service)
    else:
        tardata = create_gui_crash_report(what)

    info = get_crash_info(tardata)

    if what == "check":
        title = _("Crashed Check Reporting")
    else:
        title = _("Internal error")

    html.header(title)

    show_context_buttons(what, tardata)

    if html.request.has_var("_report") and html.check_transaction():
        details = handle_report_form(tardata, what)
    else:
        details = {}

    if what == "gui":
        # Unify different string types from exception messages to a unicode string
        exc_value = sys.exc_info()[1]
        try:
            exc_txt = unicode(exc_value)
        except UnicodeDecodeError:
            exc_txt = str(exc_value).decode("utf-8")

        html.show_error("<b>%s:</b> %s" % (_("Internal error"), exc_txt))
        html.p(
            _("An internal error occured while processing your request. "
              "You can report this issue to the Check_MK team to help "
              "fixing this issue. Please use the form below for reporting."))

    if info:
        warn_about_local_files(info)
        show_report_form(what, details)
        show_crash_report(info)
        show_crash_report_details(info)
    else:
        report_url = html.makeuri(
            [("subject", "Check_MK Crash Report - " + get_version(what))],
            filename="mailto:" + get_crash_report_target(what))
        html.message(
            _("This crash report is in a legacy format and can not be submitted "
              "automatically. Please download it manually and send it to <a href=\"%s\">%s</a>"
              ) % (report_url, get_crash_report_target(what)))
        show_old_dump_trace(tardata)

    show_agent_output(tardata)

    html.footer()
Ejemplo n.º 12
0
def _process_notify_message(msg):
    msg['id'] = utils.gen_id()
    msg['time'] = time.time()

    # construct the list of recipients
    recipients = []

    if isinstance(msg['dest'], str):
        dest_what = msg['dest']
    else:
        dest_what = msg['dest'][0]

    if dest_what == 'broadcast':
        recipients = config.multisite_users.keys()

    elif dest_what == 'online':
        recipients = userdb.get_online_user_ids()

    elif dest_what == 'list':
        recipients = msg['dest'][1]

    num_recipients = len(recipients)

    num_success = {}
    for method in msg['methods']:
        num_success[method] = 0

    # Now loop all notitification methods to send the notifications
    errors = {}
    for user_id in recipients:
        for method in msg['methods']:
            try:
                handler = _notify_methods()[method]['handler']
                handler(user_id, msg)
                num_success[method] = num_success[method] + 1
            except MKInternalError as e:
                errors.setdefault(method, []).append((user_id, e))

    message = _('The notification has been sent via<br>')
    message += "<table>"
    for method in msg['methods']:
        message += "<tr><td>%s</td><td>to %d of %d recipients</td></tr>" %\
                        (_notify_methods()[method]["title"], num_success[method], num_recipients)
    message += "</table>"

    message += _('<p>Sent notification to: %s</p>') % ', '.join(recipients)
    message += '<a href="%s">%s</a>' % (html.makeuri(
        []), _('Back to previous page'))
    html.message(HTML(message))

    if errors:
        error_message = ""
        for method, method_errors in errors.items():
            error_message += _(
                "Failed to send %s notifications to the following users:"
            ) % method
            table_rows = ''
            for user, exception in method_errors:
                table_rows += html.render_tr(html.render_td(html.render_tt(user))\
                                             + html.render_td(exception))
            error_message += html.render_table(table_rows) + html.render_br()
        html.show_error(HTML(error_message))
Ejemplo n.º 13
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()
Ejemplo n.º 14
0
 def page(self):
     html.message(_("(This module is not yet implemented)"))
Ejemplo n.º 15
0
    def _show_configuration_variables(self, groups):
        search_form(_("Search for settings:"))
        search = self._search

        html.open_div(class_="filter_buttons")
        if self._show_only_modified:
            html.buttonlink(html.makeuri([], delvars=["show_only_modified"]),
                            _("Show all settings"))
        else:
            html.buttonlink(html.makeuri([("show_only_modified", "1")]),
                            _("Show only modified settings"))
        html.close_div()

        at_least_one_painted = False
        html.open_div(class_="globalvars")
        for group in sorted(groups, key=lambda g: g.sort_index()):
            header_is_painted = False  # needed for omitting empty groups

            for config_variable_class in group.config_variables():
                config_variable = config_variable_class()
                varname = config_variable.ident()
                valuespec = config_variable.valuespec()

                if not config_variable.domain().enabled():
                    continue

                if config_variable.domain(
                ) == watolib.ConfigDomainCore and varname not in self._default_values:
                    if config.debug:
                        raise MKGeneralException(
                            "The configuration variable <tt>%s</tt> is unknown to "
                            "your local Check_MK installation" % varname)
                    else:
                        continue

                if not config_variable.in_global_settings():
                    continue

                if self._show_only_modified and varname not in self._current_settings:
                    continue

                help_text = valuespec.help() or ''
                title_text = valuespec.title()

                if search and search not in group.title().lower() \
                        and search not in config_variable.domain().ident.lower() \
                          and search not in varname \
                          and search not in help_text.lower() \
                          and search not in title_text.lower():
                    continue  # skip variable when search is performed and nothing matches
                at_least_one_painted = True

                if not header_is_painted:
                    # always open headers when searching
                    forms.header(group.title(),
                                 isopen=search or self._show_only_modified)
                    header_is_painted = True

                default_value = self._default_values[varname]

                edit_url = watolib.folder_preserving_link([
                    ("mode", self._edit_mode()), ("varname", varname),
                    ("site", html.request.var("site", ""))
                ])
                title = html.render_a(title_text,
                                      href=edit_url,
                                      class_="modified" if varname
                                      in self._current_settings else None,
                                      title=html.strip_tags(help_text))

                if varname in self._current_settings:
                    value = self._current_settings[varname]
                elif varname in self._global_settings:
                    value = self._global_settings[varname]
                else:
                    value = default_value

                try:
                    to_text = valuespec.value_to_text(value)
                except Exception:
                    logger.exception()
                    to_text = html.render_error(
                        _("Failed to render value: %r") % value)

                # Is this a simple (single) value or not? change styling in these cases...
                simple = True
                if '\n' in to_text or '<td>' in to_text:
                    simple = False
                forms.section(title, simple=simple)

                if varname in self._current_settings:
                    modified_cls = "modified"
                    title = _("This option has been modified.")
                elif varname in self._global_settings:
                    modified_cls = "modified globally"
                    title = _(
                        "This option has been modified in global settings.")
                else:
                    modified_cls = None
                    title = None

                if is_a_checkbox(valuespec):
                    html.open_div(
                        class_=["toggle_switch_container", modified_cls])
                    html.toggle_switch(
                        enabled=value,
                        help_txt=_("Immediately toggle this setting"),
                        href=html.makeactionuri([("_action", "toggle"),
                                                 ("_varname", varname)]),
                        class_=modified_cls,
                        title=title,
                    )
                    html.close_div()

                else:
                    html.a(HTML(to_text),
                           href=edit_url,
                           class_=modified_cls,
                           title=title)

            if header_is_painted:
                forms.end()
        if not at_least_one_painted and search:
            html.message(
                _('Did not find any global setting matching your search.'))
        html.close_div()
Ejemplo n.º 16
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 = html.request.var("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.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=None,
            elements=parameters,
            headers=keys_by_topic,
        )

        def validate(page_dict):
            owner_user_id = html.request.var("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 = html.request.var("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.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