Skip to content

Support serial devices to resource API#2675

Merged
stgraber merged 8 commits intolxc:mainfrom
baconYao:dev-serial-issue-2669
Nov 28, 2025
Merged

Support serial devices to resource API#2675
stgraber merged 8 commits intolxc:mainfrom
baconYao:dev-serial-issue-2669

Conversation

@baconYao
Copy link
Copy Markdown
Contributor

Fixes: #2669

@github-actions github-actions bot added the API Changes to the REST API label Nov 19, 2025
@stgraber
Copy link
Copy Markdown
Member

@baconYao can you make sure that your commits include the required Signed-off-by line? (see CONTRIBUTING.md)

@baconYao
Copy link
Copy Markdown
Contributor Author

@stgraber Roger that!

@stgraber
Copy link
Copy Markdown
Member

@baconYao Unfortunately the shared/resources package must be buildable without CGO which makes it impossible for it to use go-udev.

You can do a test build of it with:

CGO_ENABLED=0 go build -v -x ./shared/resources

That's why all the other resources only deal with a mix of /sys and /dev entries, lining up the two to put together the structs rather than being able to easily get data out of udev.

There is an exception with the storage stuff where we really needed the udev data and so directly parse the udev database from /run/udev/data, but we generally try to avoid it when possible or at least make sure that you still get some useful base data without it as not all systems running Incus use udev.

@baconYao baconYao force-pushed the dev-serial-issue-2669 branch from e1cbe68 to f17def0 Compare November 25, 2025 08:36
@github-actions github-actions bot added the Documentation Documentation needs updating label Nov 25, 2025
@baconYao
Copy link
Copy Markdown
Contributor Author

Thank you @stgraber! I will rewrite it without leveraging udev.

@baconYao
Copy link
Copy Markdown
Contributor Author

baconYao commented Nov 26, 2025

Hi @stgraber

The serial devices I emulate using QEMU are being recognized by Incus as USB devices. I’d like to ask if you have any thoughts on this issue?

Below is the output produced by incus info --resources command

baconyao@baconyao-x86-qemu:~$ incus info --resources
System:
  Vendor: QEMU
  Product: Standard PC (i440FX + PIIX, 1996)
  Version: pc-i440fx-10.1
  Type: virtual-machine
  Chassis:
      Vendor: QEMU
      Type: Other
      Version: pc-i440fx-10.1
  Motherboard:
  Firmware:
      Vendor: SeaBIOS
      Version: rel-1.17.0-0-gb52ca86e094d-prebuilt.qemu.org
      Date: 04/01/2014

CPU (x86_64):
  Vendor: AuthenticAMD
  Name: QEMU Virtual CPU version 2.5+
  Caches:
    - Level 1 (type: Data): 64KiB
    - Level 1 (type: Instruction): 64KiB
    - Level 2 (type: Unified): 512KiB
    - Level 3 (type: Unified): 16MiB
  Cores:
    - Core 0
      Frequency: 0Mhz
      Threads:
        - 0 (id: 0, online: true, NUMA node: 0)
    - Core 1
      Frequency: 0Mhz
      Threads:
        - 0 (id: 1, online: true, NUMA node: 0)
    - Core 2
      Frequency: 0Mhz
      Threads:
        - 0 (id: 2, online: true, NUMA node: 0)
    - Core 3
      Frequency: 0Mhz
      Threads:
        - 0 (id: 3, online: true, NUMA node: 0)
    - Core 4
      Frequency: 0Mhz
      Threads:
        - 0 (id: 4, online: true, NUMA node: 0)
    - Core 5
      Frequency: 0Mhz
      Threads:
        - 0 (id: 5, online: true, NUMA node: 0)

Memory:
  Free: 7.41GiB
  Used: 607.64MiB
  Total: 8.00GiB

GPU:
  NUMA node: 0
  PCI address: 0000:00:02.0
  Driver: bochs-drm (6.8.0-88-generic)
  DRM:
    ID: 0
    Card: card0 (226:0)
    Control: controlD64 (226:0)

