mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-04 14:31:13 +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
@@ -72,6 +72,59 @@ def test_docker_iol_ports_grouped_in_four_port_units(compute, project):
|
||||
assert [p.asdict()["name"] for p in node.ports] == ["eth0", "eth1"]
|
||||
|
||||
|
||||
def test_docker_iol_startup_config_materialized_once(compute, project, monkeypatch):
|
||||
"""
|
||||
The GNS3_IOL_STARTUP_CONFIG environment knob references a config file in
|
||||
the controller's configs directory: like the IOU startup_config mapping,
|
||||
its content is sent to the compute exactly once (the knob is consumed) —
|
||||
afterwards the node's configuration lives in its NVRAM on the compute.
|
||||
"""
|
||||
|
||||
node = Node(project, compute, "iol",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="docker",
|
||||
properties={"environment": "GNS3_IOL_RUNNER=1\nGNS3_IOL_STARTUP_CONFIG=my-iol-config.txt"})
|
||||
monkeypatch.setattr(node, "_base_config_file_content", lambda path: "hostname %h\n")
|
||||
|
||||
data = node._node_data()
|
||||
assert data["startup_config_content"] == "hostname %h\n"
|
||||
assert data["environment"] == "GNS3_IOL_RUNNER=1"
|
||||
assert "GNS3_IOL_STARTUP_CONFIG" not in node.properties["environment"]
|
||||
|
||||
# sent only once: a later sync (e.g. project reload) carries neither
|
||||
data = node._node_data()
|
||||
assert "startup_config_content" not in data
|
||||
|
||||
|
||||
def test_docker_iol_startup_config_missing_file_keeps_knob(compute, project, monkeypatch):
|
||||
|
||||
node = Node(project, compute, "iol",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="docker",
|
||||
properties={"environment": "GNS3_IOL_RUNNER=1\nGNS3_IOL_STARTUP_CONFIG=gone.txt"})
|
||||
monkeypatch.setattr(node, "_base_config_file_content", lambda path: None)
|
||||
|
||||
data = node._node_data()
|
||||
assert "startup_config_content" not in data
|
||||
# the knob is kept so the config still applies once the file shows up
|
||||
assert "GNS3_IOL_STARTUP_CONFIG" in node.properties["environment"]
|
||||
|
||||
|
||||
def test_extract_iol_startup_config_knob_variants():
|
||||
|
||||
from gns3server.controller.node import _extract_iol_startup_config_knob
|
||||
|
||||
assert _extract_iol_startup_config_knob(None) == (None, None)
|
||||
assert _extract_iol_startup_config_knob("GNS3_IOL_RUNNER=1") == (None, "GNS3_IOL_RUNNER=1")
|
||||
# whitespace and trailing commas are tolerated, like the compute env parsing
|
||||
filename, environment = _extract_iol_startup_config_knob("GNS3_IOL_RUNNER=1,\n GNS3_IOL_STARTUP_CONFIG=cfg.txt ,")
|
||||
assert filename == "cfg.txt"
|
||||
assert environment == "GNS3_IOL_RUNNER=1,"
|
||||
# an empty value is treated as absent
|
||||
filename, environment = _extract_iol_startup_config_knob("GNS3_IOL_STARTUP_CONFIG=")
|
||||
assert filename is None
|
||||
|
||||
|
||||
def test_name(compute, project):
|
||||
"""
|
||||
If node use a name template generate names
|
||||
|
||||
Reference in new issue
Block a user