[libvirt] [PATCH 1/3] Make QEMU driver use -chardev everywhere when it's available

Change -monitor, -serial and -parallel output to use -chardev if it is available. * src/qemu/qemu_conf.c: Update qemudBuildCommandLine to use -chardev where available. * tests/qemuxml2argvtest.c tests/qemuxml2argvdata/: Add -chardev equivalents for all current serial and parallel tests. --- src/qemu/qemu_conf.c | 108 +++++++++++++++++--- .../qemuxml2argv-channel-guestfwd.args | 2 +- .../qemuxml2argv-console-compat-chardev.args | 1 + .../qemuxml2argv-console-compat-chardev.xml | 28 +++++ .../qemuxml2argv-parallel-tcp-chardev.args | 1 + .../qemuxml2argv-parallel-tcp-chardev.xml | 27 +++++ .../qemuxml2argv-serial-dev-chardev.args | 1 + .../qemuxml2argv-serial-dev-chardev.xml | 30 ++++++ .../qemuxml2argv-serial-file-chardev.args | 1 + .../qemuxml2argv-serial-file-chardev.xml | 30 ++++++ .../qemuxml2argv-serial-many-chardev.args | 1 + .../qemuxml2argv-serial-many-chardev.xml | 32 ++++++ .../qemuxml2argv-serial-pty-chardev.args | 1 + .../qemuxml2argv-serial-pty-chardev.xml | 28 +++++ .../qemuxml2argv-serial-tcp-chardev.args | 1 + .../qemuxml2argv-serial-tcp-chardev.xml | 32 ++++++ .../qemuxml2argv-serial-tcp-telnet-chardev.args | 1 + .../qemuxml2argv-serial-tcp-telnet-chardev.xml | 32 ++++++ .../qemuxml2argv-serial-udp-chardev.args | 1 + .../qemuxml2argv-serial-udp-chardev.xml | 32 ++++++ .../qemuxml2argv-serial-unix-chardev.args | 1 + .../qemuxml2argv-serial-unix-chardev.xml | 30 ++++++ .../qemuxml2argv-serial-vc-chardev.args | 1 + .../qemuxml2argv-serial-vc-chardev.xml | 28 +++++ tests/qemuxml2argvtest.c | 12 ++ 25 files changed, 445 insertions(+), 17 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-console-compat-chardev.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-console-compat-chardev.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-parallel-tcp-chardev.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-parallel-tcp-chardev.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-dev-chardev.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-dev-chardev.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-file-chardev.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-file-chardev.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-many-chardev.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-many-chardev.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-pty-chardev.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-pty-chardev.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-chardev.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-chardev.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-telnet-chardev.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-telnet-chardev.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-udp-chardev.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-udp-chardev.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-unix-chardev.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-unix-chardev.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-vc-chardev.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-vc-chardev.xml diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index a25fac6..86172c6 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -1863,17 +1863,37 @@ int qemudBuildCommandLine(virConnectPtr conn, if (monitor_chr) { virBuffer buf = VIR_BUFFER_INITIALIZER; - if (monitor_json) - virBufferAddLit(&buf, "control,"); + /* Use -chardev if it's available */ + if (qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) { + qemudBuildCommandLineChrDevChardevStr(monitor_chr, "monitor", &buf); + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + goto no_memory; + } + + ADD_ARG_LIT("-chardev"); + ADD_ARG(virBufferContentAndReset(&buf)); + + if (monitor_json) + virBufferAddLit(&buf, "control,"); + + virBufferAddLit(&buf, "chardev:monitor"); + } + + else { + if (monitor_json) + virBufferAddLit(&buf, "control,"); + + qemudBuildCommandLineChrDevStr(monitor_chr, &buf); + } - qemudBuildCommandLineChrDevStr(monitor_chr, &buf); if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); goto no_memory; } ADD_ARG_LIT("-monitor"); - ADD_ARG(virBufferContentAndReset(&buf)); + ADD_ARG_LIT(virBufferContentAndReset(&buf)); } if (def->localtime) @@ -2199,14 +2219,42 @@ int qemudBuildCommandLine(virConnectPtr conn, virBuffer buf = VIR_BUFFER_INITIALIZER; virDomainChrDefPtr serial = def->serials[i]; - qemudBuildCommandLineChrDevStr(serial, &buf); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - goto no_memory; + /* Use -chardev if it's available */ + if (qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) { + char id[16]; + + if (snprintf(id, sizeof(id), "serial%i", i) > sizeof(id)) + goto error; + + qemudBuildCommandLineChrDevChardevStr(serial, id, &buf); + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + goto no_memory; + } + + ADD_ARG_LIT("-chardev"); + ADD_ARG(virBufferContentAndReset(&buf)); + + virBufferVSprintf(&buf, "chardev:%s", id); + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + goto no_memory; + } + + ADD_ARG_LIT("-serial"); + ADD_ARG(virBufferContentAndReset(&buf)); } - ADD_ARG_LIT("-serial"); - ADD_ARG(virBufferContentAndReset(&buf)); + else { + qemudBuildCommandLineChrDevStr(serial, &buf); + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + goto no_memory; + } + + ADD_ARG_LIT("-serial"); + ADD_ARG(virBufferContentAndReset(&buf)); + } } } @@ -2218,14 +2266,42 @@ int qemudBuildCommandLine(virConnectPtr conn, virBuffer buf = VIR_BUFFER_INITIALIZER; virDomainChrDefPtr parallel = def->parallels[i]; - qemudBuildCommandLineChrDevStr(parallel, &buf); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - goto no_memory; + /* Use -chardev if it's available */ + if (qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) { + char id[16]; + + if (snprintf(id, sizeof(id), "parallel%i", i) > sizeof(id)) + goto error; + + qemudBuildCommandLineChrDevChardevStr(parallel, id, &buf); + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + goto no_memory; + } + + ADD_ARG_LIT("-chardev"); + ADD_ARG(virBufferContentAndReset(&buf)); + + virBufferVSprintf(&buf, "chardev:%s", id); + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + goto no_memory; + } + + ADD_ARG_LIT("-parallel"); + ADD_ARG(virBufferContentAndReset(&buf)); } - ADD_ARG_LIT("-parallel"); - ADD_ARG(virBufferContentAndReset(&buf)); + else { + qemudBuildCommandLineChrDevStr(parallel, &buf); + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + goto no_memory; + } + + ADD_ARG_LIT("-parallel"); + ADD_ARG(virBufferContentAndReset(&buf)); + } } } diff --git a/tests/qemuxml2argvdata/qemuxml2argv-channel-guestfwd.args b/tests/qemuxml2argvdata/qemuxml2argv-channel-guestfwd.args index b5bb46d..deaff92 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-channel-guestfwd.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-channel-guestfwd.args @@ -1 +1 @@ -LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -chardev pipe,id=channel0,path=/tmp/guestfwd -net user,guestfwd=tcp:10.0.2.1:4600-chardev:channel0 -usb +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -chardev socket,id=monitor,path=/tmp/test-monitor,server,nowait -monitor chardev:monitor -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -chardev pipe,id=channel0,path=/tmp/guestfwd -net user,guestfwd=tcp:10.0.2.1:4600-chardev:channel0 -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-console-compat-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-console-compat-chardev.args new file mode 100644 index 0000000..fbb94f4 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-console-compat-chardev.args @@ -0,0 +1 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -chardev socket,id=monitor,path=/tmp/test-monitor,server,nowait -monitor chardev:monitor -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -chardev pty,id=serial0 -serial chardev:serial0 -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-console-compat-chardev.xml b/tests/qemuxml2argvdata/qemuxml2argv-console-compat-chardev.xml new file mode 100644 index 0000000..c16ae07 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-console-compat-chardev.xml @@ -0,0 +1,28 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + </disk> + <serial type='pty'> + <target port='0'/> + </serial> + <console type='pty'> + <target port='0'/> + </console> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-parallel-tcp-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-parallel-tcp-chardev.args new file mode 100644 index 0000000..45d1759 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-parallel-tcp-chardev.args @@ -0,0 +1 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -chardev socket,id=monitor,path=/tmp/test-monitor,server,nowait -monitor chardev:monitor -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -chardev socket,id=parallel0,host=127.0.0.1,port=9999,server,nowait -parallel chardev:parallel0 -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-parallel-tcp-chardev.xml b/tests/qemuxml2argvdata/qemuxml2argv-parallel-tcp-chardev.xml new file mode 100644 index 0000000..08176f1 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-parallel-tcp-chardev.xml @@ -0,0 +1,27 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + </disk> + <parallel type='tcp'> + <source mode='bind' host='127.0.0.1' service='9999'/> + <protocol type='raw'/> + <target port='0'/> + </parallel> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-dev-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-dev-chardev.args new file mode 100644 index 0000000..3036f13 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-dev-chardev.args @@ -0,0 +1 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -chardev socket,id=monitor,path=/tmp/test-monitor,server,nowait -monitor chardev:monitor -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -chardev tty,id=serial0,path=/dev/ttyS2 -serial chardev:serial0 -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-dev-chardev.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-dev-chardev.xml new file mode 100644 index 0000000..2b8ef5a --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-dev-chardev.xml @@ -0,0 +1,30 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + </disk> + <serial type='dev'> + <source path='/dev/ttyS2'/> + <target port='0'/> + </serial> + <console type='dev'> + <source path='/dev/ttyS2'/> + <target port='0'/> + </console> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-file-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-file-chardev.args new file mode 100644 index 0000000..1dcec2b --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-file-chardev.args @@ -0,0 +1 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -chardev socket,id=monitor,path=/tmp/test-monitor,server,nowait -monitor chardev:monitor -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -chardev file,id=serial0,path=/tmp/serial.log -serial chardev:serial0 -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-file-chardev.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-file-chardev.xml new file mode 100644 index 0000000..3726816 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-file-chardev.xml @@ -0,0 +1,30 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + </disk> + <serial type='file'> + <source path='/tmp/serial.log'/> + <target port='0'/> + </serial> + <console type='file'> + <source path='/tmp/serial.log'/> + <target port='0'/> + </console> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-many-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-many-chardev.args new file mode 100644 index 0000000..dd98fcb --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-many-chardev.args @@ -0,0 +1 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -chardev socket,id=monitor,path=/tmp/test-monitor,server,nowait -monitor chardev:monitor -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -chardev pty,id=serial0 -serial chardev:serial0 -chardev file,id=serial1,path=/tmp/serial.log -serial chardev:serial1 -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-many-chardev.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-many-chardev.xml new file mode 100644 index 0000000..444e85b --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-many-chardev.xml @@ -0,0 +1,32 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + </disk> + <serial type='pty'> + <target port='0'/> + </serial> + <serial type='file'> + <source path='/tmp/serial.log'/> + <target port='1'/> + </serial> + <console type='pty'> + <target port='0'/> + </console> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-pty-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-pty-chardev.args new file mode 100644 index 0000000..fbb94f4 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-pty-chardev.args @@ -0,0 +1 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -chardev socket,id=monitor,path=/tmp/test-monitor,server,nowait -monitor chardev:monitor -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -chardev pty,id=serial0 -serial chardev:serial0 -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-pty-chardev.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-pty-chardev.xml new file mode 100644 index 0000000..c16ae07 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-pty-chardev.xml @@ -0,0 +1,28 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + </disk> + <serial type='pty'> + <target port='0'/> + </serial> + <console type='pty'> + <target port='0'/> + </console> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-chardev.args new file mode 100644 index 0000000..50cfeb0 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-chardev.args @@ -0,0 +1 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -chardev socket,id=monitor,path=/tmp/test-monitor,server,nowait -monitor chardev:monitor -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -chardev socket,id=serial0,host=127.0.0.1,port=9999 -serial chardev:serial0 -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-chardev.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-chardev.xml new file mode 100644 index 0000000..3bcf62d --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-chardev.xml @@ -0,0 +1,32 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + </disk> + <serial type='tcp'> + <source mode='connect' host='127.0.0.1' service='9999'/> + <protocol type='raw'/> + <target port='0'/> + </serial> + <console type='tcp'> + <source mode='connect' host='127.0.0.1' service='9999'/> + <protocol type='raw'/> + <target port='0'/> + </console> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-telnet-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-telnet-chardev.args new file mode 100644 index 0000000..86fa8af --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-telnet-chardev.args @@ -0,0 +1 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -chardev socket,id=monitor,path=/tmp/test-monitor,server,nowait -monitor chardev:monitor -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -chardev socket,id=serial0,host=127.0.0.1,port=9999,telnet,server,nowait -serial chardev:serial0 -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-telnet-chardev.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-telnet-chardev.xml new file mode 100644 index 0000000..bea4306 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-telnet-chardev.xml @@ -0,0 +1,32 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + </disk> + <serial type='tcp'> + <source mode='bind' host='127.0.0.1' service='9999'/> + <protocol type='telnet'/> + <target port='0'/> + </serial> + <console type='tcp'> + <source mode='bind' host='127.0.0.1' service='9999'/> + <protocol type='telnet'/> + <target port='0'/> + </console> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-udp-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-udp-chardev.args new file mode 100644 index 0000000..45421a4 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-udp-chardev.args @@ -0,0 +1 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -chardev socket,id=monitor,path=/tmp/test-monitor,server,nowait -monitor chardev:monitor -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -chardev udp,id=serial0,host=127.0.0.1,port=9998,localaddr=127.0.0.1,localport=9999 -serial chardev:serial0 -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-udp-chardev.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-udp-chardev.xml new file mode 100644 index 0000000..115166d --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-udp-chardev.xml @@ -0,0 +1,32 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + </disk> + <serial type='udp'> + <source mode='bind' host='127.0.0.1' service='9999'/> + <source mode='connect' host='127.0.0.1' service='9998'/> + <target port='0'/> + </serial> + <console type='udp'> + <source mode='bind' host='127.0.0.1' service='9999'/> + <source mode='connect' host='127.0.0.1' service='9998'/> + <target port='0'/> + </console> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-unix-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-unix-chardev.args new file mode 100644 index 0000000..f291156 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-unix-chardev.args @@ -0,0 +1 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -chardev socket,id=monitor,path=/tmp/test-monitor,server,nowait -monitor chardev:monitor -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -chardev socket,id=serial0,path=/tmp/serial.sock -serial chardev:serial0 -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-unix-chardev.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-unix-chardev.xml new file mode 100644 index 0000000..4236b4c --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-unix-chardev.xml @@ -0,0 +1,30 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + </disk> + <serial type='unix'> + <source mode='connect' path='/tmp/serial.sock'/> + <target port='0'/> + </serial> + <console type='unix'> + <source mode='connect' path='/tmp/serial.sock'/> + <target port='0'/> + </console> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-vc-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-vc-chardev.args new file mode 100644 index 0000000..a200225 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-vc-chardev.args @@ -0,0 +1 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -chardev socket,id=monitor,path=/tmp/test-monitor,server,nowait -monitor chardev:monitor -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -chardev vc,id=serial0 -serial chardev:serial0 -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-vc-chardev.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-vc-chardev.xml new file mode 100644 index 0000000..1e5de8f --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-vc-chardev.xml @@ -0,0 +1,28 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + </disk> + <serial type='vc'> + <target port='0'/> + </serial> + <console type='vc'> + <target port='0'/> + </console> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index c39cbbc..3b0aa2b 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -273,6 +273,18 @@ mymain(int argc, char **argv) DO_TEST("parallel-tcp", 0); DO_TEST("console-compat", 0); + DO_TEST("serial-vc-chardev", QEMUD_CMD_FLAG_CHARDEV); + DO_TEST("serial-pty-chardev", QEMUD_CMD_FLAG_CHARDEV); + DO_TEST("serial-dev-chardev", QEMUD_CMD_FLAG_CHARDEV); + DO_TEST("serial-file-chardev", QEMUD_CMD_FLAG_CHARDEV); + DO_TEST("serial-unix-chardev", QEMUD_CMD_FLAG_CHARDEV); + DO_TEST("serial-tcp-chardev", QEMUD_CMD_FLAG_CHARDEV); + DO_TEST("serial-udp-chardev", QEMUD_CMD_FLAG_CHARDEV); + DO_TEST("serial-tcp-telnet-chardev", QEMUD_CMD_FLAG_CHARDEV); + DO_TEST("serial-many-chardev", QEMUD_CMD_FLAG_CHARDEV); + DO_TEST("parallel-tcp-chardev", QEMUD_CMD_FLAG_CHARDEV); + DO_TEST("console-compat-chardev", QEMUD_CMD_FLAG_CHARDEV); + DO_TEST("channel-guestfwd", QEMUD_CMD_FLAG_CHARDEV); DO_TEST("sound", 0); -- 1.6.5.2