NIC:
  NUMA node: 0
  Vendor: Intel Corporation (8086)
  Product: 82540EM Gigabit Ethernet Controller (100e)
  PCI address: 0000:00:04.0
  Driver: e1000 (6.8.0-88-generic)
  Ports:
    - Port 0 (ethernet)
      ID: ens4
      Address: 52:54:00:12:34:56
      Supported modes: 10baseT/Half, 10baseT/Full, 100baseT/Half, 100baseT/Full, 1000baseT/Full
      Supported ports: twisted pair
      Port type: twisted pair
      Transceiver type: internal
      Auto negotiation: true
      Link detected: true
      Link speed: 1000Mbit/s (full duplex)

Disks:
  Disk 0:
    NUMA node: 0
    ID: fd0
    Device: 2:0
    Type: platform
    Size: 4.00KiB
    Read-Only: false
    Removable: true
  Disk 1:
    NUMA node: 0
    ID: sda
    Device: 8:0
    Model: QEMU HARDDISK
    Type: scsi
    Size: 20.00GiB
    Read-Only: false
    Removable: false
    Partitions:
      - Partition 1
        ID: sda1
        Device: 8:1
        Read-Only: false
        Size: 1.00MiB
      - Partition 2
        ID: sda2
        Device: 8:2
        Read-Only: false
        Size: 1.77GiB
      - Partition 3
        ID: sda3
        Device: 8:3
        Read-Only: false
        Size: 18.23GiB
  Disk 2:
    NUMA node: 0
    ID: sr0
    Device: 11:0
    Model: QEMU DVD-ROM
    Type: cdrom
    Size: 0B
    Read-Only: false
    Removable: true

USB devices:
  Device 0:
    Vendor: Future Technology Devices International, Ltd
    Vendor ID: 0403
    Product: QEMU USB SERIAL
    Product ID: 6001
    Bus Address: 1
    Device Address: 2
  Device 1:
    Vendor: Future Technology Devices International, Ltd
    Vendor ID: 0403
    Product: QEMU USB SERIAL
    Product ID: 6001
    Bus Address: 1
    Device Address: 3

Below is the command I use to start QEMU.

qemu-system-x86_64 \
  -m 8192 -smp 6 -cpu qemu64 \
  -hda ubuntu.qcow2 \
  -device nec-usb-xhci,id=xhci \
  -chardev ringbuf,id=ch0,size=65536 \
  -device usb-serial,id=fake1,chardev=ch0 \
  -chardev ringbuf,id=ch1,size=65536 \
  -device usb-serial,id=fake2,chardev=ch1 \
  -netdev user,id=net0,hostfwd=tcp::2222-:22 \
  -device e1000,netdev=net0 \
  -display default \
  -accel tcg

Below is the udev info I see inside the VM (e.g., for /dev/ttyUSB0).

P: /devices/pci0000:00/0000:00:03.0/usb1/1-1/1-1:1.0/ttyUSB0/tty/ttyUSB0
M: ttyUSB0
R: 0
U: tty
D: c 188:0
N: ttyUSB0
L: 0
S: serial/by-path/pci-0000:00:03.0-usb-0:1:1.0-port0
S: serial/by-path/pci-0000:00:03.0-usbv2-0:1:1.0-port0
S: serial/by-id/usb-QEMU_QEMU_USB_SERIAL_1-0000:00:03.0-1-if00-port0
E: DEVPATH=/devices/pci0000:00/0000:00:03.0/usb1/1-1/1-1:1.0/ttyUSB0/tty/ttyUSB0
E: DEVNAME=/dev/ttyUSB0
E: MAJOR=188
E: MINOR=0
E: SUBSYSTEM=tty
E: USEC_INITIALIZED=18082429
E: ID_BUS=usb
E: ID_MODEL=QEMU_USB_SERIAL
E: ID_MODEL_ENC=QEMU\x20USB\x20SERIAL
E: ID_MODEL_ID=6001
E: ID_SERIAL=QEMU_QEMU_USB_SERIAL_1-0000:00:03.0-1
E: ID_SERIAL_SHORT=1-0000:00:03.0-1
E: ID_VENDOR=QEMU
E: ID_VENDOR_ENC=QEMU
E: ID_VENDOR_ID=0403
E: ID_REVISION=0400
E: ID_TYPE=generic
E: ID_USB_MODEL=QEMU_USB_SERIAL
E: ID_USB_MODEL_ENC=QEMU\x20USB\x20SERIAL
E: ID_USB_MODEL_ID=6001
E: ID_USB_SERIAL=QEMU_QEMU_USB_SERIAL_1-0000:00:03.0-1
E: ID_USB_SERIAL_SHORT=1-0000:00:03.0-1
E: ID_USB_VENDOR=QEMU
E: ID_USB_VENDOR_ENC=QEMU
E: ID_USB_VENDOR_ID=0403
E: ID_USB_REVISION=0400
E: ID_USB_TYPE=generic
E: ID_USB_INTERFACES=:ffffff:
E: ID_USB_INTERFACE_NUM=00
E: ID_USB_DRIVER=ftdi_sio
E: ID_VENDOR_FROM_DATABASE=Future Technology Devices International, Ltd
E: ID_MODEL_FROM_DATABASE=FT232 Serial (UART) IC
E: ID_PATH_WITH_USB_REVISION=pci-0000:00:03.0-usbv2-0:1:1.0
E: ID_PATH=pci-0000:00:03.0-usb-0:1:1.0
E: ID_PATH_TAG=pci-0000_00_03_0-usb-0_1_1_0
E: ID_MM_CANDIDATE=1
E: DEVLINKS=/dev/serial/by-path/pci-0000:00:03.0-usb-0:1:1.0-port0 /dev/serial/by-path/pci-0000:00:03.0-usbv2-0:1:1.0-port0 /dev/serial/by-id/usb-QEMU_QEMU_USB_SERIAL_1-0000:00:03.0-1-if00-port0
E: TAGS=:systemd:
E: CURRENT_TAGS=:systemd:

