[libvirt] [PATCH] Add support for multiple serial ports into the Xen driver

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); -- 1.7.3.2

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); -- 1.7.3.2

Oh, I forgot to mention that although this has been originally written and tested on RHEL-5 Xen dom0 and RHEL version of libvirt, this patch is for upstream (forward-ported from RHEL-5 version) so it was well applicable to the latest upstream libvirt sources at the time of creation. 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

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

On 02/16/2011 08:19 AM, Michal Novotny wrote:
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.
Sorry for dropping the ball on reviewing this one. Now I'm afraid that we're too close to 0.8.8 to include this without risking breaking something else, so if you don't mind waiting another day or so before we apply it... At any rate, I saw that round 1 of your patch had reviews, and didn't notice that this was a v2 patch. At first glance, you addressed the comments from round 1, including adding a test case:
.../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(-)
...so that speaks in favor of this already.
+++ 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;
This should be goto no_memory.
} 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");
Why the spurious whitespace change?
@@ -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, "))"); + }
You skipped "none" as a placeholder when parsing; but I'm not sure if this generates "none" on output to match.
+ } + } + /* If domain is not using multiple serial ports we parse data old way */ + else {
Style-wise, I would have written: } else { /* If domain is not using multiple... */ rather than injecting the comment between } and else.
@@ -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 {
Style - } and else should be on same line.
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))))
Can we add a second test that uses (serial (none /dev/ttyS1)) to prove that we handle placeholders correctly?
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
Independent of your patch, but now that we have support for backslash-newlines in the testsuite, we probably ought to convert all of the .sexpr files to take advantage of it. Can you post a v3 that addresses the first few concerns (don't worry about the .sexpr \-\n conversions for now)? -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

Eric, thanks for reply but I'm having some issues now... I've pulled libvirt sources from upstream and I'm unable to compile it since it keeps saying following: CCLD libvirt_parthelper ./.libs/libvirt_util.a(libvirt_util_la-util.o): In function `virFileOperationNoFork': /home/mig/Work/virt-related/libvirt/src/util/util.c:1363: undefined reference to `rpl_open' ./.libs/libvirt_util.a(libvirt_util_la-util.o): In function `virFileReadAll': /home/mig/Work/virt-related/libvirt/src/util/util.c:1159: undefined reference to `rpl_open' ./.libs/libvirt_util.a(libvirt_util_la-util.o): In function `virFileWriteStr': /home/mig/Work/virt-related/libvirt/src/util/util.c:1184: undefined reference to `rpl_open' /home/mig/Work/virt-related/libvirt/src/util/util.c:1186: undefined reference to `rpl_open' ./.libs/libvirt_util.a(libvirt_util_la-util.o): In function `virFileOperation': /home/mig/Work/virt-related/libvirt/src/util/util.c:1519: undefined reference to `rpl_open' ./.libs/libvirt_util.a(libvirt_util_la-util.o):/home/mig/Work/virt-related/libvirt/src/util/util.c:1795: more undefined references to `rpl_open' follow collect2: ld returned 1 exit status Unfortunately I was unable to find definition of 'rpl_open' function using git grep so I don't really know what to do there. Some bug or do I miss something?
+++ 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; This should be goto no_memory.
To my knowledge this is not the only one issue there since this has been changed from def->data.file.path to def->source.data.file.path to compile successfully but that's fine. It seems like codebase changed so it took some time to rewrite the code for the current upstream codebase.
@@ -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, "))"); + } You skipped "none" as a placeholder when parsing; but I'm not sure if this generates "none" on output to match.
Basically I don't know what you mean by this. Also, when I was defining XMLs I saw that the console node copies the first serial node however how to define it if first serial node is just none? I mean the XML is like: <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> But what should the XML part be for case of first serial device to be none ? Michal -- Michal Novotny<minovotn@redhat.com>, RHCE Virtualization Team (xen userspace), Red Hat

