8046 Commits

Author SHA1 Message Date
Jeremy Grossmann
344a342924
Merge pull request #3004 from Xeriioo/fix/docker-vnc-display-race
fix(docker): give each VNC node its own X display
2026-10-16 12:57:38 +02:00
Jeremy Grossmann
8801e5fd4b
Merge pull request #3005 from yueguobin/fix/node-update-while-running
fix: refuse Docker node updates that would recreate a running container
2026-10-16 12:17:57 +02:00
Guobin Yue
03c1564482
Merge branch '3.1' into fix/node-update-while-running 2026-10-16 17:07:39 +08:00
Jeremy Grossmann
ddaf4b9376
Merge pull request #2999 from GNS3/dependabot/pip/3.1/nornir-utils-gte-0.3.0
Update nornir-utils requirement from >=0.2.0 to >=0.3.0
2026-10-16 11:03:08 +02:00
Guobin Yue
d2b851f148
Merge branch '3.1' into fix/node-update-while-running 2026-10-16 16:56:40 +08:00
Jeremy Grossmann
7b8bb7140f
Merge branch '3.1' into dependabot/pip/3.1/nornir-utils-gte-0.3.0 2026-10-16 10:54:32 +02:00
Jeremy Grossmann
d20bcab40b
Merge pull request #2997 from GNS3/dependabot/pip/3.1/pyjwt-gte-2.15.1
Update pyjwt requirement from >=2.10.1 to >=2.15.1
2026-10-16 10:53:12 +02:00
Jeremy Grossmann
642dd976a8
Merge pull request #2996 from GNS3/dependabot/pip/3.1/langsmith-gte-0.14.7
Update langsmith requirement from >=0.7.7 to >=0.14.7
2026-10-16 10:52:55 +02:00
Jeremy Grossmann
ae3739e2b2
Merge pull request #2995 from GNS3/dependabot/pip/3.1/tiktoken-gte-0.14.0
Update tiktoken requirement from >=0.8.0 to >=0.14.0
2026-10-16 10:52:34 +02:00
Jeremy Grossmann
57f2a687de
Merge pull request #2977 from GNS3/python-3.15-support
Python 3.15 support
2026-10-16 10:51:54 +02:00
Jeremy Grossmann
578dbdceeb
Merge pull request #3003 from yueguobin/fix/mcp-device-config-remote-compute
Fix MCP device tools for nodes on remote computes
2026-10-16 10:49:56 +02:00
YueGuobin
1090a32bbb
fix: refuse Docker node updates that recreate a running container
Updating any Docker node property destroys and recreates the container
(the route calls DockerVM.update() as soon as the property diff is
non-empty), so it discards everything written inside it. On a running
node that happened silently, as a side effect of an unrelated edit: the
user only saw the node restart.

Refuse the update while the container is up and say what stopping it is
for, like QEMU, IOU, Dynamips, VPCS, VirtualBox and VMware already do
for their own restart-requiring settings. The check runs before anything
is applied — a refused update leaves the node untouched — and only when
the PUT really changes a property, since Web clients send the whole node
back on every edit.