Below is the output produced by my implementation of the Serial API (the GetSerial() function):

{
  "devices": [
    {
      "id": "ttyUSB0",
      "device": "188:0",
      "device_id": "/dev/serial/by-id/usb-QEMU_QEMU_USB_SERIAL_1-0000:00:03.0-1-if00-port0",
      "device_path": "/dev/serial/by-path/pci-0000:00:03.0-usbv2-0:1:1.0-port0",
      "driver": "ftdi_sio",
      "vendor": "Future Technology Devices International, Ltd",
      "vendor_id": "0403",
      "product": "FT232 Serial (UART) IC",
      "product_id": "6001"
    },
    {
      "id": "ttyUSB1",
      "device": "188:1",
      "device_id": "/dev/serial/by-id/usb-QEMU_QEMU_USB_SERIAL_1-0000:00:03.0-2-if00-port0",
      "device_path": "/dev/serial/by-path/pci-0000:00:03.0-usbv2-0:2:1.0-port0",
      "driver": "ftdi_sio",
      "vendor": "Future Technology Devices International, Ltd",
      "vendor_id": "0403",
      "product": "FT232 Serial (UART) IC",
      "product_id": "6001"
    }
  ],
  "total": 2
}

@stgraber
Copy link
Copy Markdown
Member

Looking into this one now

@stgraber stgraber force-pushed the dev-serial-issue-2669 branch from ec1ca8a to 6a620e0 Compare November 28, 2025 07:37
stgraber and others added 8 commits November 28, 2025 02:38
Signed-off-by: Stéphane Graber <[email protected]>
Add ResourcesSerial and ResourcesSerialDevice types to expose serial
device information in the resources API.

Signed-off-by: baconyao <[email protected]>
Initialized GetSerial() function and integrate it into GetResources()
to expose serial devices information through the resources API.

Signed-off-by: baconyao <[email protected]>
Signed-off-by: Stéphane Graber <[email protected]>
Signed-off-by: Stéphane Graber <[email protected]>
@stgraber stgraber force-pushed the dev-serial-issue-2669 branch from 6a620e0 to 30329e2 Compare November 28, 2025 07:39
@stgraber stgraber marked this pull request as ready for review November 28, 2025 08:17
@stgraber stgraber self-requested a review as a code owner November 28, 2025 08:17
@stgraber stgraber merged commit d29ca4f into lxc:main Nov 28, 2025
36 of 38 checks passed
@baconYao
Copy link
Copy Markdown
Contributor Author

baconYao commented Dec 1, 2025

Thank you @stgraber

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

API Changes to the REST API Documentation Documentation needs updating

Development

Successfully merging this pull request may close these issues.

Add serial devices to the resources API

2 participants