The virsh noddev-list command is used to display node devices. It just prints out their names in a flat list. When detaching devices for purposes of PCI passthrough though, it is important to understand what devices are children of the PCI device about to be detached. It is tedious to find this out, the user having to run virsh nodedev-dumpxml and look at the parent field. # virsh -c qemu:///system nodedev-list computer DVD_GCC_4247N net_00_13_02_b9_f9_d3 net_00_13_02_b9_f9_d3_0 net_00_15_58_2f_e9_55 pci_1002_71c4 pci_104c_ac56 pci_8086_27c5_scsi_host pci_8086_27c5_scsi_host_0 pci_8086_27c5_scsi_host_1 pci_8086_27c5_scsi_host_2 pci_8086_27c5_scsi_host_scsi_device_lun0 pci_8086_27c5_scsi_host_scsi_host pci_8086_27c8 pci_8086_27da pci_8086_27df pci_8086_27df_scsi_host pci_8086_27df_scsi_host_0 pci_8086_27df_scsi_host_scsi_device_lun0 pci_8086_27df_scsi_host_scsi_host pci_8086_4227 storage_serial_SATA_HTS721010G9SA00_MPCZ12Y0GNGWSE usb_device_a5c_2110_noserial_if3 This patch adds a new '--tree' flag to the nodedev-list command, allowing a prettier format to be used # virsh -c qemu:///system nodedev-list --tree computer | +-pci_8086_2448 | | | +-pci_104c_ac56 | +-pci_8086_27a0 +-pci_8086_27a1 | | | +-pci_1002_71c4 | +-pci_8086_27b9 +-pci_8086_27c5 | | | +-pci_8086_27c5_scsi_host | | | | | +-pci_8086_27c5_scsi_host_scsi_device_lun0 | | | | | | | +-storage_serial_SATA_HTS721010G9SA00_MPCZ12Y0GNGWSE | | | | | +-pci_8086_27c5_scsi_host_scsi_host | | | +-pci_8086_27c5_scsi_host_0 | +-pci_8086_27c5_scsi_host_1 | +-pci_8086_27c5_scsi_host_2 | +-pci_8086_27c8 | | | +-usb_device_1d6b_1_0000_00_1d_0 | | | +-usb_device_1d6b_1_0000_00_1d_0_if0 | +-pci_8086_27c9 | | | +-usb_device_1d6b_1_0000_00_1d_1 | | | +-usb_device_1d6b_1_0000_00_1d_1_if0 | +-pci_8086_27ca | | | +-usb_device_1d6b_1_0000_00_1d_2 | | | +-usb_device_1d6b_1_0000_00_1d_2_if0 | +-pci_8086_27cb | | | +-usb_device_1d6b_1_0000_00_1d_3 | | | +-usb_device_1d6b_1_0000_00_1d_3_if0 | +-usb_device_483_2016_noserial | | | | | +-usb_device_483_2016_noserial_if0 | | | +-usb_device_a5c_2110_noserial | | | +-usb_device_a5c_2110_noserial_if0 | +-usb_device_a5c_2110_noserial_if1 | +-usb_device_a5c_2110_noserial_if2 | +-usb_device_a5c_2110_noserial_if3 | +-pci_8086_27cc | | | +-usb_device_1d6b_2_0000_00_1d_7 | | | +-usb_device_1d6b_2_0000_00_1d_7_if0 | +-pci_8086_27d0 | | | +-pci_8086_109a | | | +-net_00_15_58_2f_e9_55 | +-pci_8086_27d2 | | | +-pci_8086_4227 | | | +-net_00_13_02_b9_f9_d3 | +-net_00_13_02_b9_f9_d3_0 | +-pci_8086_27d4 +-pci_8086_27d6 +-pci_8086_27d8 +-pci_8086_27da +-pci_8086_27df | +-pci_8086_27df_scsi_host | | | +-pci_8086_27df_scsi_host_scsi_device_lun0 | | | | | +-DVD_GCC_4247N | | | +-pci_8086_27df_scsi_host_scsi_host | +-pci_8086_27df_scsi_host_0 Daniel diff -r b73fe666feff src/virsh.c --- a/src/virsh.c Fri Mar 27 16:14:49 2009 +0000 +++ b/src/virsh.c Mon Mar 30 14:37:45 2009 +0100 @@ -4391,16 +4391,77 @@ static const vshCmdInfo info_node_list_d }; static const vshCmdOptDef opts_node_list_devices[] = { + {"tree", VSH_OT_BOOL, 0, gettext_noop("list devices in a tree")}, {"cap", VSH_OT_STRING, VSH_OFLAG_NONE, gettext_noop("capability name")}, {NULL, 0, 0, NULL} }; +#define MAX_INDENT 100 + +static void +cmdNodeListDevicesPrint(vshControl *ctl, + char **devices, + char **parents, + int num_devices, + int devid, + int lastdev, + unsigned int depth, + char *indent) +{ + int i; + int nextlastdev = -1; + + if (depth) { + indent[depth] = '+'; + indent[depth+1] = '-'; + } + + vshPrint(ctl, indent); + if (depth) { + if (devid == lastdev) + indent[depth] = ' '; + else + indent[depth] = '|'; + indent[depth+1] = ' '; + depth+=2; + } + vshPrint(ctl, "%s\n", devices[devid]); + + for (i = 0 ; i < num_devices ; i++) { + if (parents[i] && + STREQ(parents[i], devices[devid])) { + //fprintf(stderr, "%s %s %d %d\n", parents[i], devices[devid], i, devid); + nextlastdev = i; + } + } + + if (nextlastdev != -1) { + vshPrint(ctl, indent); + vshPrint(ctl, " |\n"); + } + + indent[depth] = ' '; + for (i = 0 ; i < num_devices ; i++) { + indent[depth] = ' '; + indent[depth+1] = ' '; + if (parents[i] && + STREQ(parents[i], devices[devid])) + cmdNodeListDevicesPrint(ctl, devices, parents, num_devices, i, nextlastdev, depth + 2, indent); + indent[depth] = '\0'; + } + if (nextlastdev == -1 && devid == lastdev) { + vshPrint(ctl, indent); + vshPrint(ctl, "\n"); + } +} + static int cmdNodeListDevices (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { char *cap; char **devices; int found, num_devices, i; + int tree = vshCommandOptBool(cmd, "tree"); if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) return FALSE; @@ -4426,9 +4487,39 @@ cmdNodeListDevices (vshControl *ctl, con return FALSE; } qsort(&devices[0], num_devices, sizeof(char*), namesorter); - for (i = 0; i < num_devices; i++) { - vshPrint(ctl, "%s\n", devices[i]); - free(devices[i]); + if (tree) { + char indent[MAX_INDENT]; + char **parents = vshMalloc(ctl, sizeof(char *) * num_devices); + for (i = 0; i < num_devices; i++) { + virNodeDevicePtr dev = virNodeDeviceLookupByName(ctl->conn, devices[i]); + if (dev && STRNEQ(devices[i], "computer")) { + const char *parent = virNodeDeviceGetParent(dev); + parents[i] = parent ? strdup(parent) : NULL; + } else { + parents[i] = NULL; + } + virNodeDeviceFree(dev); + } + for (i = 0 ; i < num_devices ; i++) { + memset(indent, '\0', sizeof indent); + if (parents[i] == NULL) + cmdNodeListDevicesPrint(ctl, + devices, + parents, + num_devices, + i, + i, + 0, + indent); + } + for (i = 0 ; i < num_devices ; i++) + free(parents[i]); + free(parents); + } else { + for (i = 0; i < num_devices; i++) { + vshPrint(ctl, "%s\n", devices[i]); + free(devices[i]); + } } free(devices); return TRUE; -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list