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 :|