is_running() is not reusable for the question: it reports a paused
container as not running and stops crashed containers as a side effect,
so DockerVM gains is_up() for "running or paused".
2026-10-16 16:49:11 +08:00
YueGuobin
290c542afe
fix: roll back a node update the compute refused
A compute 409 (for instance "must be stopped to change the console type
to vnc") left every value that had already been applied locally on the
controller node, because the update loop sets them before the PUT.
Nothing was dumped at that point, but project.dump() serializes the
whole topology: the next successful change anywhere in the project wrote
the refused values to disk, and the next project open recreated the node
with them — this time accepted by a stopped node. A refused change
silently landed later.

Restore the applied properties, the node properties, custom adapters,
missing images and the derived ports before re-raising, the way the
degraded-image create() path already cleans up after its own failure.
2026-10-16 16:49:06 +08:00
Jeremy Grossmann
2821fbd42a
Merge branch '3.1' into python-3.15-support 2026-10-16 10:39:56 +02:00
Clem
c736d5863b fix(docker): give each VNC node its own X display
When a project is opened, Docker nodes are created in parallel. The free
display was found by checking whether /tmp/.X11-unix/X<n> exists, but that
socket only appears once Xvnc has started, so several nodes got the same
display. Only the first Xvnc started; the others exited with "Server is
already active for display N" ("The vnc process has stopped with return
code 1"), and their containers drew on the screen of another node.

- reserve the displays given to the nodes of this server, and also skip a
  display whose lock file belongs to a live process
- restart a crashed Xvnc on the display the container was created with,
  after removing its stale socket, instead of picking a new display the
  container cannot reach (black screen)
- on close, only remove the X socket of our own Xvnc, never the socket of
  the node that owns the display

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 09:29:19 +02:00
Jeremy Grossmann
638a8be180
Merge pull request #3000 from yueguobin/feat/compute-auto-connect
Auto-connect flag and disconnect endpoint for computes
2026-10-16 07:08:07 +02:00
YueGuobin
f47cb56495
fix: dial per-node console hosts in MCP device config tools
The device tools (device_config_send / device_show_run / vpcs_config_set)
built their Nornir inventory with only the console port and inherited the
group hostname, which is always the controller host. Console ports of
nodes on remote computes are bound on the compute's own host, so those
nodes were unreachable from the MCP tools - only local-compute nodes
worked.

Pass the per-node console_host through the project inventory and inject
it as a host-level Nornir hostname (which overrides the group's
controller-wide default). Missing or wildcard (0.0.0.0/::) values keep
the group inheritance, so single-machine setups behave exactly as
before. VPCS builds its own host entries, so it carries the hostname
over explicitly.
2026-10-16 10:29:19 +08:00
Guobin Yue
0130048baa
Merge branch '3.1' into feat/compute-auto-connect 2026-10-15 23:04:52 +08:00
YueGuobin
7737630cb4
fix(tests): derive head revision in the migration round-trip test
The round-trip test builds its catalog from the models (which already
carry the head schema), then stamps the revision that was newest when the
test was written and replays everything above it. Any migration landing
on top therefore ran its DDL against a schema it had not rolled back -
the new computes.auto_connect migration failed with "duplicate column
name: auto_connect".

Stamp the current head instead and let the downgrade roll back every
revision above the inventory one before the upgrade replays them.
2026-10-15 23:02:53 +08:00
Jeremy Grossmann
b79dcaa49d
Merge pull request #3001 from yueguobin/chore/pre-commit-hooks
chore: add pre-commit hook running ruff and mypy checks on staged files
2026-10-15 16:52:47 +02:00
YueGuobin
6734d2d666
feat: add auto_connect flag and disconnect endpoint for computes
Computes can now be flagged auto_connect in the database. The controller
connects to flagged computes in the background at startup (reusing the
one-second delayed fire-and-forget mechanism), and enabling the flag via
PUT /computes/{id} triggers a background connection without the request
ever waiting for it. Disabling the flag does not drop an existing
connection.

Add POST /computes/{id}/disconnect to tear a compute down manually: the
notification stream and HTTP session are closed and every reconnection
path (retry backoff, notification stream reconnect, lazy connection in
http_query) is blocked until connect() is called again or the controller
restarts with auto_connect enabled. Disconnecting a compute used by an
opened project is rejected with 409 unless force=true; forcing only
drops the controller-side control channel, nodes keep running unmanaged.
The local compute cannot be disconnected.

Also make test_compute_list create its own compute (it relied on rows
from earlier tests and failed under reordering), and stop scheduling the
delayed add_compute connection during tests: the timer leaked real
connection attempts into other tests' event loops.
2026-10-15 22:50:22 +08:00
YueGuobin
fa3dd827f9
chore: add pre-commit hook running ruff and mypy checks on staged files
Mirrors the fast static checks from CI (justfile lint + type-check):
ruff check, ruff format --check and mypy (gns3server package only,
matching the files = ["gns3server"] scope in pyproject.toml). Only
staged Python files are checked; pytest and pip check are left to CI.

Enable with: just install-hooks
2026-10-15 22:44:24 +08:00
dependabot[bot]
35a2d54740
Update nornir-utils requirement from >=0.2.0 to >=0.3.0
Updates the requirements on [nornir-utils](https://github.com/nornir-automation/nornir-utils) to permit the latest version.
- [Release notes](https://github.com/nornir-automation/nornir-utils/releases)
- [Changelog](https://github.com/nornir-automation/nornir-utils/blob/main/CHANGELOG.md)
- [Commits](https://github.com/nornir-automation/nornir-utils/compare/v0.2.0...v0.3.0)

---
updated-dependencies:
- dependency-name: nornir-utils
  dependency-version: 0.3.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-15 11:22:59 +00:00
dependabot[bot]
c9a367a32f
Update pyjwt requirement from >=2.10.1 to >=2.15.1
Updates the requirements on [pyjwt](https://github.com/jpadilla/pyjwt) to permit the latest version.
- [Release notes](https://github.com/jpadilla/pyjwt/releases)
- [Changelog](https://github.com/jpadilla/pyjwt/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/jpadilla/pyjwt/compare/2.10.1...2.15.1)

---
updated-dependencies:
- dependency-name: pyjwt
  dependency-version: 2.15.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-15 11:22:50 +00:00
dependabot[bot]
cf75aeeac0
Update langsmith requirement from >=0.7.7 to >=0.14.7
Updates the requirements on [langsmith](https://github.com/langchain-ai/langsmith-sdk) to permit the latest version.
- [Release notes](https://github.com/langchain-ai/langsmith-sdk/releases)
- [Commits](https://github.com/langchain-ai/langsmith-sdk/compare/v0.7.7...v0.14.7)

---
updated-dependencies:
- dependency-name: langsmith
  dependency-version: 0.14.7
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-15 11:22:45 +00:00
dependabot[bot]
a27c135840
Update tiktoken requirement from >=0.8.0 to >=0.14.0
Updates the requirements on [tiktoken](https://github.com/openai/tiktoken) to permit the latest version.
- [Release notes](https://github.com/openai/tiktoken/releases)
- [Changelog](https://github.com/openai/tiktoken/blob/main/CHANGELOG.md)
- [Commits](https://github.com/openai/tiktoken/compare/0.8.0...0.14.0)

---
updated-dependencies:
- dependency-name: tiktoken
  dependency-version: 0.14.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-15 11:22:35 +00:00
Jeremy Grossmann
716edc3a6a
Merge pull request #2993 from yueguobin/feat/multi-kernel-capture
Concurrent kernel captures, one per interface
2026-10-15 06:02:58 +02:00
Jeremy Grossmann
59759f8963
Merge pull request #2994 from yueguobin/docs/packet-filters-guide
docs: packet filters — parameter reference, per-filter guide and REST examples
2026-10-15 05:59:47 +02:00
YueGuobin
eda2d640ab
docs: packet filters — deepen the per-filter guide with mechanism notes
Follow-up enrichments to the Per-filter guide, one per filter, each
answering the question a reader asks right after "what does it do":

- window_drop: explicit recurrence formula ([Start + k*Period, +Outage),
  duty cycle) and ASCII timelines of the three forms (one-shot /
  recurring / jittered); Chance spelled out as an independent per-packet
  draw gated to the window; jitter explained as per-cycle re-draws that
  break phase-locking with protocol timers
- quota: transparent until the budget is consumed; Chance equals
  packet_loss in draw mathematics but runs in the eBPF classifier stage
  (no correlation parameter, outside seed, invisible to captures)
- limit: the phantom-loss symptom (throughput below the configured rate
  with rate+delay set = the 1000 default overflowing)
- seed: reproduction also requires the same traffic pattern (draws are
  consumed per arriving packet); one pinned realization is not the
  distribution — statistical conclusions need several seeds
- gemodel: scattered-vs-bursty timeline at the same 5% mean (fast
  retransmit vs RTO), and a parameter recipe (M and L -> r, p)
- reorder: the mechanism is queue-jumping on the netem delay queue —
  hence the delay requirement, the limit overflow interaction and the
  delay-bounded reorder depth
- rate: per-direction independent shaping (symmetric full duplex, no
  shared budget); asymmetric rates need in-guest netem
- duplicate: real-world prototype (802.11 ARQ retransmissions), example
  values with the correlation-collapse anchors (10/25 -> ~1.8%, 25/25
  -> ~16.7%)
2026-10-15 01:08:53 +08:00
YueGuobin
63873f6041
docs: packet filters — parameter reference, per-filter guide and REST examples
Make the feature doc usable as a standalone reference:

- Parameter reference: all 13 filters' parameters, ranges and units, the
  cross-filter rules (reorder+delay, gemodel/packet_loss exclusivity,
  period>=outage, distribution needs jitter), the zero-means-disabled
  convention, and the UI display names served by available_filters
  (the Web UI labels gemodel as "Gilbert-Elliot loss", never by type)
- Per-filter guide: purpose, per-parameter meaning, caveats and a copyable
  example for each of the 13 types, including the four jitter
  distributions compared (uniform/normal/pareto/paretonormal)
- REST surface: endpoint table with privileges, a filters PUT example,
  and common recipes (WAN latency, bursty loss via gemodel, rate cap,
  ICMP blackhole, scheduled outage)
- Clarify gemodel's "one-way" mean: per direction, independent instances
  per endpoint, round trip compounds to 1-(1-mean)^2; one-directional
  loss is not expressible through the link filters dict
- Fix an inaccuracy: available_filters is a dedicated endpoint's response,
  not a field of the link payload
2026-10-15 00:50:46 +08:00
YueGuobin
3e6a53c4b9
style: apply ruff format to the files this branch touches 2026-10-14 22:13:58 +08:00
YueGuobin
97b5514134
style: zip() with strict= in the capture e2e assert message 2026-10-14 22:09:53 +08:00
YueGuobin
9e0d5050db
feat: concurrent kernel captures, one per interface
uBridge's capture module now serves one AF_PACKET capture per interface,
any number per process, and `capture stop_kernel` takes the interface it
stops — this rides that (breaking, paired-binary) protocol change.

The server-side single-slot tracker (_kernel_capture_ifc with its
reserve/release/owned_by helpers) is gone: same-port duplicates were
already refused by the NIO capturing flag, uBridge answers EALREADY on a
same-interface duplicate, and per-interface stops removed the process-
wide stop the ownership gating guarded against.

The docker e2e drives ten concurrent captures on one node's uBridge and
asserts a per-interface stop freezes exactly the stopped half while the
live half keeps recording.
2026-10-14 21:52:34 +08:00
Jeremy Grossmann
149549e029
Merge pull request #2990 from yueguobin/fix/cloud-hide-kernel-datapath-interfaces
Hide kernel-datapath interfaces from the cloud node
2026-10-14 05:55:34 +02:00
YueGuobin
c0568dc25f
fix: hide kernel-datapath interfaces from the cloud node
The cloud node offered the kernel datapath's host-side interfaces —
node anchors (gv/gq/gi/gd/gx/gp), switch cascade veth ends (gs) and
cross-compute VXLAN devices (gvl) — in its interface list and even
pre-filled them as ports on a freshly created cloud: none of them is
flagged special and only "gns3*" names were filtered. These interfaces
belong to the link or node that created them for the project's whole
lifetime, so bridging a cloud to one would race its owner.

Add is_kernel_datapath_interface() next to the naming contract in
utils/kernel_anchor.py: exact-shape matching (prefix plus its
fixed-length id-derived tail), so a user interface that merely starts
with "gv" is never swallowed. The cloud keeps managed names out of its
host-interface list and default ports mapping, while saved mappings
keep working (the existence checks still see the full interface list).
2026-10-14 10:11:49 +08:00
Jeremy Grossmann
b08441b9ad
Merge pull request #2983 from yueguobin/fix/docker-image-digest-translation
fix(docker): accept the pinned image id when the two daemons report different ids for the same content
2026-10-13 16:23:39 +02:00
Jeremy Grossmann
c188a7f21a
Merge pull request #2989 from GNS3/dependabot/pip/3.1/pyyaml-gte-6.0.3
Update pyyaml requirement from >=6.0.0 to >=6.0.3
2026-10-13 16:20:58 +02:00
Jeremy Grossmann
3a0b00e8ab
Merge pull request #2988 from GNS3/dependabot/pip/3.1/langchain-aws-gte-1.8.1
Update langchain-aws requirement from >=1.3.1 to >=1.8.1
2026-10-13 16:17:33 +02:00
Jeremy Grossmann
126b6dd14e
Merge pull request #2986 from GNS3/dependabot/pip/3.1/nornir-salt-gte-0.23.4
Update nornir-salt requirement from >=0.23.0 to >=0.23.4
2026-10-13 15:58:14 +02:00
Jeremy Grossmann
56aa77b809
Merge pull request #2985 from GNS3/dependabot/pip/3.1/setuptools-gte-84.0.0
Update setuptools requirement from >=61.0 to >=84.0.0
2026-10-13 15:56:35 +02:00
dependabot[bot]
af430439ce
Update pyyaml requirement from >=6.0.0 to >=6.0.3
Updates the requirements on [pyyaml](https://github.com/yaml/pyyaml) to permit the latest version.
- [Release notes](https://github.com/yaml/pyyaml/releases)
- [Changelog](https://github.com/yaml/pyyaml/blob/6.0.3/CHANGES)
- [Commits](https://github.com/yaml/pyyaml/compare/6.0...6.0.3)

---
updated-dependencies:
- dependency-name: pyyaml
  dependency-version: 6.0.3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-13 13:32:08 +00:00
dependabot[bot]
1ec79601ac
Update langchain-aws requirement from >=1.3.1 to >=1.8.1
Updates the requirements on [langchain-aws](https://github.com/langchain-ai/langchain-aws) to permit the latest version.
- [Release notes](https://github.com/langchain-ai/langchain-aws/releases)
- [Commits](https://github.com/langchain-ai/langchain-aws/compare/langchain-aws==1.3.1...langchain-aws==1.8.1)

---
updated-dependencies:
- dependency-name: langchain-aws
  dependency-version: 1.8.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-13 13:32:04 +00:00
dependabot[bot]
6bb44d0efc
Update nornir-salt requirement from >=0.23.0 to >=0.23.4
Updates the requirements on [nornir-salt](https://github.com/dmulyalin/nornir-salt) to permit the latest version.
- [Release notes](https://github.com/dmulyalin/nornir-salt/releases)
- [Commits](https://github.com/dmulyalin/nornir-salt/compare/0.23.0...0.23.4)

---
updated-dependencies:
- dependency-name: nornir-salt
  dependency-version: 0.23.4
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-13 13:31:53 +00:00
dependabot[bot]
a839a90e65
Update setuptools requirement from >=61.0 to >=84.0.0
Updates the requirements on [setuptools](https://github.com/pypa/setuptools) to permit the latest version.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v61.0.0...v84.0.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-version: 84.0.0
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-13 13:31:48 +00:00
grossmj
e8c641bd08
docs: update comments regarding Ethernet switch replacement with Linux bridge 2026-10-13 20:18:29 +07:00
YueGuobin
90917c4a2c
fix(docker): accept the pinned image id when the stores report different ids
Docker ids are not comparable across image stores: for the same content a
classic store reports the config digest while a containerd store (or an
image loaded from an OCI archive) reports the manifest digest. The
controller pins the id of its own daemon, so a compute whose store reports
another id for that content answered ImageMissingError forever: every node
creation streamed the image again (save/load round trip) without ever
converging, then failed with "The image 'x' is missing" after the six
retries. Docker 29 makes this easy to hit, since the id a daemon reports
now depends on how the image entered it.

The load endpoint now takes the tag and the digest pinned by the
controller, and the compute records how its own daemon identifies the
image it just received. Node creation accepts the pin through that pair,
and only while the tag still resolves to the synced content: a tag moved
to some other image, or an image the controller never pushed here, still
counts as missing. The pair lives in the compute process, so a restarted
compute syncs once more.

Computes that predate the new endpoint parameters keep the previous
behaviour, as do controllers that do not send them.
2026-10-13 17:10:17 +08:00
Jeremy Grossmann
2799780eca
Merge pull request #2980 from yueguobin/docs/vpcs-anchor-startup
docs: amend vpcs-kernel-datapath.md with the anchor startup sequence
2026-10-12 14:58:25 +02:00
YueGuobin
031abf0e52
docs: record the VPCS anchor startup sequence and capability model
The ordered startup (uBridge creates the persistent TAP and hands it to
the server's uid before vpcs is launched, vpcs attaches with -e -d), why
the attach needs no privileges while creating a TAP does, that uBridge
stays off the data path, and that the setcap in the vpcs install target
is for standalone use only.
2026-10-12 20:10:56 +08:00
Jeremy Grossmann
6d838c890d
Merge pull request #2979 from yueguobin/feat/vpcs-kernel-datapath
feat: VPCS kernel datapath
2026-10-12 13:12:43 +02:00
YueGuobin
3f2b44101f
style: apply ruff format to the VPCS datapath test 2026-10-12 17:26:46 +08:00