On 02/17/2011 02:37 AM, Michal Novotny wrote:
Eric, thanks for reply but I'm having some issues now...
I've pulled libvirt sources from upstream and I'm unable to compile it since it keeps saying following:
CCLD libvirt_parthelper ./.libs/libvirt_util.a(libvirt_util_la-util.o): In function `virFileOperationNoFork': /home/mig/Work/virt-related/libvirt/src/util/util.c:1363: undefined reference to `rpl_open'
Huh. rpl_open is a gnulib replacement for open(); I'm not sure why gnulib thinks open() needs replacing on Linux (unless it is trying to provide O_CLOEXEC support for older kernels). Was this an incremental build, where you had already built before updating to the latest libvirt.git, and just typed 'make'? Can you try 'rm gnulib/lib/fcntl.h', then 'make', to see if it clears up the issue? If it doesn't, then maybe you'll have to resort to a full-blown clean checkout.
Unfortunately I was unable to find definition of 'rpl_open' function using git grep so I don't really know what to do there. Some bug or do I miss something?
It's defined by gnulib, which is copied into place from the gnulib.git submodule during ./autogen.sh (and not under libvirt.git's control). Even then, it only exists in the replacement <fcntl.h> header provided by gnulib when gnulib thinks that open() isn't up to snuff with POSIX requirements.
Basically I don't know what you mean by this. Also, when I was defining XMLs I saw that the console node copies the first serial node however how to define it if first serial node is just none?
I mean the XML is like:
<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>
But what should the XML part be for case of first serial device to be none ?
I think the key is the <target port='1'/>. You don't need any placeholder in the XML for a missing port 0, but you do need it in the xm format where port is implied by position. That is: <devices> <serial type='dev'> <source path='/dev/ttyS1'/> <target port='1'/> </serial> </devices> should be sufficient XML to mark that you want to use multi-serial xen support, and that you are explicitly leaving virtual port 0 unoccupied and plugging in your one serial device into virtual port 1; mapping to: serial = [ "none", "/dev/ttyS1" ] in the xm file. The sexpr rationale should be the same. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 02/17/2011 08:58 PM, Eric Blake wrote:
Eric, thanks for reply but I'm having some issues now...
I've pulled libvirt sources from upstream and I'm unable to compile it since it keeps saying following:
CCLD libvirt_parthelper ./.libs/libvirt_util.a(libvirt_util_la-util.o): In function `virFileOperationNoFork': /home/mig/Work/virt-related/libvirt/src/util/util.c:1363: undefined reference to `rpl_open' Huh. rpl_open is a gnulib replacement for open(); I'm not sure why gnulib thinks open() needs replacing on Linux (unless it is trying to
On 02/17/2011 02:37 AM, Michal Novotny wrote: provide O_CLOEXEC support for older kernels). Was this an incremental build, where you had already built before updating to the latest libvirt.git, and just typed 'make'?
Can you try 'rm gnulib/lib/fcntl.h', then 'make', to see if it clears up the issue? If it doesn't, then maybe you'll have to resort to a full-blown clean checkout.
I have already solved this one by `make maintainer-clean` which cloned the gnulib again.
Unfortunately I was unable to find definition of 'rpl_open' function using git grep so I don't really know what to do there. Some bug or do I miss something? It's defined by gnulib, which is copied into place from the gnulib.git submodule during ./autogen.sh (and not under libvirt.git's control). Even then, it only exists in the replacement<fcntl.h> header provided by gnulib when gnulib thinks that open() isn't up to snuff with POSIX requirements.
OK
Basically I don't know what you mean by this. Also, when I was defining XMLs I saw that the console node copies the first serial node however how to define it if first serial node is just none?
I mean the XML is like:
<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>
But what should the XML part be for case of first serial device to be none ? I think the key is the<target port='1'/>. You don't need any placeholder in the XML for a missing port 0, but you do need it in the xm format where port is implied by position. That is:
<devices> <serial type='dev'> <source path='/dev/ttyS1'/> <target port='1'/> </serial> </devices>
should be sufficient XML to mark that you want to use multi-serial xen support, and that you are explicitly leaving virtual port 0 unoccupied and plugging in your one serial device into virtual port 1; mapping to:
serial = [ "none", "/dev/ttyS1" ]
in the xm file. The sexpr rationale should be the same.
Ah, ok, sounds good. Thanks! Michal -- Michal Novotny<minovotn@redhat.com>, RHCE Virtualization Team (xen userspace), Red Hat
participants (2)
-
Eric Blake
-
Michal Novotny