Utilize global registry to register model search classes

This commit is contained in:
jeremystretch 2022-10-10 10:09:40 -04:00
parent 5797ba0fd7
commit e67965ae22
19 changed files with 76 additions and 125 deletions

View File

@ -6,4 +6,4 @@ class CircuitsConfig(AppConfig):
verbose_name = "Circuits" verbose_name = "Circuits"
def ready(self): def ready(self):
import circuits.signals from . import signals, search

View File

@ -1,13 +1,13 @@
import circuits.filtersets import circuits.filtersets
import circuits.tables import circuits.tables
from circuits.models import Circuit, Provider, ProviderNetwork from circuits.models import Circuit, Provider, ProviderNetwork
from django.db import models
from netbox.search.models import SearchMixin from netbox.search.models import SearchMixin
from netbox.search import register_search
from utilities.utils import count_related from utilities.utils import count_related
@register_search(Provider)
class ProviderIndex(SearchMixin): class ProviderIndex(SearchMixin):
model = Provider
queryset = Provider.objects.annotate(count_circuits=count_related(Circuit, 'provider')) queryset = Provider.objects.annotate(count_circuits=count_related(Circuit, 'provider'))
filterset = circuits.filtersets.ProviderFilterSet filterset = circuits.filtersets.ProviderFilterSet
table = circuits.tables.ProviderTable table = circuits.tables.ProviderTable
@ -15,8 +15,8 @@ class ProviderIndex(SearchMixin):
choice_header = 'Circuits' choice_header = 'Circuits'
@register_search(Circuit)
class CircuitIndex(SearchMixin): class CircuitIndex(SearchMixin):
model = Circuit
queryset = Circuit.objects.prefetch_related( queryset = Circuit.objects.prefetch_related(
'type', 'provider', 'tenant', 'tenant__group', 'terminations__site' 'type', 'provider', 'tenant', 'tenant__group', 'terminations__site'
) )
@ -26,17 +26,10 @@ class CircuitIndex(SearchMixin):
choice_header = 'Circuits' choice_header = 'Circuits'
@register_search(ProviderNetwork)
class ProviderNetworkIndex(SearchMixin): class ProviderNetworkIndex(SearchMixin):
model = ProviderNetwork
queryset = ProviderNetwork.objects.prefetch_related('provider') queryset = ProviderNetwork.objects.prefetch_related('provider')
filterset = circuits.filtersets.ProviderNetworkFilterSet filterset = circuits.filtersets.ProviderNetworkFilterSet
table = circuits.tables.ProviderNetworkTable table = circuits.tables.ProviderNetworkTable
url = 'circuits:providernetwork_list' url = 'circuits:providernetwork_list'
choice_header = 'Circuits' choice_header = 'Circuits'
CIRCUIT_SEARCH_TYPES = {
'provider': ProviderIndex,
'circuit': CircuitIndex,
'providernetwork': ProviderNetworkIndex,
}

View File

@ -8,7 +8,7 @@ class DCIMConfig(AppConfig):
verbose_name = "DCIM" verbose_name = "DCIM"
def ready(self): def ready(self):
import dcim.signals from . import signals, search
from .models import CableTermination from .models import CableTermination
# Register denormalized fields # Register denormalized fields

View File

