/restore/', self.admin_site.admin_view(self.restore), name='extras_configrevision_restore'),
+ ]
+
+ return urls + super().get_urls()
+
+ # Views
+
+ def restore(self, request, pk):
+ # Get the ConfigRevision being restored
+ candidate_config = get_object_or_404(ConfigRevision, pk=pk)
+
+ if request.method == 'POST':
+ candidate_config.activate()
+ self.message_user(request, f"Restored configuration revision #{pk}")
+
+ return redirect(reverse('admin:extras_configrevision_changelist'))
+
+ # Get the current ConfigRevision
+ config_version = get_config().version
+ current_config = ConfigRevision.objects.filter(pk=config_version).first()
+
+ params = []
+ for param in PARAMS:
+ params.append((
+ param.name,
+ current_config.data.get(param.name, None),
+ candidate_config.data.get(param.name, None)
+ ))
+
+ context = self.admin_site.each_context(request)
+ context.update({
+ 'object': candidate_config,
+ 'params': params,
+ })
+
+ return TemplateResponse(request, 'admin/extras/configrevision/restore.html', context)
+
#
# Reports & scripts
diff --git a/netbox/extras/models/models.py b/netbox/extras/models/models.py
index d4d6d648e..57615c0c5 100644
--- a/netbox/extras/models/models.py
+++ b/netbox/extras/models/models.py
@@ -560,7 +560,7 @@ class ConfigRevision(models.Model):
return self.data[item]
return super().__getattribute__(item)
- def cache(self):
+ def activate(self):
"""
Cache the configuration data.
"""
diff --git a/netbox/extras/signals.py b/netbox/extras/signals.py
index ce1dead8f..9b37dd763 100644
--- a/netbox/extras/signals.py
+++ b/netbox/extras/signals.py
@@ -172,4 +172,4 @@ def update_config(sender, instance, **kwargs):
"""
Update the cached NetBox configuration when a new ConfigRevision is created.
"""
- instance.cache()
+ instance.activate()
diff --git a/netbox/netbox/config/__init__.py b/netbox/netbox/config/__init__.py
index 7c353fdb9..9e015a891 100644
--- a/netbox/netbox/config/__init__.py
+++ b/netbox/netbox/config/__init__.py
@@ -48,7 +48,6 @@ class Config:
if not self.config or not self.version:
self._populate_from_db()
self.defaults = {param.name: param.default for param in PARAMS}
- logger.debug("Loaded configuration data from cache")
def __getattr__(self, item):
@@ -70,6 +69,8 @@ class Config:
"""Populate config data from Redis cache"""
self.config = cache.get('config') or {}
self.version = cache.get('config_version')
+ if self.config:
+ logger.debug("Loaded configuration data from cache")
def _populate_from_db(self):
"""Cache data from latest ConfigRevision, then populate from cache"""
@@ -77,6 +78,7 @@ class Config:
try:
revision = ConfigRevision.objects.last()
+ logger.debug("Loaded configuration data from database")
except DatabaseError:
# The database may not be available yet (e.g. when running a management command)
logger.warning(f"Skipping config initialization (database unavailable)")
@@ -86,7 +88,7 @@ class Config:
logger.debug("No previous configuration found in database; proceeding with default values")
return
- revision.cache()
+ revision.activate()
logger.debug("Filled cache with data from latest ConfigRevision")
self._populate_from_cache()
diff --git a/netbox/templates/admin/extras/configrevision/restore.html b/netbox/templates/admin/extras/configrevision/restore.html
new file mode 100644
index 000000000..15531de2d
--- /dev/null
+++ b/netbox/templates/admin/extras/configrevision/restore.html
@@ -0,0 +1,34 @@
+{% extends "admin/base_site.html" %}
+
+{% block content %}
+ Restore configuration #{{ object.pk }} from {{ object.created }}?
+
+
+
+
+ Parameter |
+ Current Value |
+ New Value |
+
+
+
+ {% for param, current, new in params %}
+
+ {{ param }} |
+ {{ current }} |
+ {{ new }} |
+
+ {% endfor %}
+
+
+
+
+{% endblock content %}
+
+