Coordinate capabilities across nodes by managing nodes.NodeFeature records in the Django admin.
nodes.NodeFeature) to open the changelist (admin:nodes_nodefeature_changelist).nodes/admin.py and displays columns for the display name, slug, default roles, enablement status, and available actions.Each feature encapsulates a capability that nodes can expose. The admin form provides:
filter_horizontal = ("roles",) in NodeFeatureAdmin).Actions column when a feature is enabled (NodeFeature.get_default_actions).Use the search field to find features by slug or display string. The queryset prefetches role relations, keeping list navigation fast even with many records.
Node roles and individual nodes both control feature availability:
NodeFeature.roles through the horizontal selector.admin:nodes_node_change) to adjust the inline Node feature assignments table. The inline is provided by NodeFeatureAssignmentInline (nodes/admin.py lines 96-100) and writes to the NodeFeatureAssignment through model.Changes to assignments are applied immediately after saving the node or feature form. Use Django’s history view to audit adjustments.
Select one or more features on the changelist and choose Check features for eligibility. The admin action (NodeFeatureAdmin.check_features_for_eligibility) calls the registry in nodes/feature_checks.py to evaluate whether the local node satisfies hardware or software requirements. Results appear as Django messages with success, warning, or error levels.
Eligibility runs also report whether a feature can be enabled manually. The helper _manual_enablement_message in NodeFeatureAdmin communicates whether the feature belongs to Node.MANUAL_FEATURE_SLUGS or requires automation.
To toggle features outside of automatic provisioning, select them in the changelist and execute Enable selected features. When a local node is registered, the action creates NodeFeatureAssignment rows for that node (see NodeFeatureAssignment.objects.update_or_create calls in nodes/models.py lines 1009-1191).
If no local node exists, the admin posts an informational message. Register a node first via the Nodes interface, then re-run the enable action.
DEFAULT_ACTIONS in nodes/models.py.feature_checks registry in nodes/feature_checks.py to cover the slug in question.nodes/fixtures/ or migrations are not removing the feature (nodes/migrations/0018, 0027, etc.). Reapply role assignments if a migration intentionally deprecates the feature.