From 9a361bbba8c8d3ea3f1a1d56912851d509179fa9 Mon Sep 17 00:00:00 2001 From: Chunyan Liu Date: Wed, 15 Jun 2016 14:00:12 +0800 Subject: [PATCH] xenconfig: add conversion of usb controller config to and from xml libxl configuration files conversion can now handle USB controllers. When parting libxl config file, USB controllers with type PV are ignored as those aren't handled. Signed-off-by: Chunyan Liu --- src/xenconfig/xen_xl.c | 190 ++++++++++++++++++++++++++++ tests/xlconfigdata/test-usbctrl.cfg | 13 ++ tests/xlconfigdata/test-usbctrl.xml | 31 +++++ tests/xlconfigtest.c | 1 + 4 files changed, 235 insertions(+) create mode 100644 tests/xlconfigdata/test-usbctrl.cfg create mode 100644 tests/xlconfigdata/test-usbctrl.xml diff --git a/src/xenconfig/xen_xl.c b/src/xenconfig/xen_xl.c index 25a3621084..7774dfc009 100644 --- a/src/xenconfig/xen_xl.c +++ b/src/xenconfig/xen_xl.c @@ -502,6 +502,110 @@ xenParseXLInputDevs(virConfPtr conf, virDomainDefPtr def) return 0; } +static int +xenParseXLUSBController(virConfPtr conf, virDomainDefPtr def) +{ + virConfValuePtr list = virConfGetValue(conf, "usbctrl"); + virDomainControllerDefPtr controller = NULL; + + if (list && list->type == VIR_CONF_LIST) { + list = list->list; + while (list) { + char type[8]; + char version[4]; + char ports[4]; + char *key; + int usbctrl_version = 2; /* by default USB 2.0 */ + int usbctrl_ports = 8; /* by default 8 ports */ + int usbctrl_type = -1; + + type[0] = version[0] = ports[0] = '\0'; + + if ((list->type != VIR_CONF_STRING) || (list->str == NULL)) + goto skipusbctrl; + /* usbctrl=['type=pv,version=2,ports=8'] */ + key = list->str; + while (key) { + char *data; + char *nextkey = strchr(key, ','); + + if (!(data = strchr(key, '='))) + goto skipusbctrl; + data++; + + if (STRPREFIX(key, "type=")) { + int len = nextkey ? (nextkey - data) : sizeof(type) - 1; + if (virStrncpy(type, data, len, sizeof(type)) == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("type %s invalid"), + data); + goto skipusbctrl; + } + } else if (STRPREFIX(key, "version=")) { + int len = nextkey ? (nextkey - data) : sizeof(version) - 1; + if (virStrncpy(version, data, len, sizeof(version)) == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("version %s invalid"), + data); + goto skipusbctrl; + } + if (virStrToLong_i(version, NULL, 16, &usbctrl_version) < 0) + goto skipusbctrl; + } else if (STRPREFIX(key, "ports=")) { + int len = nextkey ? (nextkey - data) : sizeof(ports) - 1; + if (virStrncpy(ports, data, len, sizeof(ports)) == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("version %s invalid"), + data); + goto skipusbctrl; + } + if (virStrToLong_i(ports, NULL, 16, &usbctrl_ports) < 0) + goto skipusbctrl; + } + + while (nextkey && (nextkey[0] == ',' || + nextkey[0] == ' ' || + nextkey[0] == '\t')) + nextkey++; + key = nextkey; + } + + if (type[0] == '\0') { + if (usbctrl_version == 1) + usbctrl_type = VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB1; + else + usbctrl_type = VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB2; + } else { + if (STREQLEN(type, "qusb", 4)) { + if (usbctrl_version == 1) + usbctrl_type = VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB1; + else + usbctrl_type = VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB2; + } else { + goto skipusbctrl; + } + } + + if (!(controller = virDomainControllerDefNew(VIR_DOMAIN_CONTROLLER_TYPE_USB))) + return -1; + + controller->type = VIR_DOMAIN_CONTROLLER_TYPE_USB; + controller->model = usbctrl_type; + controller->opts.usbopts.ports = usbctrl_ports; + + if (VIR_APPEND_ELEMENT(def->controllers, def->ncontrollers, controller) < 0) { + virDomainControllerDefFree(controller); + return -1; + } + + skipusbctrl: + list = list->next; + } + } + + return 0; +} + static int xenParseXLUSB(virConfPtr conf, virDomainDefPtr def) { @@ -613,6 +717,9 @@ xenParseXL(virConfPtr conf, if (xenParseXLUSB(conf, def) < 0) goto cleanup; + if (xenParseXLUSBController(conf, def) < 0) + goto cleanup; + if (virDomainDefPostParse(def, caps, VIR_DOMAIN_DEF_PARSE_ABI_UPDATE, xmlopt) < 0) goto cleanup; @@ -1093,6 +1200,86 @@ xenFormatXLInputDevs(virConfPtr conf, virDomainDefPtr def) return -1; } +static int +xenFormatXLUSBController(virConfPtr conf, + virDomainDefPtr def) +{ + virConfValuePtr usbctrlVal = NULL; + int hasUSBCtrl = 0; + size_t i; + + for (i = 0; i < def->ncontrollers; i++) { + if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB) { + hasUSBCtrl = 1; + break; + } + } + + if (!hasUSBCtrl) + return 0; + + if (VIR_ALLOC(usbctrlVal) < 0) + return -1; + + usbctrlVal->type = VIR_CONF_LIST; + usbctrlVal->list = NULL; + + for (i = 0; i < def->ncontrollers; i++) { + if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB) { + virConfValuePtr val, tmp; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (def->controllers[i]->model != -1) { + switch (def->controllers[i]->model) { + case VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB1: + virBufferAddLit(&buf, "type=qusb,version=1,"); + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB2: + virBufferAddLit(&buf, "type=qusb,version=2,"); + break; + + default: + goto error; + } + } + + if (def->controllers[i]->opts.usbopts.ports != -1) + virBufferAsprintf(&buf, "ports=%x", + def->controllers[i]->opts.usbopts.ports); + + if (VIR_ALLOC(val) < 0) { + virBufferFreeAndReset(&buf); + goto error; + } + val->type = VIR_CONF_STRING; + val->str = virBufferContentAndReset(&buf); + tmp = usbctrlVal->list; + while (tmp && tmp->next) + tmp = tmp->next; + if (tmp) + tmp->next = val; + else + usbctrlVal->list = val; + } + } + + if (usbctrlVal->list != NULL) { + int ret = virConfSetValue(conf, "usbctrl", usbctrlVal); + usbctrlVal = NULL; + if (ret < 0) + return -1; + } + VIR_FREE(usbctrlVal); + + return 0; + + error: + virConfFreeValue(usbctrlVal); + return -1; +} + + static int xenFormatXLUSB(virConfPtr conf, virDomainDefPtr def) @@ -1186,6 +1373,9 @@ xenFormatXL(virDomainDefPtr def, virConnectPtr conn) if (xenFormatXLUSB(conf, def) < 0) goto cleanup; + if (xenFormatXLUSBController(conf, def) < 0) + goto cleanup; + return conf; cleanup: diff --git a/tests/xlconfigdata/test-usbctrl.cfg b/tests/xlconfigdata/test-usbctrl.cfg new file mode 100644 index 0000000000..91e9460b6b --- /dev/null +++ b/tests/xlconfigdata/test-usbctrl.cfg @@ -0,0 +1,13 @@ +name = "XenGuest1" +uuid = "45b60f51-88a9-47a8-a3b3-5e66d71b2283" +maxmem = 512 +memory = 512 +vcpus = 1 +localtime = 0 +on_poweroff = "preserve" +on_reboot = "restart" +on_crash = "preserve" +vif = [ "mac=5a:36:0e:be:00:09" ] +bootloader = "/usr/bin/pygrub" +disk = [ "format=qcow2,vdev=xvda,access=rw,backendtype=qdisk,target=/var/lib/xen/images/debian/disk.qcow2" ] +usbctrl = [ "type=qusb,version=2,ports=6" ] diff --git a/tests/xlconfigdata/test-usbctrl.xml b/tests/xlconfigdata/test-usbctrl.xml new file mode 100644 index 0000000000..3c03f37e79 --- /dev/null +++ b/tests/xlconfigdata/test-usbctrl.xml @@ -0,0 +1,31 @@ + + XenGuest1 + 45b60f51-88a9-47a8-a3b3-5e66d71b2283 + 524288 + 524288 + 1 + /usr/bin/pygrub + + linux + + + preserve + restart + preserve + + + + + + + + + + + + + + + + + diff --git a/tests/xlconfigtest.c b/tests/xlconfigtest.c index 4248da13e2..401e5607d1 100644 --- a/tests/xlconfigtest.c +++ b/tests/xlconfigtest.c @@ -278,6 +278,7 @@ mymain(void) #endif DO_TEST("vif-typename"); DO_TEST("usb"); + DO_TEST("usbctrl"); virObjectUnref(caps); virObjectUnref(xmlopt);