{% load i18n %} {# Why a device the plugin created refuses a manual delete, and where the #} {# supported delete lives. NetBox's own delete dialog renders the raw #} {# ProtectedError - our table names and nothing else - so the explanation #} {# has to be on the page the operator is already looking at. #}
{% trans "Forward Ownership" %}
{% if ownership.absence %} {% endif %} {% if ownership.delete_blockers %} {% endif %}
{% trans "Owned by sync" %} {% for sync in ownership.syncs %} {{ sync.name }}{% if not forloop.last %}, {% endif %} {% empty %} — {% endfor %}
{% trans "Scope status" %} {% if ownership.uncovered %} {% trans "Uncovered" %} {% endif %} {% if ownership.out_of_scope %} {% trans "Out of scope" %} {% endif %} {% if ownership.backfilled %} {% trans "Backfilled" %} {% endif %} {% if not ownership.uncovered and not ownership.out_of_scope and not ownership.backfilled %} {% trans "In scope" %} {% endif %}
{% trans "Absent from Forward for" %} {% blocktrans count runs=ownership.absence.consecutive_absent_runs trimmed %} {{ runs }} consecutive run {% plural %} {{ runs }} consecutive runs {% endblocktrans %} ({% trans "since" %} {{ ownership.absence.first_absent_at }})
{% trans "Records held" %} {% for label, count in ownership.holders %} {{ label }}: {{ count }}{% if not forloop.last %}
{% endif %} {% empty %} {% trans "None" %} {% endfor %}
{% trans "Would refuse a delete" %} {# The database's own verdict, so it includes rows from other #} {# plugins reached through the cascade - BGP peers attached to this #} {# device's IP addresses, for instance - not only our records. #} {% for label, count in ownership.delete_blockers %} {{ label }} × {{ count }}{% if not forloop.last %}
{% endif %} {% endfor %}
{# The remedy for this one device, when the whole-set prune would take it #} {# anyway. The button narrows that prune rather than deleting directly, so #} {# every gate still applies and the job records a reason if it declines. #} {% if ownership.prune.offered and perms.dcim.delete_device %}
{% csrf_token %} {% if ownership.prune.held %}
{% endif %} {% if ownership.prune.held %}

{% blocktrans with runs=ownership.prune.required_runs hours=ownership.prune.required_hours %}Forward no longer reports this device, but a device disabled in Forward looks exactly the same, so the absence must persist for {{ runs }} consecutive syncs and {{ hours }} hours before the prune will delete it.{% endblocktrans %}

{% endif %}
{% elif ownership.prune.still_reported and ownership.prune.endpoint_detail %}

{% blocktrans trimmed with reason=ownership.prune.endpoint_detail_label %} Forward still reports this device as an SNMP endpoint, but the endpoint scope excludes it: {{ reason }}. That is a scoping decision, not a removal, so the uncovered cleanup will never delete it. {% endblocktrans %} {% if ownership.prune.endpoint_detail == "endpoint_untagged" %} {% trans "Add one of the endpoint's Forward tags to the sync's include tags, or tag the endpoint in Forward, to cover it again." %} {% elif ownership.prune.endpoint_detail == "endpoint_generic" %} {% trans "Enable generic endpoint import on the source to cover it again, or delete it by hand if it should not have been imported." %} {% elif ownership.prune.endpoint_detail == "endpoint_scope_off" %} {% trans "Enable endpoint import on the source to cover it again." %} {% elif ownership.prune.endpoint_detail == "endpoint_cimc" %} {% trans "CIMC controllers are imported as inventory items of their server; this standalone device predates that and can be deleted by hand." %} {% elif ownership.prune.endpoint_detail == "endpoint_no_snmp" %} {% trans "Restore SNMP collection for the endpoint in Forward to cover it again." %} {% endif %}

{% elif ownership.prune.still_reported %}

{% blocktrans trimmed %} Forward still reports this device; it carries none of this sync's include tags. That is a scoping decision, not a removal, so the uncovered cleanup will never delete it. Change the tags in Forward or the sync's include tags to bring it back into scope. {% endblocktrans %}

{% endif %} {% if ownership.holders %}

{% blocktrans trimmed %} Deleting this device from NetBox, here or from the device list, also removes these Forward records; the next sync will not look for it. The scope reconciliation panel on the owning sync is the gated way: it deletes only devices Forward no longer reports, applies the absence quarantine and the shrink refusal, and records what it removed. {% endblocktrans %}

{% endif %} {% if ownership.foreign_delete_blockers %} {# Be exact about the limit: the prune releases OUR rows and then asks #} {# the database to delete the device. A row another plugin holds it with #} {# is reported, not removed, so the prune refuses this device too until #} {# that row is gone. Promising otherwise would send an operator to a #} {# button that cannot help them, so this says what to do instead. #} {% endif %}
{% if ownership.primary_sync_url %} {% endif %}