class RackReservationTable(BaseTable): pk = ToggleColumn() reservation = tables.Column(accessor="pk", linkify=True) site = tables.Column(accessor=Accessor("rack__site"), linkify=True) tenant = TenantColumn() rack = tables.Column(linkify=True) unit_list = tables.Column(orderable=False, verbose_name="Units") tags = TagColumn(url_name="dcim:rackreservation_list") actions = ButtonsColumn(RackReservation) class Meta(BaseTable.Meta): model = RackReservation fields = ( "pk", "reservation", "site", "rack", "unit_list", "user", "created", "tenant", "description", "tags", "actions", ) default_columns = ( "pk", "reservation", "site", "rack", "unit_list", "user", "description", "actions", )
class CommandTokenTable(BaseTable): """Table for rendering a listing of CommandToken entries.""" pk = ToggleColumn() platform = TemplateColumn( template_code= '<span style="font-family: monospace">{{ record.platform }}</span>') token = TemplateColumn( template_code= '<span style="font-family: monospace">{{ record.token }}</span>') comment = TemplateColumn( template_code= '<span style="font-family: monospace">{{ record.comment }}</span>') actions = TemplateColumn( template_code=""" <a href="{% url 'plugins:nautobot_chatops:commandtoken_changelog' pk=record.pk %}" class="btn btn-default btn-xs" title="Change log"><span class="mdi mdi-history"></span></a> {% if perms.nautobot_chatops.change_commandtoken %} <a href="{% url 'plugins:nautobot_chatops:commandtoken_edit' pk=record.pk %}" class="btn btn-xs btn-warning"><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span></a> {% endif %}""", attrs={"td": { "class": "text-right noprint" }}, verbose_name="", ) class Meta(BaseTable.Meta): """Metaclass attributes of CommandTokenTable.""" model = CommandToken fields = ("pk", "platform", "token", "comment", "actions") default_columns = ("pk", "platform", "comment", "actions")
class RoleTable(BaseTable): pk = ToggleColumn() name = tables.LinkColumn() prefix_count = LinkedCountColumn( viewname="ipam:prefix_list", url_params={"role": "slug"}, verbose_name="Prefixes", ) vlan_count = LinkedCountColumn(viewname="ipam:vlan_list", url_params={"role": "slug"}, verbose_name="VLANs") actions = ButtonsColumn(Role, pk_field="slug") class Meta(BaseTable.Meta): model = Role fields = ( "pk", "name", "slug", "prefix_count", "vlan_count", "description", "weight", "actions", ) default_columns = ( "pk", "name", "prefix_count", "vlan_count", "description", "actions", )
class GoldenConfigTable(BaseTable): """Table to display Config Management Status.""" pk = ToggleColumn() device__name = TemplateColumn( template_code= """<a href="{% url 'dcim:device' pk=record.device.pk %}">{{ record.device }}</a>""", verbose_name="Device", ) if ENABLE_BACKUP: backup_last_success_date = TemplateColumn(verbose_name="Backup Status", template_code=BACKUP_SUCCESS) if ENABLE_INTENDED: intended_last_success_date = TemplateColumn( verbose_name="Intended Status", template_code=INTENDED_SUCCESS) if ENABLE_COMPLIANCE: compliance_last_success_date = TemplateColumn( verbose_name="Compliance Status", template_code=COMPLIANCE_SUCCESS) actions = TemplateColumn(template_code=ALL_ACTIONS, verbose_name="Actions", extra_context=CONFIG_FEATURES, orderable=False) class Meta(BaseTable.Meta): """Meta for class CircuitMaintenanceTable.""" model = models.GoldenConfig fields = actual_fields()
class RIRTable(BaseTable): pk = ToggleColumn() name = tables.LinkColumn() is_private = BooleanColumn(verbose_name="Private") aggregate_count = LinkedCountColumn( viewname="ipam:aggregate_list", url_params={"rir": "slug"}, verbose_name="Aggregates", ) actions = ButtonsColumn(RIR, pk_field="slug") class Meta(BaseTable.Meta): model = RIR fields = ( "pk", "name", "slug", "is_private", "aggregate_count", "description", "actions", ) default_columns = ( "pk", "name", "is_private", "aggregate_count", "description", "actions", )
class VLANTable(StatusTableMixin, BaseTable): pk = ToggleColumn() vid = tables.TemplateColumn(template_code=VLAN_LINK, verbose_name="ID") site = tables.LinkColumn(viewname="dcim:site", args=[Accessor("site__slug")]) group = tables.LinkColumn(viewname="ipam:vlangroup", args=[Accessor("group__pk")]) tenant = tables.TemplateColumn(template_code=COL_TENANT) role = tables.TemplateColumn(template_code=VLAN_ROLE_LINK) class Meta(BaseTable.Meta): model = VLAN fields = ( "pk", "vid", "site", "group", "name", "tenant", "status", "role", "description", ) row_attrs = { "class": lambda record: "success" if not isinstance(record, VLAN) else "", }
class ConfigContextTable(BaseTable): pk = ToggleColumn() name = tables.LinkColumn() owner = tables.LinkColumn() is_active = BooleanColumn(verbose_name="Active") class Meta(BaseTable.Meta): model = ConfigContext fields = ( "pk", "name", "owner", "weight", "is_active", "description", "regions", "sites", "roles", "platforms", "cluster_groups", "clusters", "tenant_groups", "tenants", ) default_columns = ("pk", "name", "weight", "is_active", "description")
class CustomLinkTable(BaseTable): pk = ToggleColumn() name = tables.Column(linkify=True) new_window = BooleanColumn() class Meta(BaseTable.Meta): model = CustomLink fields = ( "pk", "name", "content_type", "text", "target_url", "weight", "group_name", "button_class", "new_window", ) default_columns = ( "pk", "name", "content_type", "group_name", "weight", )
class ConfigComplianceTable(BaseTable): """Table for rendering a listing of Device entries and their associated ConfigCompliance record status.""" pk = ToggleColumn(accessor=A("device")) device = TemplateColumn( template_code="""<a href="{% url 'plugins:nautobot_golden_config:configcompliance_devicedetail' pk=record.device %}" <strong>{{ record.device__name }}</strong></a> """ ) def __init__(self, *args, **kwargs): """Override default values to dynamically add columns.""" # Used ConfigCompliance.objects on purpose, vs queryset (set in args[0]), as there were issues with that as # well as not as expected from user standpoint (e.g. not always the same values on columns depending on # filtering) features = list( models.ConfigCompliance.objects.order_by("rule__feature__name") .values_list("rule__feature__name", flat=True) .distinct() ) extra_columns = [(feature, ComplianceColumn(verbose_name=feature)) for feature in features] kwargs["extra_columns"] = extra_columns # Nautobot's BaseTable.configurable_columns() only recognizes columns in self.base_columns, # so override the class's base_columns to include our additional columns as configurable. self.base_columns = copy.deepcopy(self.base_columns) for feature, column in extra_columns: self.base_columns[feature] = column super().__init__(*args, **kwargs) class Meta(BaseTable.Meta): """Metaclass attributes of ConfigComplianceTable.""" model = models.ConfigCompliance fields = ( "pk", "device", )
class DeviceTypeTable(BaseTable): pk = ToggleColumn() model = tables.Column(linkify=True, verbose_name="Device Type") is_full_depth = BooleanColumn(verbose_name="Full Depth") instance_count = LinkedCountColumn( viewname="dcim:device_list", url_params={"device_type_id": "pk"}, verbose_name="Instances", ) tags = TagColumn(url_name="dcim:devicetype_list") class Meta(BaseTable.Meta): model = DeviceType fields = ( "pk", "model", "manufacturer", "slug", "part_number", "u_height", "is_full_depth", "subdevice_role", "instance_count", "tags", ) default_columns = ( "pk", "model", "manufacturer", "part_number", "u_height", "is_full_depth", "instance_count", )
class VRFTable(BaseTable): pk = ToggleColumn() name = tables.LinkColumn() rd = tables.Column(verbose_name="RD") tenant = tables.TemplateColumn(template_code=COL_TENANT) enforce_unique = BooleanColumn(verbose_name="Unique") import_targets = tables.TemplateColumn(template_code=VRF_TARGETS, orderable=False) export_targets = tables.TemplateColumn(template_code=VRF_TARGETS, orderable=False) tags = TagColumn(url_name="ipam:vrf_list") class Meta(BaseTable.Meta): model = VRF fields = ( "pk", "name", "rd", "tenant", "enforce_unique", "description", "import_targets", "export_targets", "tags", ) default_columns = ("pk", "name", "rd", "tenant", "description")
class SecretTable(BaseTable): """Table for list view of `Secret` objects.""" pk = ToggleColumn() name = tables.LinkColumn() tags = TagColumn(url_name="extras:secret_list") class Meta(BaseTable.Meta): model = Secret fields = ( "pk", "name", "provider", "description", "tags", ) default_columns = ( "pk", "name", "provider", "description", "tags", ) def render_provider(self, value): return registry["secrets_providers"][value].name if value in registry[ "secrets_providers"] else value
class CustomFieldTable(BaseTable): pk = ToggleColumn() # TODO: Replace name column with slug #464 slug = tables.Column(linkify=True, accessor="name") content_types = ContentTypesColumn(truncate_words=15) required = BooleanColumn() class Meta(BaseTable.Meta): model = CustomField fields = ( "pk", "slug", "content_types", "type", "label", "description", "required", "default", "weight", ) default_columns = ( "pk", "slug", "content_types", "type", "label", "required", "weight", ) def render_description(self, record): if record.description: return mark_safe(render_markdown(record.description)) return self.default
class DynamicGroupTable(BaseTable): pk = ToggleColumn() name = tables.Column(linkify=True) members = tables.Column(accessor="count", verbose_name="Group Members", orderable=False) actions = ButtonsColumn(DynamicGroup, pk_field="slug") class Meta(BaseTable.Meta): # pylint: disable=too-few-public-methods """Resource Manager Meta.""" model = DynamicGroup fields = ( "pk", "name", "description", "content_type", "members", "actions", ) def render_members(self, value, record): """Provide a filtered URL to the group members (if any).""" # Only linkify if there are members. if not value: return value return format_html('<a href="{}">{}</a>', record.get_group_members_url(), value)
class WebhookTable(BaseTable): pk = ToggleColumn() name = tables.Column(linkify=True) content_types = tables.TemplateColumn(WEBHOOK_CONTENT_TYPES) enabled = BooleanColumn() type_create = BooleanColumn() type_update = BooleanColumn() type_delete = BooleanColumn() ssl_verification = BooleanColumn() class Meta(BaseTable.Meta): model = Webhook fields = ( "pk", "name", "content_types", "payload_url", "http_content_type", "http_method", "enabled", "type_create", "type_update", "type_delete", "ssl_verification", "ca_file_path", ) default_columns = ( "pk", "name", "content_types", "payload_url", "http_content_type", "enabled", )
class DeviceComponentTable(BaseTable): pk = ToggleColumn() device = tables.Column(linkify=True) name = tables.Column(linkify=True, order_by=("_name", )) cable = tables.Column(linkify=True) class Meta(BaseTable.Meta): order_by = ("device", "name")
class DeviceTable(StatusTableMixin, BaseTable): pk = ToggleColumn() name = tables.TemplateColumn(order_by=("_name",), template_code=DEVICE_LINK) tenant = tables.TemplateColumn(template_code=COL_TENANT) site = tables.Column(linkify=True) rack = tables.Column(linkify=True) device_role = ColoredLabelColumn(verbose_name="Role") device_type = tables.LinkColumn( viewname="dcim:devicetype", args=[Accessor("device_type__pk")], verbose_name="Type", text=lambda record: record.device_type.display_name, ) primary_ip = tables.Column(linkify=True, order_by=("primary_ip6", "primary_ip4"), verbose_name="IP Address") primary_ip4 = tables.Column(linkify=True, verbose_name="IPv4 Address") primary_ip6 = tables.Column(linkify=True, verbose_name="IPv6 Address") cluster = tables.LinkColumn(viewname="virtualization:cluster", args=[Accessor("cluster__pk")]) virtual_chassis = tables.LinkColumn(viewname="dcim:virtualchassis", args=[Accessor("virtual_chassis__pk")]) vc_position = tables.Column(verbose_name="VC Position") vc_priority = tables.Column(verbose_name="VC Priority") tags = TagColumn(url_name="dcim:device_list") class Meta(BaseTable.Meta): model = Device fields = ( "pk", "name", "status", "tenant", "device_role", "device_type", "platform", "serial", "asset_tag", "site", "rack", "position", "face", "primary_ip", "primary_ip4", "primary_ip6", "cluster", "virtual_chassis", "vc_position", "vc_priority", "tags", ) default_columns = ( "pk", "name", "status", "tenant", "site", "rack", "device_role", "device_type", "primary_ip", )
class GitRepositoryTable(BaseTable): pk = ToggleColumn() name = tables.LinkColumn() remote_url = tables.Column(verbose_name="Remote URL") token_rendered = tables.Column(verbose_name="Token") last_sync_time = tables.DateTimeColumn( empty_values=(), format=settings.SHORT_DATETIME_FORMAT, verbose_name="Sync Time" ) last_sync_user = tables.Column(empty_values=(), verbose_name="Sync By") class JobResultColumn(tables.TemplateColumn): def render(self, record, table, value, bound_column, **kwargs): if record.name in table.context.get("job_results", {}): table.context.update({"result": table.context["job_results"][record.name]}) else: table.context.update({"result": None}) return super().render(record, table, value, bound_column, **kwargs) last_sync_status = JobResultColumn(template_name="extras/inc/job_label.html", verbose_name="Sync Status") provides = tables.TemplateColumn(GITREPOSITORY_PROVIDES) actions = ButtonsColumn(GitRepository, pk_field="slug", prepend_template=GITREPOSITORY_BUTTONS) class Meta(BaseTable.Meta): model = GitRepository fields = ( "pk", "name", "slug", "remote_url", "branch", "token_rendered", "provides", "last_sync_time", "last_sync_user", "last_sync_status", "actions", ) default_columns = ( "pk", "name", "remote_url", "branch", "provides", "last_sync_status", "actions", ) def render_last_sync_time(self, record): if record.name in self.context["job_results"]: return self.context["job_results"][record.name].completed return self.default def render_last_sync_user(self, record): if record.name in self.context["job_results"]: user = self.context["job_results"][record.name].user return user return self.default
class TagTable(BaseTable): pk = ToggleColumn() name = tables.LinkColumn(viewname="extras:tag", args=[Accessor("slug")]) color = ColorColumn() actions = ButtonsColumn(Tag, pk_field="slug") class Meta(BaseTable.Meta): model = Tag fields = ("pk", "name", "items", "slug", "color", "description", "actions")
class TenantTable(BaseTable): pk = ToggleColumn() name = tables.LinkColumn() tags = TagColumn(url_name="tenancy:tenant_list") class Meta(BaseTable.Meta): model = Tenant fields = ("pk", "name", "slug", "group", "description", "tags") default_columns = ("pk", "name", "group", "description")
class AggregateTable(BaseTable): pk = ToggleColumn() prefix = tables.LinkColumn(verbose_name="Aggregate") tenant = tables.TemplateColumn(template_code=TENANT_LINK) date_added = tables.DateColumn(format="Y-m-d", verbose_name="Added") class Meta(BaseTable.Meta): model = Aggregate fields = ("pk", "prefix", "rir", "tenant", "date_added", "description")
class CableTable(StatusTableMixin, BaseTable): pk = ToggleColumn() id = tables.Column(linkify=True, verbose_name="ID") termination_a_parent = tables.TemplateColumn( template_code=CABLE_TERMINATION_PARENT, accessor=Accessor("termination_a"), orderable=False, verbose_name="Side A", ) termination_a = tables.LinkColumn( accessor=Accessor("termination_a"), orderable=False, verbose_name="Termination A", ) termination_b_parent = tables.TemplateColumn( template_code=CABLE_TERMINATION_PARENT, accessor=Accessor("termination_b"), orderable=False, verbose_name="Side B", ) termination_b = tables.LinkColumn( accessor=Accessor("termination_b"), orderable=False, verbose_name="Termination B", ) length = tables.TemplateColumn(template_code=CABLE_LENGTH, order_by="_abs_length") color = ColorColumn() tags = TagColumn(url_name="dcim:cable_list") class Meta(BaseTable.Meta): model = Cable fields = ( "pk", "id", "label", "termination_a_parent", "termination_a", "termination_b_parent", "termination_b", "status", "type", "color", "length", "tags", ) default_columns = ( "pk", "id", "label", "termination_a_parent", "termination_a", "termination_b_parent", "termination_b", "status", "type", )
class RouteTargetTable(BaseTable): pk = ToggleColumn() name = tables.LinkColumn() tenant = tables.TemplateColumn(template_code=COL_TENANT) tags = TagColumn(url_name="ipam:vrf_list") class Meta(BaseTable.Meta): model = RouteTarget fields = ("pk", "name", "tenant", "description", "tags") default_columns = ("pk", "name", "tenant", "description")
class ClusterGroupTable(BaseTable): pk = ToggleColumn() name = tables.LinkColumn() cluster_count = tables.Column(verbose_name="Clusters") actions = ButtonsColumn(ClusterGroup, pk_field="slug") class Meta(BaseTable.Meta): model = ClusterGroup fields = ("pk", "name", "slug", "cluster_count", "description", "actions") default_columns = ("pk", "name", "cluster_count", "description", "actions")
class AnotherExampleModelTable(BaseTable): """Table for list view of `AnotherExampleModel` objects.""" pk = ToggleColumn() name = tables.LinkColumn() actions = ButtonsColumn(AnotherExampleModel) class Meta(BaseTable.Meta): model = AnotherExampleModel fields = ["pk", "name", "number"]
class ProviderNetworkTable(BaseTable): pk = ToggleColumn() name = tables.Column(linkify=True) provider = tables.Column(linkify=True) tags = TagColumn(url_name="circuits:providernetwork_list") class Meta(BaseTable.Meta): model = ProviderNetwork fields = ("pk", "name", "provider", "description", "tags") default_columns = ("pk", "name", "provider", "description")
class AggregateTable(BaseTable): pk = ToggleColumn() prefix = tables.LinkColumn(verbose_name="Aggregate", order_by=("network", "prefix_length")) tenant = TenantColumn() date_added = tables.DateColumn(format="Y-m-d", verbose_name="Added") class Meta(BaseTable.Meta): model = Aggregate fields = ("pk", "prefix", "rir", "tenant", "date_added", "description")
class GraphQLQueryTable(BaseTable): pk = ToggleColumn() name = tables.Column(linkify=True) class Meta(BaseTable.Meta): model = GraphQLQuery fields = ( "pk", "name", "slug", )
class GoldenConfigTable(BaseTable): """Table to display Config Management Status.""" pk = ToggleColumn() name = TemplateColumn( template_code="""<a href="{% url 'dcim:device' pk=record.pk %}">{{ record.name }}</a>""", verbose_name="Device", ) if ENABLE_BACKUP: backup_last_success_date = Column(verbose_name="Backup Status", empty_values=()) if ENABLE_INTENDED: intended_last_success_date = Column(verbose_name="Intended Status", empty_values=()) if ENABLE_COMPLIANCE: compliance_last_success_date = Column(verbose_name="Compliance Status", empty_values=()) actions = TemplateColumn( template_code=ALL_ACTIONS, verbose_name="Actions", extra_context=CONFIG_FEATURES, orderable=False ) def _render_last_success_date(self, record, column, value): # pylint: disable=no-self-use """Abstract method to get last success per row record.""" entry = record.goldenconfig_set.first() last_success_date = getattr(entry, f"{value}_last_success_date", None) last_attempt_date = getattr(entry, f"{value}_last_attempt_date", None) if not last_success_date or not last_attempt_date: column.attrs = {"td": {"style": "color:black"}} return "--" if not last_success_date and not last_attempt_date: column.attrs = {"td": {"style": "color:black"}} return "--" if last_success_date and last_attempt_date == last_success_date: column.attrs = {"td": {"style": "color:green"}} return last_success_date column.attrs = {"td": {"style": "color:red"}} return last_success_date def render_backup_last_success_date(self, record, column): # pylint: disable=no-self-use """Pull back backup last success per row record.""" return self._render_last_success_date(record, column, "backup") def render_intended_last_success_date(self, record, column): # pylint: disable=no-self-use """Pull back intended last success per row record.""" return self._render_last_success_date(record, column, "intended") def render_compliance_last_success_date(self, record, column): # pylint: disable=no-self-use """Pull back compliance last success per row record.""" return self._render_last_success_date(record, column, "compliance") class Meta(BaseTable.Meta): """Meta for class GoldenConfigTable.""" model = Device fields = actual_fields()
class RelationshipAssociationTable(BaseTable): pk = ToggleColumn() actions = ButtonsColumn(Relationship, buttons=("delete", )) source = tables.Column(linkify=True) destination = tables.Column(linkify=True) class Meta(BaseTable.Meta): model = RelationshipAssociation fields = ("relationship", "source", "destination", "actions")