Ping ... could somebody review this one please? Thanks, Michal On 01/22/2011 05:49 PM, Michal Novotny wrote:
Hi, this is the patch to add support for multiple serial ports to the libvirt Xen driver. It support both old style (serial = "pty") and new style (serial = [ "/dev/ttyS0", "/dev/ttyS1" ]) definition and tests for xml2sexpr, sexpr2xml and xmconfig have been added as well.
Written and tested on RHEL-5 Xen dom0 and working as designed but the Xen version have to have patch for RHBZ #614004.
Also, this patch is addressing issue described in RHBZ #670789.
Michal
Signed-off-by: Michal Novotny<minovotn@redhat.com> --- src/xen/xend_internal.c | 73 ++++++++++- src/xen/xm_internal.c | 141 +++++++++++++++++--- .../sexpr2xml-fv-serial-dev-2-ports.sexpr | 1 + .../sexpr2xml-fv-serial-dev-2-ports.xml | 53 ++++++++ tests/sexpr2xmltest.c | 1 + .../test-fullvirt-serial-dev-2-ports.cfg | 25 ++++ .../test-fullvirt-serial-dev-2-ports.xml | 55 ++++++++ tests/xmconfigtest.c | 1 + .../xml2sexpr-fv-serial-dev-2-ports.sexpr | 1 + .../xml2sexpr-fv-serial-dev-2-ports.xml | 44 ++++++ tests/xml2sexprtest.c | 1 + 11 files changed, 370 insertions(+), 26 deletions(-) create mode 100644 tests/sexpr2xmldata/sexpr2xml-fv-serial-dev-2-ports.sexpr create mode 100644 tests/sexpr2xmldata/sexpr2xml-fv-serial-dev-2-ports.xml create mode 100644 tests/xmconfigdata/test-fullvirt-serial-dev-2-ports.cfg create mode 100644 tests/xmconfigdata/test-fullvirt-serial-dev-2-ports.xml create mode 100644 tests/xml2sexprdata/xml2sexpr-fv-serial-dev-2-ports.sexpr create mode 100644 tests/xml2sexprdata/xml2sexpr-fv-serial-dev-2-ports.xml
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index 44d5a22..493736e 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -1218,6 +1218,9 @@ xenDaemonParseSxprChar(const char *value,
if (value[0] == '/') { def->source.type = VIR_DOMAIN_CHR_TYPE_DEV; + def->data.file.path = strdup(value); + if (!def->data.file.path) + goto error; } else { if ((tmp = strchr(value, ':')) != NULL) { *tmp = '\0'; @@ -2334,6 +2337,8 @@ xenDaemonParseSxpr(virConnectPtr conn, tty = xenStoreDomainGetConsolePath(conn, def->id); xenUnifiedUnlock(priv); if (hvm) { + + tmp = sexpr_node(root, "domain/image/hvm/serial"); if (tmp&& STRNEQ(tmp, "none")) { virDomainChrDefPtr chr; @@ -2346,6 +2351,54 @@ xenDaemonParseSxpr(virConnectPtr conn, chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL; def->serials[def->nserials++] = chr; } + + + const struct sexpr *serial_root; + bool have_multiple_serials = false; + + serial_root = sexpr_lookup(root, "domain/image/hvm/serial"); + if (serial_root) { + const struct sexpr *cur, *node, *cur2; + + for (cur = serial_root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) { + node = cur->u.s.car; + + for (cur2 = node; cur2->kind == SEXPR_CONS; cur2 = cur2->u.s.cdr) { + tmp = cur2->u.s.car->u.value; + + if (tmp&& STRNEQ(tmp, "none")) { + virDomainChrDefPtr chr; + if ((chr = xenDaemonParseSxprChar(tmp, tty)) == NULL) + goto error; + if (VIR_REALLOC_N(def->serials, def->nserials+1)< 0) { + virDomainChrDefFree(chr); + goto no_memory; + } + chr->targetType = VIR_DOMAIN_CHR_TARGET_TYPE_SERIAL; + chr->target.port = def->nserials; + def->serials[def->nserials++] = chr; + } + have_multiple_serials = true; + } + } + } + + /* If no serial port has been defined (using the new-style definition) use the old way */ + if (!have_multiple_serials) { + tmp = sexpr_node(root, "domain/image/hvm/serial"); + if (tmp&& STRNEQ(tmp, "none")) { + virDomainChrDefPtr chr; + if ((chr = xenDaemonParseSxprChar(tmp, tty)) == NULL) + goto error; + if (VIR_REALLOC_N(def->serials, def->nserials+1)< 0) { + virDomainChrDefFree(chr); + goto no_memory; + } + chr->targetType = VIR_DOMAIN_CHR_TARGET_TYPE_SERIAL; + def->serials[def->nserials++] = chr; + } + } + tmp = sexpr_node(root, "domain/image/hvm/parallel"); if (tmp&& STRNEQ(tmp, "none")) { virDomainChrDefPtr chr; @@ -5958,10 +6011,22 @@ xenDaemonFormatSxpr(virConnectPtr conn, virBufferAddLit(&buf, "(parallel none)"); } if (def->serials) { - virBufferAddLit(&buf, "(serial "); - if (xenDaemonFormatSxprChr(def->serials[0],&buf)< 0) - goto error; - virBufferAddLit(&buf, ")"); + if (def->nserials> 1) { + virBufferAddLit(&buf, "(serial ("); + for (i = 0; i< def->nserials; i++) { + if (xenDaemonFormatSxprChr(def->serials[i],&buf)< 0) + goto error; + if (i< def->nserials - 1) + virBufferAddLit(&buf, " "); + } + virBufferAddLit(&buf, "))"); + } + else { + virBufferAddLit(&buf, "(serial "); + if (xenDaemonFormatSxprChr(def->serials[0],&buf)< 0) + goto error; + virBufferAddLit(&buf, ")"); + } } else { virBufferAddLit(&buf, "(serial none)"); } diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index bfb6698..f457d80 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -1432,20 +1432,54 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) { chr = NULL; }
- if (xenXMConfigGetString(conf, "serial",&str, NULL)< 0) - goto cleanup; - if (str&& STRNEQ(str, "none")&& - !(chr = xenDaemonParseSxprChar(str, NULL))) - goto cleanup; + /* Try to get the list of values to support multiple serial ports */ + list = virConfGetValue(conf, "serial"); + if (list&& list->type == VIR_CONF_LIST) { + list = list->list; + while (list) { + char *port; + + if ((list->type != VIR_CONF_STRING) || (list->str == NULL)) { + xenXMError(VIR_ERR_INTERNAL_ERROR, + _("config value %s was malformed"), port); + goto cleanup; + }
- if (chr) { - if (VIR_ALLOC_N(def->serials, 1)< 0) { - virDomainChrDefFree(chr); - goto no_memory; + port = list->str; + if (VIR_ALLOC(chr)< 0) + goto no_memory; + if (!(chr = xenDaemonParseSxprChar(port, NULL))) + goto cleanup; + + if (VIR_REALLOC_N(def->serials, def->nserials+1)< 0) + goto no_memory; + + chr->targetType = VIR_DOMAIN_CHR_TARGET_TYPE_SERIAL; + chr->target.port = def->nserials; + + def->serials[def->nserials++] = chr; + chr = NULL; + + list = list->next; + } + } + /* If domain is not using multiple serial ports we parse data old way */ + else { + if (xenXMConfigGetString(conf, "serial",&str, NULL)< 0) + goto cleanup; + if (str&& STRNEQ(str, "none")&& + !(chr = xenDaemonParseSxprChar(str, NULL))) + goto cleanup; + + if (chr) { + if (VIR_ALLOC_N(def->serials, 1)< 0) { + virDomainChrDefFree(chr); + goto no_memory; + } + chr->targetType = VIR_DOMAIN_CHR_TARGET_TYPE_SERIAL; + def->serials[0] = chr; + def->nserials++; } - chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL; - def->serials[0] = chr; - def->nserials++; } } else { if (!(def->console = xenDaemonParseSxprChar("pty", NULL))) @@ -2123,6 +2157,45 @@ cleanup: return -1; }
+static int xenXMDomainConfigFormatSerial(virConfValuePtr list, + virDomainChrDefPtr serial) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + virConfValuePtr val, tmp; + int ret; + + ret = xenDaemonFormatSxprChr(serial,&buf); + if (ret< 0) { + virReportOOMError(); + goto cleanup; + } + if (virBufferError(&buf)) { + virReportOOMError(); + goto cleanup; + } + + if (VIR_ALLOC(val)< 0) { + virReportOOMError(); + goto cleanup; + } + + val->type = VIR_CONF_STRING; + val->str = virBufferContentAndReset(&buf); + tmp = list->list; + while (tmp&& tmp->next) + tmp = tmp->next; + if (tmp) + tmp->next = val; + else + list->list = val; + + return 0; + +cleanup: + virBufferFreeAndReset(&buf); + return -1; +} + static int xenXMDomainConfigFormatNet(virConnectPtr conn, virConfValuePtr list, virDomainNetDefPtr net, @@ -2685,17 +2758,41 @@ virConfPtr xenXMDomainConfigFormat(virConnectPtr conn, }
if (def->nserials) { - virBuffer buf = VIR_BUFFER_INITIALIZER; - char *str; - int ret; + /* If there's a single serial port definition use the old approach not to break old configs */ + if (def->nserials == 1) { + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *str; + int ret; + + ret = xenDaemonFormatSxprChr(def->serials[0],&buf); + str = virBufferContentAndReset(&buf); + if (ret == 0) + ret = xenXMConfigSetString(conf, "serial", str); + VIR_FREE(str); + if (ret< 0) + goto no_memory; + } + else { + virConfValuePtr serialVal = NULL;
- ret = xenDaemonFormatSxprChr(def->serials[0],&buf); - str = virBufferContentAndReset(&buf); - if (ret == 0) - ret = xenXMConfigSetString(conf, "serial", str); - VIR_FREE(str); - if (ret< 0) - goto no_memory; + if (VIR_ALLOC(serialVal)< 0) + goto no_memory; + serialVal->type = VIR_CONF_LIST; + serialVal->list = NULL; + + for (i = 0; i< def->nserials; i++) { + if (xenXMDomainConfigFormatSerial(serialVal, def->serials[i])< 0) + goto cleanup; + } + + if (serialVal->list != NULL) { + int ret = virConfSetValue(conf, "serial", serialVal); + serialVal = NULL; + if (ret< 0) + goto no_memory; + } + VIR_FREE(serialVal); + } } else { if (xenXMConfigSetString(conf, "serial", "none")< 0) goto no_memory; diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-serial-dev-2-ports.sexpr b/tests/sexpr2xmldata/sexpr2xml-fv-serial-dev-2-ports.sexpr new file mode 100644 index 0000000..e709eb0 --- /dev/null +++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-dev-2-ports.sexpr @@ -0,0 +1 @@ +(domain (domid 1)(name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8ff')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial (/dev/ttyS0 /dev/ttyS1))(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-serial-dev-2-ports.xml b/tests/sexpr2xmldata/sexpr2xml-fv-serial-dev-2-ports.xml new file mode 100644 index 0000000..783cd67 --- /dev/null +++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-dev-2-ports.xml @@ -0,0 +1,53 @@ +<domain type='xen' id='1'> +<name>fvtest</name> +<uuid>b5d70dd2-75cd-aca5-1776-9660b059d8ff</uuid> +<memory>409600</memory> +<currentMemory>409600</currentMemory> +<vcpu>1</vcpu> +<os> +<type>hvm</type> +<loader>/usr/lib/xen/boot/hvmloader</loader> +<boot dev='hd'/> +</os> +<features> +<acpi/> +</features> +<clock offset='utc'/> +<on_poweroff>destroy</on_poweroff> +<on_reboot>restart</on_reboot> +<on_crash>restart</on_crash> +<devices> +<emulator>/usr/lib64/xen/bin/qemu-dm</emulator> +<disk type='file' device='disk'> +<driver name='file'/> +<source file='/root/foo.img'/> +<target dev='hda' bus='ide'/> +</disk> +<disk type='file' device='cdrom'> +<driver name='file'/> +<source file='/root/boot.iso'/> +<target dev='hdc' bus='ide'/> +<readonly/> +</disk> +<interface type='bridge'> +<mac address='00:16:3e:1b:b1:47'/> +<source bridge='xenbr0'/> +<script path='vif-bridge'/> +<target dev='vif1.0'/> +</interface> +<serial type='dev'> +<source path='/dev/ttyS0'/> +<target port='0'/> +</serial> +<serial type='dev'> +<source path='/dev/ttyS1'/> +<target port='1'/> +</serial> +<console type='dev'> +<source path='/dev/ttyS0'/> +<target port='0'/> +</console> +<input type='mouse' bus='ps2'/> +<graphics type='vnc' port='5901' autoport='no'/> +</devices> +</domain> diff --git a/tests/sexpr2xmltest.c b/tests/sexpr2xmltest.c index f100dd8..4b5766d 100644 --- a/tests/sexpr2xmltest.c +++ b/tests/sexpr2xmltest.c @@ -158,6 +158,7 @@ mymain(int argc, char **argv)
DO_TEST("fv-serial-null", "fv-serial-null", 1); DO_TEST("fv-serial-file", "fv-serial-file", 1); + DO_TEST("fv-serial-dev-2-ports", "fv-serial-dev-2-ports", 1); DO_TEST("fv-serial-stdio", "fv-serial-stdio", 1); DO_TEST("fv-serial-pty", "fv-serial-pty", 1); DO_TEST("fv-serial-pipe", "fv-serial-pipe", 1); diff --git a/tests/xmconfigdata/test-fullvirt-serial-dev-2-ports.cfg b/tests/xmconfigdata/test-fullvirt-serial-dev-2-ports.cfg new file mode 100644 index 0000000..86e7998 --- /dev/null +++ b/tests/xmconfigdata/test-fullvirt-serial-dev-2-ports.cfg @@ -0,0 +1,25 @@ +name = "XenGuest2" +uuid = "c7a5fdb2-cdaf-9455-926a-d65c16db1809" +maxmem = 579 +memory = 394 +vcpus = 1 +builder = "hvm" +kernel = "/usr/lib/xen/boot/hvmloader" +boot = "d" +pae = 1 +acpi = 1 +apic = 1 +localtime = 0 +on_poweroff = "destroy" +on_reboot = "restart" +on_crash = "restart" +device_model = "/usr/lib/xen/bin/qemu-dm" +sdl = 0 +vnc = 1 +vncunused = 1 +vnclisten = "127.0.0.1" +vncpasswd = "123poi" +disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso,hdc:cdrom,r" ] +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,script=vif-bridge,model=e1000,type=ioemu" ] +parallel = "none" +serial = [ "/dev/ttyS0", "/dev/ttyS1" ] diff --git a/tests/xmconfigdata/test-fullvirt-serial-dev-2-ports.xml b/tests/xmconfigdata/test-fullvirt-serial-dev-2-ports.xml new file mode 100644 index 0000000..e4d3f16 --- /dev/null +++ b/tests/xmconfigdata/test-fullvirt-serial-dev-2-ports.xml @@ -0,0 +1,55 @@ +<domain type='xen'> +<name>XenGuest2</name> +<uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> +<memory>592896</memory> +<currentMemory>403456</currentMemory> +<vcpu>1</vcpu> +<os> +<type arch='i686' machine='xenfv'>hvm</type> +<loader>/usr/lib/xen/boot/hvmloader</loader> +<boot dev='cdrom'/> +</os> +<features> +<acpi/> +<apic/> +<pae/> +</features> +<clock offset='utc'/> +<on_poweroff>destroy</on_poweroff> +<on_reboot>restart</on_reboot> +<on_crash>restart</on_crash> +<devices> +<emulator>/usr/lib/xen/bin/qemu-dm</emulator> +<disk type='block' device='disk'> +<driver name='phy'/> +<source dev='/dev/HostVG/XenGuest2'/> +<target dev='hda' bus='ide'/> +</disk> +<disk type='file' device='cdrom'> +<driver name='file'/> +<source file='/root/boot.iso'/> +<target dev='hdc' bus='ide'/> +<readonly/> +</disk> +<interface type='bridge'> +<mac address='00:16:3e:66:92:9c'/> +<source bridge='xenbr1'/> +<script path='vif-bridge'/> +<model type='e1000'/> +</interface> +<serial type='dev'> +<source path='/dev/ttyS0'/> +<target port='0'/> +</serial> +<serial type='dev'> +<source path='/dev/ttyS1'/> +<target port='1'/> +</serial> +<console type='dev'> +<source path='/dev/ttyS0'/> +<target port='0'/> +</console> +<input type='mouse' bus='ps2'/> +<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> +</devices> +</domain> diff --git a/tests/xmconfigtest.c b/tests/xmconfigtest.c index ea00747..0de890c 100644 --- a/tests/xmconfigtest.c +++ b/tests/xmconfigtest.c @@ -218,6 +218,7 @@ mymain(int argc, char **argv) DO_TEST("fullvirt-usbtablet", 2); DO_TEST("fullvirt-usbmouse", 2); DO_TEST("fullvirt-serial-file", 2); + DO_TEST("fullvirt-serial-dev-2-ports", 2); DO_TEST("fullvirt-serial-null", 2); DO_TEST("fullvirt-serial-pipe", 2); DO_TEST("fullvirt-serial-pty", 2); diff --git a/tests/xml2sexprdata/xml2sexpr-fv-serial-dev-2-ports.sexpr b/tests/xml2sexprdata/xml2sexpr-fv-serial-dev-2-ports.sexpr new file mode 100644 index 0000000..2048159 --- /dev/null +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-dev-2-ports.sexpr @@ -0,0 +1 @@ +(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial (/dev/ttyS0 /dev/ttyS1))(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(model 'e1000')(type ioemu)))) \ No newline at end of file diff --git a/tests/xml2sexprdata/xml2sexpr-fv-serial-dev-2-ports.xml b/tests/xml2sexprdata/xml2sexpr-fv-serial-dev-2-ports.xml new file mode 100644 index 0000000..e5d1817 --- /dev/null +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-dev-2-ports.xml @@ -0,0 +1,44 @@ +<domain type='xen'> +<name>fvtest</name> +<uuid>b5d70dd275cdaca517769660b059d8bc</uuid> +<os> +<type>hvm</type> +<loader>/usr/lib/xen/boot/hvmloader</loader> +<boot dev='hd'/> +</os> +<memory>409600</memory> +<vcpu>1</vcpu> +<on_poweroff>destroy</on_poweroff> +<on_reboot>restart</on_reboot> +<on_crash>restart</on_crash> +<features> +<acpi/> +</features> +<devices> +<emulator>/usr/lib64/xen/bin/qemu-dm</emulator> +<interface type='bridge'> +<source bridge='xenbr0'/> +<mac address='00:16:3e:1b:b1:47'/> +<script path='vif-bridge'/> +<model type='e1000'/> +</interface> +<disk type='file' device='cdrom'> +<source file='/root/boot.iso'/> +<target dev='hdc'/> +<readonly/> +</disk> +<disk type='file'> +<source file='/root/foo.img'/> +<target dev='ioemu:hda'/> +</disk> +<serial type='dev'> +<source path='/dev/ttyS0'/> +<target port='0'/> +</serial> +<serial type='dev'> +<source path='/dev/ttyS1'/> +<target port='1'/> +</serial> +<graphics type='vnc' port='5917' keymap='ja'/> +</devices> +</domain> diff --git a/tests/xml2sexprtest.c b/tests/xml2sexprtest.c index 8a5d115..ed10dec 100644 --- a/tests/xml2sexprtest.c +++ b/tests/xml2sexprtest.c @@ -148,6 +148,7 @@ mymain(int argc, char **argv)
DO_TEST("fv-serial-null", "fv-serial-null", "fvtest", 1); DO_TEST("fv-serial-file", "fv-serial-file", "fvtest", 1); + DO_TEST("fv-serial-dev-2-ports", "fv-serial-dev-2-ports", "fvtest", 1); DO_TEST("fv-serial-stdio", "fv-serial-stdio", "fvtest", 1); DO_TEST("fv-serial-pty", "fv-serial-pty", "fvtest", 1); DO_TEST("fv-serial-pipe", "fv-serial-pipe", "fvtest", 1);
-- Michal Novotny<minovotn@redhat.com>, RHCE Virtualization Team (xen userspace), Red Hat