def _import(self, csv_reader: CSVReader) -> ActionResult: if self._has_title_line: try: next(csv_reader) # skip header except StopIteration: pass num_succeeded, num_failed = 0, 0 fail_messages = [] selected = [] for row in csv_reader: if not row: continue # skip empty lines host_name, attributes = self._get_host_info_from_row(row) try: watolib.Folder.current().create_hosts([(host_name, attributes, None)]) selected.append('_c_%s' % host_name) num_succeeded += 1 except Exception as e: fail_messages.append( _("Failed to create a host from line %d: %s") % (csv_reader.line_num, e)) num_failed += 1 self._delete_csv_file() msg = _("Imported %d hosts into the current folder.") % num_succeeded if num_failed: msg += "<br><br>" + (_("%d errors occured:") % num_failed) msg += "<ul>" for fail_msg in fail_messages: msg += "<li>%s</li>" % fail_msg msg += "</ul>" if num_succeeded > 0 and html.request.var("do_service_detection") == "1": # Create a new selection for performing the bulk discovery config.user.set_rowselection(weblib.selection_id(), 'wato-folder-/' + watolib.Folder.current().path(), selected, 'set') html.request.set_var('mode', 'bulkinventory') html.request.set_var('_bulk_inventory', '1') html.request.set_var('show_checkboxes', '1') return "bulkinventory" return "folder", msg
def _bulk_actions(self, table, at_least_one_imported, top, withsearch, colspan, show_checkboxes): table.row(collect_headers=False, fixed=True) table.cell(css="bulksearch", colspan=3) if not show_checkboxes: onclick_uri = html.makeuri([('show_checkboxes', '1'), ('selection', weblib.selection_id())]) checkbox_title = _('Show Checkboxes and bulk actions') else: onclick_uri = html.makeuri([('show_checkboxes', '0')]) checkbox_title = _('Hide Checkboxes and bulk actions') html.toggle_button("checkbox_on", show_checkboxes, "checkbox", title=checkbox_title, onclick="location.href=\'%s\'" % onclick_uri, is_context_button=False) if withsearch: html.text_input("search") html.button("_search", _("Search")) html.set_focus("search") table.cell(css="bulkactions", colspan=colspan - 3) html.write_text(' ' + _("Selected hosts:\n")) if not self._folder.locked_hosts(): if config.user.may("wato.manage_hosts"): html.button("_bulk_delete", _("Delete")) if config.user.may("wato.edit_hosts"): html.button("_bulk_edit", _("Edit")) html.button("_bulk_cleanup", _("Cleanup")) if config.user.may("wato.services"): html.button("_bulk_inventory", _("Discovery")) if not self._folder.locked_hosts(): if config.user.may("wato.parentscan"): html.button("_parentscan", _("Parentscan")) if config.user.may("wato.edit_hosts") and config.user.may("wato.move_hosts"): self._host_bulk_move_to_folder_combo(top) if at_least_one_imported: html.button("_bulk_movetotarget", _("Move to Target Folders"))
def make_checkbox_selection_topic(selection_key: str, is_enabled: bool = True) -> PageMenuTopic: name_selected = _("Select all checkboxes") name_deselected = _("Deselect all checkboxes") is_selected = user.get_rowselection(weblib.selection_id(), selection_key) return PageMenuTopic( title=_("Selection"), entries=[ PageMenuEntry( name="checkbox_selection", title=name_deselected if is_selected else name_selected, icon_name="checkbox", item=make_javascript_link( "cmk.selection.toggle_all_rows(this.form, %s, %s);" % (json.dumps(name_selected), json.dumps(name_deselected))), is_enabled=is_enabled, ), ], )
def _show_hosts(self): if not self._folder.has_hosts(): return show_checkboxes = html.request.var('show_checkboxes', '0') == '1' hostnames = sorted(self._folder.hosts().keys(), key=utils.key_num_split) search_text = html.request.var("search") # Helper function for showing bulk actions. This is needed at the bottom # of the table of hosts and - if there are more than just a few - also # at the top of the table. search_shown = False # Show table of hosts in this folder html.begin_form("hosts", method="POST") with table_element("hosts", title=_("Hosts"), searchable=False, omit_empty_columns=True) as table: # Remember if that host has a target folder (i.e. was imported with # a folder information but not yet moved to that folder). If at least # one host has a target folder, then we show an additional bulk action. at_least_one_imported = False more_than_ten_items = False for num, hostname in enumerate(hostnames): if search_text and (search_text.lower() not in hostname.lower()): continue host = self._folder.host(hostname) effective = host.effective_attributes() if effective.get("imported_folder"): at_least_one_imported = True if num == 11: more_than_ten_items = True # Compute colspan for bulk actions colspan = 6 for attr in host_attribute_registry.attributes(): if attr.show_in_table(): colspan += 1 if not self._folder.locked_hosts() and config.user.may( "wato.edit_hosts") and config.user.may("wato.move_hosts"): colspan += 1 if show_checkboxes: colspan += 1 if self._folder.is_search_folder(): colspan += 1 # Add the bulk action buttons also to the top of the table when this # list shows more than 10 rows if more_than_ten_items and \ (config.user.may("wato.edit_hosts") or config.user.may("wato.manage_hosts")): self._bulk_actions(table, at_least_one_imported, True, True, colspan, show_checkboxes) search_shown = True contact_group_names = load_contact_group_information() host_errors = self._folder.host_validation_errors() rendered_hosts = [] # Now loop again over all hosts and display them for hostname in hostnames: self._show_host_row(rendered_hosts, table, hostname, search_text, show_checkboxes, colspan, host_errors, contact_group_names) if config.user.may("wato.edit_hosts") or config.user.may( "wato.manage_hosts"): self._bulk_actions(table, at_least_one_imported, False, not search_shown, colspan, show_checkboxes) html.hidden_fields() html.end_form() selected = config.user.get_rowselection( weblib.selection_id(), 'wato-folder-/' + self._folder.path()) row_count = len(rendered_hosts) headinfo = "%d %s" % (row_count, _("host") if row_count == 1 else _("hosts")) html.javascript("cmk.utils.update_header_info(%s);" % json.dumps(headinfo)) if show_checkboxes: selection_properties = { "page_id": "wato-folder-%s" % ('/' + self._folder.path()), "selection_id": weblib.selection_id(), "selected_rows": selected, } html.javascript('cmk.selection.init_rowselect(%s);' % (json.dumps(selection_properties)))
def _import(self, csv_reader: CSVReader) -> ActionResult: if self._has_title_line: try: next(csv_reader) # skip header except StopIteration: pass num_succeeded, num_failed = 0, 0 fail_messages = [] selected = [] imported_hosts = [] for row_num, row in enumerate(csv_reader): if not row: continue # skip empty lines host_name, attributes = self._get_host_info_from_row(row, row_num) try: watolib.Folder.current().create_hosts( [(host_name, attributes, None)], bake_hosts=False, ) imported_hosts.append(host_name) selected.append("_c_%s" % host_name) num_succeeded += 1 except Exception as e: fail_messages.append( _("Failed to create a host from line %d: %s") % (csv_reader.line_num, e)) num_failed += 1 watolib.hosts_and_folders.try_bake_agents_for_hosts(imported_hosts) self._delete_csv_file() msg = _("Imported %d hosts into the current folder.") % num_succeeded if num_failed: msg += "<br><br>" + (_("%d errors occured:") % num_failed) msg += "<ul>" for fail_msg in fail_messages: msg += "<li>%s</li>" % fail_msg msg += "</ul>" folder_path = watolib.Folder.current().path() if num_succeeded > 0 and request.var("do_service_detection") == "1": # Create a new selection for performing the bulk discovery user.set_rowselection( weblib.selection_id(), "wato-folder-/" + folder_path, selected, "set", ) return redirect( mode_url( "bulkinventory", _bulk_inventory="1", show_checkboxes="1", folder=folder_path, selection=weblib.selection_id(), )) flash(msg) return redirect(mode_url("folder", folder=folder_path))
def action(self) -> ActionResult: if html.request.var("_search"): # just commit to search form return None folder_url = self._folder.url() # Operations on SUBFOLDERS if html.request.var("_delete_folder"): if html.check_transaction(): self._folder.delete_subfolder(html.request.var("_delete_folder")) return redirect(folder_url) if html.request.has_var("_move_folder_to"): if html.check_transaction(): what_folder = watolib.Folder.folder(html.request.var("_ident")) target_folder = watolib.Folder.folder(html.request.var("_move_folder_to")) watolib.Folder.current().move_subfolder_to(what_folder, target_folder) return redirect(folder_url) # Operations on HOSTS # Deletion of single hosts delname = html.request.var("_delete_host") if delname and watolib.Folder.current().has_host(delname): watolib.Folder.current().delete_hosts([delname]) return redirect(folder_url) # Move single hosts to other folders if html.request.has_var("_move_host_to"): hostname = html.request.var("_ident") if hostname and watolib.Folder.current().has_host(hostname): target_folder = watolib.Folder.folder(html.request.var("_move_host_to")) watolib.Folder.current().move_hosts([hostname], target_folder) return redirect(folder_url) # bulk operation on hosts if not html.transaction_valid(): return redirect(folder_url) # Host table: No error message on search filter reset if html.request.var("_hosts_reset_sorting") or html.request.var("_hosts_sort"): return None selected_host_names = get_hostnames_from_checkboxes() if not selected_host_names: raise MKUserError(None, _("Please select some hosts before doing bulk operations on hosts.")) # Move if html.request.var("_bulk_move"): target_folder_path = html.request.var("_bulk_moveto", html.request.var("_top_bulk_moveto")) if target_folder_path == "@": raise MKUserError("_bulk_moveto", _("Please select the destination folder")) target_folder = watolib.Folder.folder(target_folder_path) watolib.Folder.current().move_hosts(selected_host_names, target_folder) flash(_("Moved %d hosts to %s") % (len(selected_host_names), target_folder.title())) return redirect(folder_url) # Move to target folder (from import) if html.request.var("_bulk_movetotarget"): self._move_to_imported_folders(selected_host_names) return redirect(folder_url) # Deletion if html.request.var("_bulk_delete"): return self._delete_hosts(selected_host_names) search_text = html.request.get_unicode_input_mandatory("search", "") for request_var, mode_name in [ ("_bulk_inventory", "bulkinventory"), ("_parentscan", "parentscan"), ("_bulk_edit", "bulkedit"), ("_bulk_cleanup", "bulkcleanup"), ]: if html.request.var(request_var): return redirect( self._folder.url(add_vars=[ ("mode", mode_name), ("search", search_text), ("selection", weblib.selection_id()), ])) return None
def _show_hosts(self): if not self._folder.has_hosts(): return hostnames = sorted(self._folder.hosts().keys(), key=utils.key_num_split) search_text = html.request.var("search") # Show table of hosts in this folder html.begin_form("hosts", method="POST") with table_element("hosts", title=_("Hosts"), searchable=False, omit_empty_columns=True) as table: # Compute colspan for bulk actions colspan = 6 for attr in host_attribute_registry.attributes(): if attr.show_in_table(): colspan += 1 if not self._folder.locked_hosts() and config.user.may( "wato.edit_hosts") and config.user.may("wato.move_hosts"): colspan += 1 if self._folder.is_search_folder(): colspan += 1 contact_group_names = load_contact_group_information() host_errors = self._folder.host_validation_errors() rendered_hosts: List[HostName] = [] # Now loop again over all hosts and display them max_hosts = len(hostnames) for hostname in hostnames: if table.limit_reached: table.limit_hint = max_hosts continue self._show_host_row(rendered_hosts, table, hostname, search_text, colspan, host_errors, contact_group_names) html.hidden_field("selection_id", weblib.selection_id()) html.hidden_fields() html.end_form() selected = config.user.get_rowselection( weblib.selection_id(), 'wato-folder-/' + self._folder.path()) row_count = len(hostnames) headinfo = "%d %s" % (row_count, _("host") if row_count == 1 else _("hosts")) html.javascript("cmk.utils.update_header_info(%s);" % json.dumps(headinfo)) selection_properties = { "page_id": "wato-folder-%s" % ('/' + self._folder.path()), "selection_id": weblib.selection_id(), "selected_rows": selected, } html.javascript('cmk.selection.init_rowselect(%s);' % (json.dumps(selection_properties)))