@ -14,11 +14,12 @@ from dcim.models import (
VirtualChassis, VirtualChassis,
) )
from netbox.search.models import SearchMixin from netbox.search.models import SearchMixin
from netbox.search import register_search
from utilities.utils import count_related from utilities.utils import count_related
@register_search(Site)
class SiteIndex(SearchMixin): class SiteIndex(SearchMixin):
model = Site
queryset = Site.objects.prefetch_related('region', 'tenant', 'tenant__group') queryset = Site.objects.prefetch_related('region', 'tenant', 'tenant__group')
filterset = dcim.filtersets.SiteFilterSet filterset = dcim.filtersets.SiteFilterSet
table = dcim.tables.SiteTable table = dcim.tables.SiteTable
@ -26,8 +27,8 @@ class SiteIndex(SearchMixin):
choice_header = 'DCIM' choice_header = 'DCIM'
@register_search(Rack)
class RackIndex(SearchMixin): class RackIndex(SearchMixin):
model = Rack
queryset = Rack.objects.prefetch_related('site', 'location', 'tenant', 'tenant__group', 'role').annotate( queryset = Rack.objects.prefetch_related('site', 'location', 'tenant', 'tenant__group', 'role').annotate(
device_count=count_related(Device, 'rack') device_count=count_related(Device, 'rack')
) )
@ -37,8 +38,8 @@ class RackIndex(SearchMixin):
choice_header = 'DCIM' choice_header = 'DCIM'
@register_search(RackReservation)
class RackReservationIndex(SearchMixin): class RackReservationIndex(SearchMixin):
model = RackReservation
queryset = RackReservation.objects.prefetch_related('rack', 'user') queryset = RackReservation.objects.prefetch_related('rack', 'user')
filterset = dcim.filtersets.RackReservationFilterSet filterset = dcim.filtersets.RackReservationFilterSet
table = dcim.tables.RackReservationTable table = dcim.tables.RackReservationTable
@ -46,8 +47,8 @@ class RackReservationIndex(SearchMixin):
choice_header = 'DCIM' choice_header = 'DCIM'
@register_search(Location)
class LocationIndex(SearchMixin): class LocationIndex(SearchMixin):
model = Site
queryset = Location.objects.add_related_count( queryset = Location.objects.add_related_count(
Location.objects.add_related_count(Location.objects.all(), Device, 'location', 'device_count', cumulative=True), Location.objects.add_related_count(Location.objects.all(), Device, 'location', 'device_count', cumulative=True),
Rack, Rack,
@ -61,8 +62,8 @@ class LocationIndex(SearchMixin):
choice_header = 'DCIM' choice_header = 'DCIM'
@register_search(DeviceType)
class DeviceTypeIndex(SearchMixin): class DeviceTypeIndex(SearchMixin):
model = DeviceType
queryset = DeviceType.objects.prefetch_related('manufacturer').annotate( queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(
instance_count=count_related(Device, 'device_type') instance_count=count_related(Device, 'device_type')
) )
@ -72,8 +73,8 @@ class DeviceTypeIndex(SearchMixin):
choice_header = 'DCIM' choice_header = 'DCIM'
@register_search(Device)
class DeviceIndex(SearchMixin): class DeviceIndex(SearchMixin):
model = Device
queryset = Device.objects.prefetch_related( queryset = Device.objects.prefetch_related(
'device_type__manufacturer', 'device_type__manufacturer',
'device_role', 'device_role',
@ -90,8 +91,8 @@ class DeviceIndex(SearchMixin):
choice_header = 'DCIM' choice_header = 'DCIM'
@register_search(ModuleType)
class ModuleTypeIndex(SearchMixin): class ModuleTypeIndex(SearchMixin):
model = ModuleType
queryset = ModuleType.objects.prefetch_related('manufacturer').annotate( queryset = ModuleType.objects.prefetch_related('manufacturer').annotate(
instance_count=count_related(Module, 'module_type') instance_count=count_related(Module, 'module_type')
) )
@ -101,8 +102,8 @@ class ModuleTypeIndex(SearchMixin):
choice_header = 'DCIM' choice_header = 'DCIM'
@register_search(Module)
class ModuleIndex(SearchMixin): class ModuleIndex(SearchMixin):
model = Module
queryset = Module.objects.prefetch_related( queryset = Module.objects.prefetch_related(
'module_type__manufacturer', 'module_type__manufacturer',
'device', 'device',
@ -114,8 +115,8 @@ class ModuleIndex(SearchMixin):
choice_header = 'DCIM' choice_header = 'DCIM'
@register_search(VirtualChassis)
class VirtualChassisIndex(SearchMixin): class VirtualChassisIndex(SearchMixin):
model = VirtualChassis
queryset = VirtualChassis.objects.prefetch_related('master').annotate( queryset = VirtualChassis.objects.prefetch_related('master').annotate(
member_count=count_related(Device, 'virtual_chassis') member_count=count_related(Device, 'virtual_chassis')
) )
@ -125,8 +126,8 @@ class VirtualChassisIndex(SearchMixin):
choice_header = 'DCIM' choice_header = 'DCIM'
@register_search(Cable)
class CableIndex(SearchMixin): class CableIndex(SearchMixin):
model = Cable
queryset = Cable.objects.all() queryset = Cable.objects.all()
filterset = dcim.filtersets.CableFilterSet filterset = dcim.filtersets.CableFilterSet
table = dcim.tables.CableTable table = dcim.tables.CableTable
@ -134,25 +135,10 @@ class CableIndex(SearchMixin):
choice_header = 'DCIM' choice_header = 'DCIM'
@register_search(PowerFeed)
class PowerFeedIndex(SearchMixin): class PowerFeedIndex(SearchMixin):
model = PowerFeed
queryset = PowerFeed.objects.all() queryset = PowerFeed.objects.all()
filterset = dcim.filtersets.PowerFeedFilterSet filterset = dcim.filtersets.PowerFeedFilterSet
table = dcim.tables.PowerFeedTable table = dcim.tables.PowerFeedTable
url = 'dcim:powerfeed_list' url = 'dcim:powerfeed_list'
choice_header = 'DCIM' choice_header = 'DCIM'
DCIM_SEARCH_TYPES = {
'site': SiteIndex,
'rack': RackIndex,
'rackreservation': RackReservationIndex,
'location': LocationIndex,
'devicetype': DeviceTypeIndex,
'device': DeviceIndex,
'moduletype': ModuleTypeIndex,
'module': ModuleIndex,
'virtualchassis': VirtualChassisIndex,
'cable': CableIndex,
'powerfeed': PowerFeedIndex,
}

View File

@ -5,5 +5,4 @@ class ExtrasConfig(AppConfig):
name = "extras" name = "extras"
def ready(self): def ready(self):
import extras.lookups from . import lookups, search, signals
import extras.signals

View File

@ -29,4 +29,5 @@ registry['model_features'] = {
feature: collections.defaultdict(set) for feature in EXTRAS_FEATURES feature: collections.defaultdict(set) for feature in EXTRAS_FEATURES
} }
registry['denormalized_fields'] = collections.defaultdict(list) registry['denormalized_fields'] = collections.defaultdict(list)
registry['search'] = collections.defaultdict(dict)
registry['views'] = collections.defaultdict(dict) registry['views'] = collections.defaultdict(dict)

View File

@ -6,4 +6,4 @@ class IPAMConfig(AppConfig):
verbose_name = "IPAM" verbose_name = "IPAM"
def ready(self): def ready(self):
import ipam.signals from . import signals, search

View File

@ -1,13 +1,12 @@
import ipam.filtersets import ipam.filtersets
import ipam.tables import ipam.tables
from django.db import models
from ipam.models import ASN, VLAN, VRF, Aggregate, IPAddress, Prefix, Service from ipam.models import ASN, VLAN, VRF, Aggregate, IPAddress, Prefix, Service
from netbox.search.models import SearchMixin from netbox.search.models import SearchMixin
from utilities.utils import count_related from netbox.search import register_search
@register_search(VRF)
class VRFIndex(SearchMixin): class VRFIndex(SearchMixin):
model = VRF
queryset = VRF.objects.prefetch_related('tenant', 'tenant__group') queryset = VRF.objects.prefetch_related('tenant', 'tenant__group')
filterset = ipam.filtersets.VRFFilterSet filterset = ipam.filtersets.VRFFilterSet
table = ipam.tables.VRFTable table = ipam.tables.VRFTable
@ -15,8 +14,8 @@ class VRFIndex(SearchMixin):
choice_header = 'IPAM' choice_header = 'IPAM'
@register_search(Aggregate)
class AggregateIndex(SearchMixin): class AggregateIndex(SearchMixin):
model = Aggregate
queryset = Aggregate.objects.prefetch_related('rir') queryset = Aggregate.objects.prefetch_related('rir')
filterset = ipam.filtersets.AggregateFilterSet filterset = ipam.filtersets.AggregateFilterSet
table = ipam.tables.AggregateTable table = ipam.tables.AggregateTable
@ -24,8 +23,8 @@ class AggregateIndex(SearchMixin):
choice_header = 'IPAM' choice_header = 'IPAM'
@register_search(Prefix)
class PrefixIndex(SearchMixin): class PrefixIndex(SearchMixin):
model = Prefix
queryset = Prefix.objects.prefetch_related( queryset = Prefix.objects.prefetch_related(
'site', 'vrf__tenant', 'tenant', 'tenant__group', 'vlan', 'role' 'site', 'vrf__tenant', 'tenant', 'tenant__group', 'vlan', 'role'
) )
@ -35,8 +34,8 @@ class PrefixIndex(SearchMixin):
choice_header = 'IPAM' choice_header = 'IPAM'
@register_search(IPAddress)
class IPAddressIndex(SearchMixin): class IPAddressIndex(SearchMixin):
model = IPAddress
queryset = IPAddress.objects.prefetch_related('vrf__tenant', 'tenant', 'tenant__group') queryset = IPAddress.objects.prefetch_related('vrf__tenant', 'tenant', 'tenant__group')
filterset = ipam.filtersets.IPAddressFilterSet filterset = ipam.filtersets.IPAddressFilterSet
table = ipam.tables.IPAddressTable table = ipam.tables.IPAddressTable
@ -44,8 +43,8 @@ class IPAddressIndex(SearchMixin):
choice_header = 'IPAM' choice_header = 'IPAM'
@register_search(VLAN)
class VLANIndex(SearchMixin): class VLANIndex(SearchMixin):
model = VLAN
queryset = VLAN.objects.prefetch_related('site', 'group', 'tenant', 'tenant__group', 'role') queryset = VLAN.objects.prefetch_related('site', 'group', 'tenant', 'tenant__group', 'role')
filterset = ipam.filtersets.VLANFilterSet filterset = ipam.filtersets.VLANFilterSet
table = ipam.tables.VLANTable table = ipam.tables.VLANTable
@ -53,8 +52,8 @@ class VLANIndex(SearchMixin):
choice_header = 'IPAM' choice_header = 'IPAM'
@register_search(ASN)
class ASNIndex(SearchMixin): class ASNIndex(SearchMixin):
model = ASN
queryset = ASN.objects.prefetch_related('rir', 'tenant', 'tenant__group') queryset = ASN.objects.prefetch_related('rir', 'tenant', 'tenant__group')
filterset = ipam.filtersets.ASNFilterSet filterset = ipam.filtersets.ASNFilterSet
table = ipam.tables.ASNTable table = ipam.tables.ASNTable
@ -62,21 +61,10 @@ class ASNIndex(SearchMixin):
choice_header = 'IPAM' choice_header = 'IPAM'
@register_search(Service)
class ServiceIndex(SearchMixin): class ServiceIndex(SearchMixin):
model = Service
queryset = Service.objects.prefetch_related('device', 'virtual_machine') queryset = Service.objects.prefetch_related('device', 'virtual_machine')
filterset = ipam.filtersets.ServiceFilterSet filterset = ipam.filtersets.ServiceFilterSet
table = ipam.tables.ServiceTable table = ipam.tables.ServiceTable
url = 'ipam:service_list' url = 'ipam:service_list'
choice_header = 'IPAM' choice_header = 'IPAM'
IPAM_SEARCH_TYPES = {
'vrf': VRFIndex,
'aggregate': AggregateIndex,
'prefix': PrefixIndex,
'ipaddress': IPAddressIndex,
'vlan': VLANIndex,
'asn': ASNIndex,
'service': ServiceIndex,
}

View File

@ -0,0 +1 @@
from .register import register_search

View File

@ -4,6 +4,8 @@ from django.conf import settings
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.db.models.signals import post_save, pre_delete from django.db.models.signals import post_save, pre_delete
from django.urls import reverse from django.urls import reverse
from extras.registry import registry
from netbox.constants import SEARCH_MAX_RESULTS from netbox.constants import SEARCH_MAX_RESULTS
# The cache for the initialized backend. # The cache for the initialized backend.
@ -71,7 +73,12 @@ class SearchBackend(object):
pre_delete.connect(self._pre_delete_receiver, model) pre_delete.connect(self._pre_delete_receiver, model)
def get_registry(self): def get_registry(self):
return self._registered_models # return self._registered_models
r = {}
for app_label, models in registry['search'].items():
r.update(**models)
return r
# Signalling hooks. # Signalling hooks.

View File

@ -1,30 +0,0 @@
from circuits.search_indexes import CIRCUIT_SEARCH_TYPES
from dcim.search_indexes import DCIM_SEARCH_TYPES
from extras.search_indexes import JOURNAL_SEARCH_TYPES
from ipam.search_indexes import IPAM_SEARCH_TYPES
from tenancy.search_indexes import TENANCY_SEARCH_TYPES
from virtualization.search_indexes import VIRTUALIZATION_SEARCH_TYPES
from wireless.search_indexes import WIRELESS_SEARCH_TYPES
SEARCH_TYPE_HIERARCHY = {
'Circuits': CIRCUIT_SEARCH_TYPES,
'DCIM': DCIM_SEARCH_TYPES,
'IPAM': IPAM_SEARCH_TYPES,
'Tenancy': TENANCY_SEARCH_TYPES,
'Virtualization': VIRTUALIZATION_SEARCH_TYPES,
'Wireless': WIRELESS_SEARCH_TYPES,
'Journal': JOURNAL_SEARCH_TYPES,
}
def build_search_types():
result = dict()
for app_types in SEARCH_TYPE_HIERARCHY.values():
for name, items in app_types.items():
result[name] = items
return result
SEARCH_TYPES = build_search_types()

View File

@ -6,8 +6,8 @@ from django.apps import apps
from django.conf import settings from django.conf import settings
from django.utils.module_loading import module_has_submodule from django.utils.module_loading import module_has_submodule
from extras.registry import registry
from .backends import default_search_engine from .backends import default_search_engine
from .hierarchy import SEARCH_TYPES
def get_app_modules(): def get_app_modules():
@ -19,8 +19,13 @@ def get_app_modules():
def register(): def register():
for name, module in SEARCH_TYPES.items():
default_search_engine.register(name, module) # for name, module in SEARCH_TYPES.items():
# default_search_engine.register(name, module)
for app_label, models in registry['search'].items():
for name, cls in models.items():
default_search_engine.register(name, cls)
for name, module in get_app_modules(): for name, module in get_app_modules():
submodule_name = "search_indexes" submodule_name = "search_indexes"
@ -37,3 +42,15 @@ def register():
cls_name = cls_obj.model.__name__.lower() cls_name = cls_obj.model.__name__.lower()
if not default_search_engine.is_registered(cls_name, cls_obj): if not default_search_engine.is_registered(cls_name, cls_obj):
default_search_engine.register(cls_name, cls_obj) default_search_engine.register(cls_name, cls_obj)
def register_search(model):
def _wrapper(cls):
app_label = model._meta.app_label
model_name = model._meta.model_name
registry['search'][app_label][model_name] = cls
return cls
return _wrapper

View File

@ -3,3 +3,6 @@ from django.apps import AppConfig
class TenancyConfig(AppConfig): class TenancyConfig(AppConfig):
name = 'tenancy' name = 'tenancy'
def ready(self):
from . import search

View File

@ -1,13 +1,13 @@
import tenancy.filtersets import tenancy.filtersets
import tenancy.tables import tenancy.tables
from django.db import models
from netbox.search.models import SearchMixin from netbox.search.models import SearchMixin
from netbox.search import register_search
from tenancy.models import Contact, ContactAssignment, Tenant from tenancy.models import Contact, ContactAssignment, Tenant
from utilities.utils import count_related from utilities.utils import count_related
@register_search(Tenant)
class TenantIndex(SearchMixin): class TenantIndex(SearchMixin):
model = Tenant
queryset = Tenant.objects.prefetch_related('group') queryset = Tenant.objects.prefetch_related('group')
filterset = tenancy.filtersets.TenantFilterSet filterset = tenancy.filtersets.TenantFilterSet
table = tenancy.tables.TenantTable table = tenancy.tables.TenantTable
@ -15,8 +15,8 @@ class TenantIndex(SearchMixin):
choice_header = 'Tenancy' choice_header = 'Tenancy'
@register_search(Contact)
class ContactIndex(SearchMixin): class ContactIndex(SearchMixin):
model = Contact
queryset = Contact.objects.prefetch_related('group', 'assignments').annotate( queryset = Contact.objects.prefetch_related('group', 'assignments').annotate(
assignment_count=count_related(ContactAssignment, 'contact') assignment_count=count_related(ContactAssignment, 'contact')
) )
@ -24,9 +24,3 @@ class ContactIndex(SearchMixin):
table = tenancy.tables.ContactTable table = tenancy.tables.ContactTable
url = 'tenancy:contact_list' url = 'tenancy:contact_list'
choice_header = 'Tenancy' choice_header = 'Tenancy'
TENANCY_SEARCH_TYPES = {
'tenant': TenantIndex,
'contact': ContactIndex,
}

View File

@ -3,3 +3,6 @@ from django.apps import AppConfig
class VirtualizationConfig(AppConfig): class VirtualizationConfig(AppConfig):
name = 'virtualization' name = 'virtualization'
def ready(self):
from . import search

View File

@ -1,13 +1,14 @@
import virtualization.filtersets import virtualization.filtersets
import virtualization.tables import virtualization.tables
from django.db import models from dcim.models import Device
from netbox.search.models import SearchMixin from netbox.search.models import SearchMixin
from netbox.search import register_search
from utilities.utils import count_related from utilities.utils import count_related
from virtualization.models import Cluster, Device, VirtualMachine from virtualization.models import Cluster, VirtualMachine
@register_search(Cluster)
class ClusterIndex(SearchMixin): class ClusterIndex(SearchMixin):
model = Cluster
queryset = Cluster.objects.prefetch_related('type', 'group').annotate( queryset = Cluster.objects.prefetch_related('type', 'group').annotate(
device_count=count_related(Device, 'cluster'), vm_count=count_related(VirtualMachine, 'cluster') device_count=count_related(Device, 'cluster'), vm_count=count_related(VirtualMachine, 'cluster')
) )
@ -17,8 +18,8 @@ class ClusterIndex(SearchMixin):
choice_header = 'Virtualization' choice_header = 'Virtualization'
@register_search(VirtualMachine)
class VirtualMachineIndex(SearchMixin): class VirtualMachineIndex(SearchMixin):
model = VirtualMachine
queryset = VirtualMachine.objects.prefetch_related( queryset = VirtualMachine.objects.prefetch_related(
'cluster', 'cluster',
'tenant', 'tenant',
@ -31,9 +32,3 @@ class VirtualMachineIndex(SearchMixin):
table = virtualization.tables.VirtualMachineTable table = virtualization.tables.VirtualMachineTable
url = 'virtualization:virtualmachine_list' url = 'virtualization:virtualmachine_list'
choice_header = 'Virtualization' choice_header = 'Virtualization'
VIRTUALIZATION_SEARCH_TYPES = {
'cluster': ClusterIndex,
'virtualmachine': VirtualMachineIndex,
}

View File

@ -5,4 +5,4 @@ class WirelessConfig(AppConfig):
name = 'wireless' name = 'wireless'
def ready(self): def ready(self):
import wireless.signals from . import signals, search

View File

@ -1,14 +1,14 @@
import wireless.filtersets import wireless.filtersets
import wireless.tables import wireless.tables
from dcim.models import Interface from dcim.models import Interface
from django.db import models
from netbox.search.models import SearchMixin from netbox.search.models import SearchMixin
from netbox.search import register_search
from utilities.utils import count_related from utilities.utils import count_related
from wireless.models import WirelessLAN, WirelessLink from wireless.models import WirelessLAN, WirelessLink
@register_search(WirelessLAN)
class WirelessLANIndex(SearchMixin): class WirelessLANIndex(SearchMixin):
model = WirelessLAN
queryset = WirelessLAN.objects.prefetch_related('group', 'vlan').annotate( queryset = WirelessLAN.objects.prefetch_related('group', 'vlan').annotate(
interface_count=count_related(Interface, 'wireless_lans') interface_count=count_related(Interface, 'wireless_lans')
) )
@ -18,16 +18,10 @@ class WirelessLANIndex(SearchMixin):
choice_header = 'Wireless' choice_header = 'Wireless'
@register_search(WirelessLink)
class WirelessLinkIndex(SearchMixin): class WirelessLinkIndex(SearchMixin):
model = WirelessLink
queryset = WirelessLink.objects.prefetch_related('interface_a__device', 'interface_b__device') queryset = WirelessLink.objects.prefetch_related('interface_a__device', 'interface_b__device')
filterset = wireless.filtersets.WirelessLinkFilterSet filterset = wireless.filtersets.WirelessLinkFilterSet
table = wireless.tables.WirelessLinkTable table = wireless.tables.WirelessLinkTable
url = 'wireless:wirelesslink_list' url = 'wireless:wirelesslink_list'
choice_header = 'Wireless' choice_header = 'Wireless'
WIRELESS_SEARCH_TYPES = {
'wirelesslan': WirelessLANIndex,
'wirelesslink': WirelessLinkIndex,
}