Config Manager Render Service
Overview
The NVIDIA Config Manager Network Template Render Service is an event-driven microservice that automatically generates and versions network device configurations. The configured DCIM provider supplies device data and change events; the built-in nautobot-2x provider remains the default. Rendered configurations are stored in the Config Store.
Architecture
The service consists of three main components: the API, the event consumers, and the event dispatcher.
API endpoints
You can use the render service’s API endpoints to trigger the rendering of network device configurations.
POST /v1/render/{device_uuid}/render- Render the configuration for a single devicePOST /v1/render/all- Queue renders for all devices that are enabled for renderingPOST /v1/render/batch- Queue renders for a list of devices
Event Consumers
Two specialized pull-based consumers process NATS JetStream events:
DCIM event consumer responds to provider-neutral change events (device, interface, cable, IP address, and so on). The consumer validates the event envelope, dispatches it to model-specific handlers, and queues device renders. The built-in Nautobot provider translates its legacy changelog payload at the provider boundary during the compatibility window.
Device change consumer responds to queued device render requests from event handlers. The consumer executes renders with distributed locking, and updates the config store.
External NATS administration
The bundled NATS deployment creates the streams automatically. The application creates missing durable consumers at runtime in both bundled and externally managed deployments. When NATS is owned outside the Config Manager deployment, coordinate the streams, account imports, and user permissions with the NATS administrator. An administrator can own consumer provisioning instead by omitting create permission and provisioning the fixed durables described below.
The application uses three fixed durable names in every deployment:
Each stream also has an apiPrefix value. Its default, $JS.API, addresses JetStream in the connected account directly. Override it when the stream belongs to another NATS account and its JetStream API service export is imported under a different local subject prefix. For example:
The prefix is configured per stream because the Config Manager stream can remain local while the Nautobot event stream is imported from another account. It is a local routing prefix, not a stream or consumer name. The NATS user permissions and account service imports must refer to the selected prefix.
For each render pull-consumer <prefix>, <stream>, and <consumer> tuple, the application account needs these consumer subjects:
The account also needs the ordinary data-plane permissions for its configured subjects: subscribe access to request/delivery inboxes, permission to publish acknowledgements to the reply subjects supplied by JetStream, and publish access to any event subjects produced by the application. In an account-import design, the owning administrator must export the corresponding JetStream service subjects and the application account must import them at apiPrefix.
When temporal.archive.enabled=true, the archive service consumes archiveSubject through the fixed archiveConsumer.name and archiveConsumer.deliverySubject. It requires consumer INFO and durable CREATE for that exact stream and durable, subscribe access to the configured delivery subject, and publish access to JetStream acknowledgement subjects. The archive service creates the push durable when it is missing. An administrator can provision the same durable with deliver_policy=new, ack_policy=explicit, ack_wait=360s, max_deliver=-1, the configured filter and delivery subjects, and a delivery group matching the durable name.
Clients specify their stream explicitly and do not request STREAM.INFO for externally managed streams. Stream creation, mutation, and inspection therefore remain administrator operations. When externalServices.nats.local=true, the application retains its existing stream setup behavior for local development.
An administrator-provisioned consumer should use the configured stream and filter subject with the fixed durable name, deliver_policy=new, ack_policy=explicit, ack_wait=360s, and max_deliver=-1. The application validates operational settings but does not change an existing consumer or require its delivery policy to match; the owner can retain the delivery policy chosen for a migration boundary.
If create permission is omitted and the durable is absent, the consumer logs the exact provisioning request. If delete permission is omitted, the reset API returns instructions to delete and recreate the exact durable at the stream head. Configuration mismatches likewise produce an administrator-ready update request in the consumer log.
Event Dispatcher
The event dispatcher is a dynamic event routing system that maps normalized DCIM object types to handler functions. It maintains a dispatch table for supported render impacts and exposes Prometheus metrics for event processing.
Rendering Process
The rendering process is as follows:
- Fetch normalized
RenderDatafrom the selected DCIM provider. - Render the configuration using the
nv_config_manager_templates.Renderer. - Persist the rendered files using the Config Store client.
- Record intended-configuration metadata through the DCIM provider.
Template Version Management
Producer: Runs as a Kubernetes job on service deployment. The producer queries the selected DCIM provider for devices with stale template_version, and publishes template-change events for outdated devices.
Version tracking: The producer records the nv_config_manager_templates version through the DCIM provider, and the template consumer refuses to process events for newer versions (NAKs with 30s delay). This allows for zero-downtime rolling deployments (old pods terminate, new pods process backlog).
Deployment
The service is deployed as a Kubernetes deployment, with three consumer deployments (DCIM, device, template), a producer job (runs on helm upgrade), and Redis for distributed locking. The service exposes Prometheus metrics on port 8000.
The service is configured using a configuration file (config.py). The configuration file contains the selected DCIM provider settings, NATS connection details (TLS, credentials), Redis connection for locking, Config Store client settings, and environment-specific aggregate management flags. External providers configure dcim_change_stream and dcim_change_subject; empty Helm values retain the historical Nautobot stream and subject.
Monitoring
Prometheus metrics:
Event processing:
nv_config_manager_events_received- Events received through NATS (by model, instance, namespace).nv_config_manager_events_processed- Events successfully processed.nv_config_manager_events_skipped- Events skipped (no handler, device not enabled).nv_config_manager_events_failed- Events that failed processing (by exception type).nv_config_manager_event_processing_time- Event processing duration histogram.
Legacy Nautobot change compatibility:
nv_config_manager_nautobot_change_messages_receivednv_config_manager_nautobot_change_messages_processednv_config_manager_nautobot_change_messages_failednv_config_manager_nautobot_change_message_processing_time- Render durationnv_config_manager_nautobot_change_message_end_to_end_time- Nautobot publish to Config Store persist
Template changes:
nv_config_manager_template_change_messages_received(by template_version)nv_config_manager_template_change_messages_processednv_config_manager_template_change_messages_failednv_config_manager_template_change_message_processing_time
Error handling
Exception types:
DCIMError- DCIM provider API errors, retry on transient failuresRenderException- Template rendering failures, ACK (do not retry)DeviceNotEnabledError- Device not enabled for rendering, ACKEventParseError- Malformed event data, fail counter incrementedConfigStoreException- Config store persistence errors
Consumer behavior:
- ACK: Successful processing, render exceptions (will not succeed on retry), disabled devices
- NAK: Transient failures, lock acquisition failures (5s delay), version mismatches (30s delay)
- Consumer recreation: Any fetch/heartbeat failure triggers automatic consumer rebuild
Key design patterns
Provider-owned handler registration: The event dispatcher exposes a registration surface; the selected provider registers its own object-type handlers and owns affected-device resolution.
Pull-based consumption: Consumers fetch messages on-demand rather than push-based subscriptions, enabling better flow control and horizontal scaling.
Distributed locking: Redis-backed locks prevent concurrent renders for the same device across multiple consumer instances.
Version-aware processing: Template consumer compares running version to message version, refusing to process newer versions to enable safe rolling deployments.
Provider-backed data access: Render obtains normalized device data and managed-device state from the configured DCIM provider. Template rendering runs in a thread pool using asyncio.to_thread() to avoid blocking the event loop.
Connection sharing: NATSConnectionManager shares the NATS connection across components within a process.