def _parameter_valuespec_cisco_wlc(): return Dictionary( help=_( "Here you can set which alert type is set when the given " "access point is missing (might be powered off). The access point " "can be specified by the AP name or the AP model"), elements=[("ap_name", ListOf(Tuple(elements=[ TextAscii(title=_("AP name")), MonitoringState(title=_("State when missing"), default_value=2) ], ), title=_("Access point name"), add_label=_("Add name")))], )
def _valuespec_if_groups(): node_name_elements: List[DictionaryEntry] = [("node_name", TextAscii(title=_("Node name")))] return Transform(Alternative( title=_('Network interface groups'), help= _('Normally the Interface checks create a single service for interface. ' 'By defining if-group patterns multiple interfaces can be combined together. ' 'A single service is created for this interface group showing the total traffic amount ' 'of its members. You can configure if interfaces which are identified as group interfaces ' 'should not show up as single service. You can restrict grouped interfaces by iftype and the ' 'item name of the single interface.'), elements=[ ListOf( title=_("Groups on single host"), add_label=_("Add pattern"), valuespec=Dictionary(elements=vs_elements_if_groups_group + vs_elements_if_groups_matches, required_keys=["group_name", "group_presence"]), ), ListOf(magic="@!!", title=_("Groups on cluster"), add_label=_("Add pattern"), valuespec=Dictionary(elements=vs_elements_if_groups_group + [("node_patterns", ListOf( title=_("Patterns for each node"), add_label=_("Add pattern"), valuespec=Dictionary(elements=node_name_elements + vs_elements_if_groups_matches, required_keys=["node_name"]), allow_empty=False, ))], optional_keys=[])), ], ), forth=transform_if_groups_forth)
def _tag_choices_valuespec(self): # We want the compact tuple style visualization which is not # supported by the Dictionary valuespec. Transform! return Transform( ListOf( Tuple( elements=[ TextAscii( title=_("Tag ID"), size=16, regex="^[-a-z0-9A-Z_]*$", none_is_empty=True, regex_error=_( "Invalid tag ID. Only the characters a-z, A-Z, " "0-9, _ and - are allowed.")), TextUnicode(title=_("Title") + "*", allow_empty=False, size=40), Foldable( ListChoice( title=_("Auxiliary tags"), choices=self._effective_config.aux_tag_list. get_choices(), )), ], show_titles=True, orientation="horizontal", ), add_label=_("Add tag choice"), row_label="@. Choice", sort_by=1, # sort by description help= _("The first choice of a tag group will be its default value. " "If a tag group has only one choice, it will be displayed " "as a checkbox and set or not set the only tag. If it has " "more choices you may leave at most one tag id empty. A host " "with that choice will not get any tag of this group.<br><br>" "The tag ID must contain only of letters, digits and " "underscores.<br><br><b>Renaming tags ID:</b> if you want " "to rename the ID of a tag, then please make sure that you do not " "change its title at the same time! Otherwise WATO will not " "be able to detect the renaming and cannot exchange the tags " "in all folders, hosts and rules accordingly."), ), forth=lambda x: [(c["id"], c["title"], c["aux_tags"]) for c in x], back=lambda x: [dict(zip(["id", "title", "aux_tags"], c)) for c in x], )
def _valuespec_inventory_df_rules(): return Dictionary( title=_("Discovery parameters for filesystem checks"), elements=[ ("include_volume_name", Transform( CascadingDropdown( title=_("Service description format"), choices= [(False, _("Name of mount point")), (True, _("Name of volume and name of mount point"), DropdownChoice( label=_("Filesystem grouping"), choices=[ ('mountpoint', _('Grouping pattern applies to mount point only' )), ('volume_name_and_mountpoint', _('Grouping pattern applies to volume name and mount point' )), ], help=_( "Specifies how the <a href='wato.py?mode=edit_ruleset&varname=filesystem_groups'>Filesystem grouping patterns</a> " "feature processes this filesystem."), ))]), forth=lambda x: (True, "mountpoint") if x is True else x, )), ("ignore_fs_types", ListChoice(title=_("Filesystem types to ignore"), choices=[ ("tmpfs", "tmpfs"), ("nfs", "nfs"), ("smbfs", "smbfs"), ("cifs", "cifs"), ("iso9660", "iso9660"), ], default_value=[ "tmpfs", "nfs", "smbfs", "cifs", "iso9660" ])), ("never_ignore_mountpoints", ListOf( TextOrRegExpUnicode(), title=_("Mountpoints to never ignore"), help=_( "Regardless of filesystem type, these mountpoints will always be discovered." "Regular expressions are supported."))), ], )
def levels_absolute_or_dynamic(name, value): return Alternative( title=_("Levels of %s %s") % (name, value), default_value=(80.0, 90.0), elements=[ Tuple(title=_("Percentage %s space") % value, elements=[ Percentage(title=_("Warning at"), unit=_("% used")), Percentage(title=_("Critical at"), unit=_("% used")), ]), Tuple(title=_("Absolute %s space") % value, elements=[ Integer(title=_("Warning at"), unit=_("MB"), default_value=500), Integer(title=_("Critical at"), unit=_("MB"), default_value=1000), ]), ListOf( Tuple( orientation="horizontal", elements=[ Filesize(title=_(" larger than")), Alternative( title=_("Levels for the %s %s size") % (name, value), elements=[ Tuple(title=_("Percentage %s space") % value, elements=[ Percentage(title=_("Warning at"), unit=_("% used")), Percentage(title=_("Critical at"), unit=_("% used")), ]), Tuple(title=_("Absolute free space"), elements=[ Integer(title=_("Warning at"), unit=_("MB")), Integer(title=_("Critical at"), unit=_("MB")), ]), ]), ], ), title=_('Dynamic levels'), ), ])
def _parameter_valuespec_fcp(): return Dictionary(elements=[ ("speed", OptionalDropdownChoice(title=_("Operating speed"), help=_( "If you use this parameter then the check goes warning if the " "interface is not operating at the expected speed (e.g. it " "is working with 8Gbit/s instead of 16Gbit/s)."), choices=[ (None, _("ignore speed")), (4000000000, "4 Gbit/s"), (8000000000, "8 Gbit/s"), (16000000000, "16 Gbit/s"), ], otherlabel=_("specify manually ->"), explicit=Integer(title=_("Other speed in bits per second"), label=_("Bits per second")))), ("traffic", ListOf( CascadingDropdown( title=_("Direction"), orientation="horizontal", choices=[ ('both', _("In / Out"), vs_interface_traffic()), ('in', _("In"), vs_interface_traffic()), ('out', _("Out"), vs_interface_traffic()), ], ), title=_("Used bandwidth (minimum or maximum traffic)"), help=_("Setting levels on the used bandwidth is optional. If you do set " "levels you might also consider using averaging."), )), ("read_latency", Levels(title=_("Read latency"), unit=_("ms"), default_value=None, default_levels=(50.0, 100.0))), ("write_latency", Levels(title=_("Write latency"), unit=_("ms"), default_value=None, default_levels=(50.0, 100.0))), ("latency", Levels(title=_("Overall latency"), unit=_("ms"), default_value=None, default_levels=(50.0, 100.0))), ],)
def _vs_inventory_paths_and_keys(self) -> CascadingDropdown: def vs_choices(title): return CascadingDropdown( title=title, choices=[ ("nothing", _("Restrict all")), ( "choices", _("Restrict the following keys"), ListOfStrings( orientation="horizontal", size=15, allow_empty=True, ), ), ], default_value="nothing", ) return CascadingDropdown( choices=[ ("allow_all", _("Allowed to see the whole tree")), ("forbid_all", _("Forbid to see the whole tree")), ( "paths", _("Allowed to see parts of the tree"), ListOf( Dictionary( elements=[ vs_element_inventory_visible_raw_path(), ("attributes", vs_choices(_("Restrict single values"))), ("columns", vs_choices(_("Restrict table columns"))), ("nodes", vs_choices(_("Restrict subcategories"))), ], optional_keys=["attributes", "columns", "nodes"], ), help=vs_inventory_path_or_keys_help() + _("<br>If single values, table columns or subcategories are not" " restricted, then all entries are added respectively." ), ), ), ], default_value="allow_all", )
def _parameter_valuespec_solaris_services(): return Dictionary(elements=[ ("additional_servicenames", ListOfStrings( title=_("Alternative names for the service"), help= _("Here you can specify alternative names that the service might have. " "This helps when the exact spelling of the services can changed from " "one version to another."), )), ("states", ListOf( Tuple( orientation="horizontal", elements=[ DropdownChoice( title=_("Expected state"), choices=[ (None, _("Ignore the state")), ("online", _("Online")), ("disabled", _("Disabled")), ("maintenance", _("Maintenance")), ("legacy_run", _("Legacy run")), ], ), DropdownChoice( title=_("STIME"), choices=[ (None, _("Ignore")), (True, _("Has changed")), (False, _("Did not changed")), ], ), MonitoringState(title=_("Resulting state"), ), ], ), title=_("Services states"), help= _("You can specify a separate monitoring state for each possible " "combination of service state. If you do not use this parameter, " "then only online/legacy_run will be assumed to be OK."), )), ("else", MonitoringState( title=_("State if no entry matches"), default_value=2, )), ], )
def __element(): return Tuple(elements=[ age_levels_dropdown(), ListOf( valuespec=RegExp( mode=RegExp.infix, title=_("Status"), allow_empty=False, size=50, ), add_label=_("Add new status"), allow_empty=False, movable=False, help=RegExp(mode=RegExp.infix).help(), ), ], )
def valuespec(self): return ListOf( Dictionary(optional_keys=[], elements=[ ('title', TextUnicode( title=_('Title'), allow_empty=False, )), ('duration', Age(title=_("Duration"), )), ]), title=_("Custom graph timeranges"), movable=True, totext=_("%d timeranges"), default_value=config.graph_timeranges, )
def gen_agent_config_dict_listof_testsuites(mode): titledict = { 'agent_serial': 'to execute', 'agent_parallel': 'to execute individually', 'external': 'to be executed externally' } return ListOf( gen_testsuite_tuple(mode), help=_(""" Click on '<i>Add test suite</i>' to specify the suites to be executed, including additional parameters, piggyback host and execution order. This is the recommended way.<br> If you do not add any suite here, the Robotmk plugin will add every <tt>.robot</tt> file/every directory within the <i>Robot suites directory</i> to the execution list - without any further parametrization.<br>""" ), add_label=_("Add test suite"), movable=True, title=_("Suites"), )
def _parameter_valuespec_win_firewall_status(): return Dictionary( title=_('Time left for installed certificates before renew.'), elements=[ ("profiles", ListOf( Tuple(elements=[ TextAscii( title=_("Profile name"), help=_("Name of the firewall profile."), ), DropdownChoice( title=_("State"), help=_("Profile state active or inaktive"), choices=[ ("True", _("Enabled")), ("False", _("Disabled")), ], ), DropdownChoice( title=_("Incomming Action"), help=_("Default behaviour for incomming traffic."), choices=[ ("Block", _("Block")), ("Allow", _("Allow")), ], ), DropdownChoice( title=_("Outgoing Action"), help=_("Default behaviour for outgoing traffic."), choices=[ ("Block", _("Block")), ("Allow", _("Allow")), ], ), ], ), title=_("Firewall Profile configuration"), help=_("Please select the abropriate profile configuration."), allow_empty=False, default_value=[ ("Domain", "True", "Block", "Allow"), ("Privat", "True", "Block", "Allow"), ("Public", "True", "Block", "Allow"), ], )), ], )
def _parameter_valuespec_job(): return Dictionary(elements=[ ( "age", Tuple( title=_("Maximum time since last start of job execution"), elements=[ Age(title=_("Warning at"), default_value=0), Age(title=_("Critical at"), default_value=0), ], ), ), ( "exit_code_to_state_map", ListOf( Tuple( orientation="horizontal", elements=[ Integer(title=_("Exit code")), MonitoringState(title=_("Resulting state"), ), ], default_value=(0, 0), ), title=_("Explicit mapping of job exit codes to states"), help= _("Here you can define a mapping between possible exit codes and service states. " "If no mapping is defined, the check becomes CRITICAL when the exit code is not 0. " "If an exit code occurs that is not defined in this mapping, the check becomes CRITICAL. " "If you happen to define the same exit code multiple times the first entry will be used." ), allow_empty=False, ), ), ( "outcome_on_cluster", DropdownChoice( title="%s - %s" % ( _("Clusters: Preferred check result of local checks"), _deprecation_message(), ), choices=[], deprecated_choices=("worst", "best"), invalid_choice_title=_( 'Old setting: "%s". Choose that in the new ruleset.'), ), ), ], )
def _valuespec_inv_retention_intervals() -> ValueSpec: def vs_choices(title): return CascadingDropdown( title=title, choices=[ ("all", _("Choose all")), ( "choices", _("Choose the following keys"), ListOfStrings( orientation="horizontal", size=15, allow_empty=True, ), ), ], default_value="choices", ) return ListOf( Dictionary( elements=[ ( "interval", Age( title=_( "How long single values or table columns are kept." ), minvalue=1, default_value=3600 * 2, display=["days", "hours", "minutes"], ), ), vs_element_inventory_visible_raw_path(), ("attributes", vs_choices(_("Choose single values"))), ("columns", vs_choices(_("Choose table columns"))), ], optional_keys=["attributes", "columns"], ), title=_("Retention intervals for HW/SW inventory entities"), help=vs_inventory_path_or_keys_help() + _("<br>With these intervals specific single values or table columns can be kept" " from the previous inventory tree if the current agent output does not" " provide any new data for these entries." "<br>Only entries corresponding to chosen single values or columns are added." ), )
def hr_process_parameter_elements(): return [ ('levels', Tuple( title=_('Levels for process count'), help=_("Please note that if you specify and also if you modify levels " "here, the change is activated only during an inventory." "Saving this rule is not enough. This is due to the nature of" "inventory rules."), elements=[ Integer( title=_("Critical below"), unit=_("processes"), default_value=1, ), Integer( title=_("Warning below"), unit=_("processes"), default_value=1, ), Integer( title=_("Warning above"), unit=_("processes"), default_value=99999, ), Integer( title=_("Critical above"), unit=_("processes"), default_value=99999, ), ], )), ('status', ListOf( Tuple(orientation="horizontal", elements=[ DropdownChoice(choices=[ ('running', _('Running')), ('runnable', _('Runnable (Waiting for resource)')), ('not_runnable', _('Not runnable (Loaded but waiting for event)')), ('invalid', _('Invalid (Not loaded)')), ]), MonitoringState() ]), title=_('Map process states'), )), ]
def _parameter_valuespec_hostsystem_sensors(): return ListOf(Dictionary( help=_("This rule allows to override alert levels for the given sensor names."), elements=[("name", TextAscii(title=_("Sensor name"))), ("states", Dictionary( title=_("Custom states"), elements=[(element, MonitoringState(title="Sensor %s" % description, label=_("Set state to"), default_value=int(element))) for (element, description) in [("0", _("OK")), ( "1", _("WARNING")), ("2", _("CRITICAL")), ("3", _("UNKNOWN"))] ], ))], optional_keys=False), add_label=_("Add sensor name"))
def _parameter_valuespec_vpn_tunnel(): return Dictionary( elements=[ ( "tunnels", ListOf( Tuple( title=("VPN Tunnel Endpoints"), elements=[ IPv4Address( title=_("IP-Address or Name of Tunnel Endpoint"), help=_( "The configured value must match a tunnel reported by the monitored " "device." ), ), TextInput( title=_("Tunnel Alias"), help=_( "You can configure an individual alias here for the tunnel matching " "the IP-Address or Name configured in the field above." ), ), MonitoringState( default_value=2, title=_("State if tunnel is not found"), ), ], ), add_label=_("Add tunnel"), movable=False, title=_("VPN tunnel specific configuration"), ), ), ( "state", MonitoringState( title=_("Default state to report when tunnel can not be found anymore"), help=_( "Default state if a tunnel, which is not listed above in this rule, " "can no longer be found." ), ), ), ], )
def vs_parameters(cls): return [ ("rows", ListOf( Dictionary( elements=[ ("title", TextUnicode( title=_("Title"), allow_empty=False, )), ("query", CascadingDropdown( orientation="horizontal", title=_("Query"), label=_("Table") + ": ", choices=[ ("hosts", _("Hosts"), visuals.VisualFilterList(info_list=["host" ],)), ("services", _("Services"), visuals.VisualFilterList(info_list=["host", "service"],)), ("events", _("Events"), visuals.VisualFilterList(info_list=["host", "event"],)), ])), ], optional_keys=[], ), title=_("Rows"), add_label=_("Add new row"), del_label=_("Delete this row"), allow_empty=False, )), ("show_stale", Checkbox( title=_("Show stale hosts and services"), default_value=True, )), ("show_failed_notifications", Checkbox( title=_("Show failed notifications"), default_value=True, )), ("show_sites_not_connected", Checkbox( title=_("Display a message if sites are not connected"), default_value=True, )), ]
def get_free_used_dynamic_valuespec(what, name, default_value=(80.0, 90.0)): if what == "used": title = _("used space") course = _("above") else: title = _("free space") course = _("below") vs_subgroup = [ Tuple( title=_("Percentage %s") % title, elements=[ Percentage(title=_("Warning if %s") % course, unit="%", minvalue=0.0), Percentage(title=_("Critical if %s") % course, unit="%", minvalue=0.0), ]), Tuple( title=_("Absolute %s") % title, elements=[ Integer(title=_("Warning if %s") % course, unit=_("MB"), minvalue=0), Integer(title=_("Critical if %s") % course, unit=_("MB"), minvalue=0), ]) ] def validate_dynamic_levels(value, varprefix): if [v for v in value if v[0] < 0]: raise MKUserError(varprefix, _("You need to specify levels " "of at least 0 bytes.")) return Alternative( title=_("Levels for %s %s") % (name, title), style="dropdown", show_alternative_title=True, default_value=default_value, elements=vs_subgroup + [ ListOf( Tuple( orientation="horizontal", elements=[ Filesize(title=_("%s larger than") % name.title()), Alternative(elements=vs_subgroup) ]), title=_('Dynamic levels'), allow_empty=False, validate=validate_dynamic_levels, ) ], )
def _parameter_valuespec_websphere_mq_instance(): return Dictionary(elements=[ ("map_instance_states", ListOf( Tuple( orientation="horizontal", elements=[ DropdownChoice(choices=[ ('active', _('Active')), ('standby', _('Standby')), ], ), MonitoringState(), ], ), title=_('Map instance state'), )), ], )
def _valuespec_fileinfo_groups(): return Transform( Dictionary( title=_("Group patterns"), elements=[ ( "group_patterns", ListOf( Tuple( help=_("This defines one file grouping pattern."), show_titles=True, orientation="horizontal", elements=[ TextInput( title=_("Name of group"), size=20, ), Transform( Tuple( show_titles=True, orientation="vertical", elements=[ TextInput( title=_("Include Pattern"), size=40), TextInput( title=_("Exclude Pattern"), size=40), ], ), forth=lambda params: isinstance( params, str) and (params, "") or params, ), ], ), title=_("File Grouping Patterns"), help=_get_fileinfo_groups_help(), add_label=_("Add pattern group"), ), ), ], ), forth=_transform_fileinfo_groups, )
def _vs(self): return Dictionary(title=_("Read only mode"), optional_keys=False, render="form", elements=[ ("enabled", Alternative(title=_("Enabled"), elements=[ FixedValue( False, title=_("Disabled "), totext="Not enabled", ), FixedValue( True, title=_("Enabled permanently"), totext=_("Enabled until disabling"), ), Tuple(title=_("Enabled in time range"), elements=[ AbsoluteDate( title=_("Start"), include_time=True, ), AbsoluteDate( title=_("Until"), include_time=True, default_value=time.time() + 3600, ), ]) ])), ("rw_users", ListOf( userdb.UserSelection(), title=_("Can still edit"), help=_("Users listed here are still allowed to modify things."), movable=False, add_label=_("Add user"), default_value=[config.user.id], )), ("message", TextAreaUnicode( title=_("Message"), rows=3, )), ])
def _parameter_valuespec_ibm_mq_channels(): return Dictionary(elements=[ ( "mapped_states", ListOf( valuespec=Tuple( orientation="horizontal", elements=[ DropdownChoice( title=_("Channel state"), choices=[ ("inactive", "INACTIVE"), ("initializing", "INITIALIZING"), ("binding", "BINDING"), ("starting", "STARTING"), ("running", "RUNNING"), ("retrying", "RETRYING"), ("stopping", "STOPPING"), ("stopped", "STOPPED"), ], ), MonitoringState(title=_("Service state"), ), ], ), title=_("Map channel state to service state"), help=_( """If you do not use this parameter, the following factory defaults apply:<br> INACTIVE: OK<br> INITIALIZING: OK<br> BINDING: OK<br> STARTING: OK<br> RUNNING: OK<br> RETRYING: WARN<br> STOPPING: OK<br> STOPPED: CRIT<br> """), ), ), ( "mapped_states_default", MonitoringState(title=_("Service state if no map rule matches"), default_value=2), ), ], )
def valuespec_alert_remapping(): return ListOf( Dictionary( elements=[ ( "rule_names", ListOfStrings( title=_("Alert rule names"), help=_("A list of rule names as defined in Alertmanager."), ), ), ( "map", Dictionary( title=_("States"), elements=[ ("inactive", MonitoringState(title="inactive")), ("pending", MonitoringState(title="pending")), ("firing", MonitoringState(title="firing")), ("none", MonitoringState(title="none")), ("n/a", MonitoringState(title="n/a")), ], optional_keys=[], ), ), ], optional_keys=[], ), title=_("Remap alert rule states"), add_label=_("Add mapping"), help=_("Configure the monitoring state for Alertmanager rules."), allow_empty=False, default_value=[ { "map": { "inactive": 2, "pending": 2, "firing": 0, "none": 2, "n/a": 2, }, "rule_names": ["Watchdog"], } ], )
def _vs_aws_tags(title): return ListOf( valuespec=Tuple( help=_( "How to configure AWS tags please see " "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html" ), orientation="horizontal", elements=[ TextInput(title=_("Key")), ListOfStrings(title=_("Values"), orientation="horizontal"), ], ), add_label=_("Add new tag"), movable=False, title=title, validate=validate_aws_tags, )
def _parameter_valuespec_mem_cluster(): return ListOf( Tuple( elements=[ Integer(title=_("Equal or more than"), unit=_("nodes")), Tuple( title=_("Percentage of total RAM"), elements=[ Percentage(title=_("Warning at a RAM usage of"), default_value=80.0), Percentage(title=_("Critical at a RAM usage of"), default_value=90.0), ], ), ] ), help=_("Here you can specify the total memory usage levels for clustered hosts."), title=_("Memory Usage"), add_label=_("Add limits"), )
def _valuespec_logwatch_groups(): return Transform( Dictionary( title=_("Logfile Grouping"), elements=[ ( "grouping_patterns", ListOf( Tuple( help=_( "This defines one logfile grouping pattern"), show_titles=True, orientation="horizontal", elements=[ TextInput(title=_("Name of group"), ), Tuple( show_titles=True, orientation="vertical", elements=[ TextInput(title=_("Include Pattern")), TextInput(title=_("Exclude Pattern")), ], ), ], ), add_label=_("Add pattern group"), title=_("List Grouping Patterns"), ), ), ], optional_keys=[], help= _("The check <tt>logwatch</tt> normally creates one service for each logfile. " "By defining grouping patterns you can switch to the check <tt>logwatch.groups</tt>. " "If the pattern begins with a tilde then this pattern is interpreted as a regular " "expression instead of as a filename globbing pattern and <tt>*</tt> and <tt>?</tt> " "are treated differently. " "That check monitors a list of logfiles at once. This is useful if you have " "e.g. a folder with rotated logfiles where the name of the current logfile" "also changes with each rotation"), ), forth=lambda p: p if isinstance(p, dict) else {"grouping_patterns": p}, )
def valuespec(cls): return Dictionary( elements=[("arguments", ListOf( Transform( Tuple(elements=[ TextInput(title=_("Keyword")), ListOfStrings( title=_("Values"), orientation="horizontal", ) ]), forth=cls._convert_to_vs, back=cls._convert_from_vs, ), magic="#keys#", ))], optional_keys=[], )
def parameter_valuespec(self): return Dictionary( help= _("This rule allows you to specify levels for the voltage, current, power " "and apparent power of your device. The levels will only be applied if the device " "actually supplies values for these parameters."), elements=_phase_elements() + [ ("map_device_states", ListOf( Tuple(elements=[TextAscii( size=10), MonitoringState()]), title=_("Map device state"), help= _("Here you can enter either device state number (eg. from SNMP devices) " "or exact device state name and the related monitoring state." ), )), ], )
def _parameter_valuespec_websphere_mq_instance(): return Dictionary(elements=[ ( "map_instance_states", ListOf( Tuple( orientation="horizontal", elements=[ DropdownChoice(choices=[ ("active", _("Active")), ("standby", _("Standby")), ], ), MonitoringState(), ], ), title=_("Map instance state"), ), ), ], )