mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-03 05:51:15 +02:00
feat: IOU-style startup-config for IOL Docker nodes
Templates reference a config file with the GNS3_IOL_STARTUP_CONFIG environment knob; the controller materializes the file content into startup_config_content on node creation (sent once, knob consumed — the same pattern as the IOU startup_config mapping). The compute builds the content into the node's nvram_<app id> at the next start using the IOU nvram_import utility (IOL and IOU share the nvram container format, verified against iol-xe 17.18.02): valid config at boot, no setup dialog, %h hostname substitution, hostname rewrite on rename. Semantics verified against the runner: IOL boots from NVRAM whenever it holds a config, so a plain stop/start never re-applies the startup config and 'write memory' survives restarts; an explicit content edit (PUT) is re-applied on the next start and wins over the saved config, like IOU.
This commit is contained in:
8 files changed
+440
-9
No files matched your search
@@ -40,6 +40,30 @@ import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _extract_iol_startup_config_knob(environment):
|
||||
"""
|
||||
Split the GNS3_IOL_STARTUP_CONFIG knob out of a Docker environment
|
||||
(iol-runner images): the value is a config file name, resolved by the
|
||||
controller in its configs directory.
|
||||
|
||||
:returns: (filename, environment without the knob line); filename is None
|
||||
when the knob is absent or empty.
|
||||
"""
|
||||
|
||||
if not environment or "GNS3_IOL_STARTUP_CONFIG=" not in environment:
|
||||
return None, environment
|
||||
filename = None
|
||||
kept = []
|
||||
for line in environment.splitlines():
|
||||
stripped = line.strip().rstrip(",")
|
||||
if stripped.startswith("GNS3_IOL_STARTUP_CONFIG="):
|
||||
if filename is None:
|
||||
filename = stripped.split("=", 1)[1].strip()
|
||||
else:
|
||||
kept.append(line)
|
||||
return filename or None, "\n".join(kept)
|
||||
|
||||
|
||||
class Node:
|
||||
# These properties are used only on controller and are not forwarded to the compute
|
||||
CONTROLLER_ONLY_PROPERTIES = [
|
||||
@@ -573,6 +597,25 @@ class Node:
|
||||
data[v] = self._base_config_file_content(self._properties[k])
|
||||
del data[k]
|
||||
del self._properties[k] # We send the file only one time
|
||||
|
||||
# IOL runner (Docker) startup-config: translate the config file
|
||||
# referenced by the GNS3_IOL_STARTUP_CONFIG environment knob into
|
||||
# content, like the mappings above. Sent only once — afterwards
|
||||
# the node's configuration lives in its NVRAM on the compute (a
|
||||
# reloaded node is recreated without the knob and boots from the
|
||||
# persistent NVRAM, preserving `write memory`).
|
||||
if self._node_type == "docker":
|
||||
filename, environment = _extract_iol_startup_config_knob(self._properties.get("environment"))
|
||||
if filename:
|
||||
content = self._base_config_file_content(filename)
|
||||
if content:
|
||||
data["startup_config_content"] = content
|
||||
data["environment"] = environment
|
||||
self._properties["environment"] = environment
|
||||
else:
|
||||
log.warning(
|
||||
f"Cannot load IOL startup-config file '{filename}' for node '{self._name}': file not found"
|
||||
)
|
||||
data["name"] = self._name
|
||||
|
||||
# For remote computes, convert absolute image paths to relative paths
|
||||
|
||||
Reference in new issue
Block a user