* src/qemu/qemu_driver.c: Parse pty devices for channels --- src/qemu/qemu_driver.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 2fb059d..c1feb0f 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1439,6 +1439,16 @@ qemudFindCharDevicePTYs(virConnectPtr conn, } } + /* then the channel devices */ + for (i = 0 ; i < vm->def->nchannels ; i++) { + virDomainChrDefPtr chr = vm->def->channels[i]; + if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) { + if ((ret = qemudExtractTTYPath(conn, output, &offset, + &chr->data.file.path)) != 0) + return ret; + } + } + return 0; } -- 1.6.5.2

This change makes the QEMU driver get pty paths from the output of the monitor 'info chardev' command. This output is structured, and contains both the name of the device and the path on the same line. This is considerably more reliable than parsing the startup log output, which requires the parsing code to know which order QEMU will print pty information in. Note that we still need to parse the log output as the monitor itself may be on a pty. This should be rare, however, and the new code will replace all pty paths parsed by the log output method once the monitor is available. * src/qemu/qemu_monitor.(c|h) src/qemu_monitor_text.(c|h): Implement qemuMonitorGetPtyPaths(). * src/qemu/qemu_driver.c: Get pty path information using qemuMonitorGetPtyPaths(). --- src/qemu/qemu_driver.c | 68 +++++++++++++++++++++++++++++++++++++++- src/qemu/qemu_monitor.c | 9 +++++ src/qemu/qemu_monitor.h | 3 ++ src/qemu/qemu_monitor_text.c | 71 ++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_text.h | 4 ++ 5 files changed, 153 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index c1feb0f..6f1fc1a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1407,6 +1407,40 @@ qemudExtractTTYPath(virConnectPtr conn, } static int +qemudFindCharDevicePTYsMonitor(virConnectPtr conn, + virDomainObjPtr vm, + virHashTablePtr paths) +{ + int i; + +#define LOOKUP_PTYS(array, arraylen, idprefix) \ + for (i = 0 ; i < (arraylen) ; i++) { \ + virDomainChrDefPtr chr = (array)[i]; \ + if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) { \ + char id[16]; \ +\ + if (snprintf(id, sizeof(id), idprefix "%i", i) >= sizeof(id)) \ + return -1; \ +\ + const char *path = (const char *) virHashLookup(paths, id); \ + if (path == NULL) { \ + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, \ + _("no assigned pty for device %s"), id); \ + return -1; \ + } \ +\ + chr->data.file.path = strdup(path); \ + } \ + } + + LOOKUP_PTYS(vm->def->serials, vm->def->nserials, "serial"); + LOOKUP_PTYS(vm->def->parallels, vm->def->nparallels, "parallel"); + LOOKUP_PTYS(vm->def->channels, vm->def->nchannels, "channel"); + + return 0; +} + +static int qemudFindCharDevicePTYs(virConnectPtr conn, virDomainObjPtr vm, const char *output, @@ -1452,6 +1486,11 @@ qemudFindCharDevicePTYs(virConnectPtr conn, return 0; } +static void qemudFreePtyPath(void *payload, const char *name ATTRIBUTE_UNUSED) +{ + free(payload); +} + static int qemudWaitForMonitor(virConnectPtr conn, struct qemud_driver* driver, @@ -1459,7 +1498,7 @@ qemudWaitForMonitor(virConnectPtr conn, { char buf[4096]; /* Plenty of space to get startup greeting */ int logfd; - int ret; + int ret = -1; if ((logfd = qemudLogReadFD(conn, driver->logDir, vm->def->name, pos)) < 0) @@ -1485,7 +1524,32 @@ qemudWaitForMonitor(virConnectPtr conn, if (qemuConnectMonitor(vm) < 0) return -1; - return 0; + /* Try to get the pty path mappings again via the monitor. This is much more + * reliable if it's available. + * Note that the monitor itself can be on a pty, so we still need to try the + * log output method. */ + virHashTablePtr paths = virHashCreate(0); + if (paths == NULL) { + virReportOOMError(NULL); + goto cleanup; + } + + qemuDomainObjEnterMonitor(vm); + qemuDomainObjPrivatePtr priv = vm->privateData; + ret = qemuMonitorGetPtyPaths(priv->mon, paths); + qemuDomainObjExitMonitor(vm); + + VIR_DEBUG("qemuMonitorGetPtyPaths returned %i", ret); + if (ret == 0) { + ret = qemudFindCharDevicePTYsMonitor(conn, vm, paths); + } + +cleanup: + if (paths) { + virHashFree(paths, qemudFreePtyPath); + } + + return ret; } static int diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 103cf28..750e3e6 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -1267,3 +1267,12 @@ int qemuMonitorRemoveHostNetwork(qemuMonitorPtr mon, ret = qemuMonitorTextRemoveHostNetwork(mon, vlan, netname); return ret; } + +int qemuMonitorGetPtyPaths(qemuMonitorPtr mon, + virHashTablePtr paths) +{ + DEBUG("mon=%p, fd=%d", + mon, mon->fd); + + return qemuMonitorTextGetPtyPaths(mon, paths); +} diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 8b1e3a3..db00b26 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -28,6 +28,7 @@ #include "internal.h" #include "domain_conf.h" +#include "hash.h" typedef struct _qemuMonitor qemuMonitor; typedef qemuMonitor *qemuMonitorPtr; @@ -272,5 +273,7 @@ int qemuMonitorRemoveHostNetwork(qemuMonitorPtr mon, int vlan, const char *netname); +int qemuMonitorGetPtyPaths(qemuMonitorPtr mon, + virHashTablePtr paths); #endif /* QEMU_MONITOR_H */ diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 72cb2bb..3ed45ba 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -1594,3 +1594,74 @@ cleanup: VIR_FREE(reply); return ret; } + + +/* Parse the output of "info chardev" and return a hash of pty paths. + * + * Output is: + * foo: filename=pty:/dev/pts/7 + * monitor: filename=stdio + * serial0: filename=vc + * parallel0: filename=vc + * + * Non-pty lines are ignored. In the above example, key is 'foo', value is + * '/dev/pty/7'. The hash will contain only a single value. + */ + +int qemuMonitorTextGetPtyPaths(qemuMonitorPtr mon, + virHashTablePtr paths) +{ + const char *cmd = "info chardev"; + char *reply = NULL; + int ret = -1; + + if (qemuMonitorCommand(mon, cmd, &reply) < 0) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + _("failed to retrieve chardev info in qemu with '%s'"), + cmd); + goto cleanup; + } + + char *pos = reply; /* The current start of searching */ + char *end = pos + strlen(reply); /* The end of the reply string */ + char *eol; /* The character which ends the current line */ + + while (pos < end) { + /* Split the output into lines */ + eol = memchr(pos, '\n', end - pos); + if (eol == NULL) + eol = end; + + /* Look for 'filename=pty:' */ +#define NEEDLE "filename=pty:" + char *needle = memmem(pos, eol - pos, NEEDLE, strlen(NEEDLE)); + + /* If it's not there we can ignore this line */ + if (!needle) + goto next; + + /* id is everthing from the beginning of the line to the ':' + * find ':' and turn it into a terminator */ + char *colon = memchr(pos, ':', needle - pos); + if (colon == NULL) + goto next; + *colon = '\0'; + char *id = pos; + + /* Path is everything after needle to the end of the line */ + *eol = '\0'; + char *path = needle + strlen(NEEDLE); + + virHashAddEntry(paths, id, strdup(path)); +#undef NEEDLE + + next: + pos = eol + 1; + } + + ret = 0; + +cleanup: + VIR_FREE(reply); + return ret; +} diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index bc52ad2..519edf4 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -28,6 +28,7 @@ #include "internal.h" #include "qemu_monitor.h" +#include "hash.h" int qemuMonitorTextIOProcess(qemuMonitorPtr mon, const char *data, @@ -153,4 +154,7 @@ int qemuMonitorTextRemoveHostNetwork(qemuMonitorPtr mon, int vlan, const char *netname); +int qemuMonitorTextGetPtyPaths(qemuMonitorPtr mon, + virHashTablePtr paths); + #endif /* QEMU_MONITOR_TEXT_H */ -- 1.6.5.2

On Thu, Dec 10, 2009 at 01:41:39PM +0000, Matthew Booth wrote:
This change makes the QEMU driver get pty paths from the output of the monitor 'info chardev' command. This output is structured, and contains both the name of the device and the path on the same line. This is considerably more reliable than parsing the startup log output, which requires the parsing code to know which order QEMU will print pty information in.
Note that we still need to parse the log output as the monitor itself may be on a pty. This should be rare, however, and the new code will replace all pty paths parsed by the log output method once the monitor is available.
* src/qemu/qemu_monitor.(c|h) src/qemu_monitor_text.(c|h): Implement qemuMonitorGetPtyPaths(). * src/qemu/qemu_driver.c: Get pty path information using qemuMonitorGetPtyPaths().
Okay, I have pushed the 3 patches, code looks fine, and lot of regression tests ! I just changed that last patch to reformat the macro and replaced a free() into VIR_FREE() ... IIRC those were pointed by danpb in his last review. thanks ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/
participants (2)
-
Daniel Veillard
-
Matthew Booth