[libvirt] [PATCH 00/10] A bunch of extensions to libxl driver

This are some additional features to libxl driver. Some of them require change in domain config structures/syntax. Details described with each patch. Actually this is next iteration of a few years old patch series... Marek Marczykowski-Górecki (10): libxl: update dom->id in libxlDomainCreateWithFlags conf: support backend domain name in disk and network devices libxl: support backend domain setting for disk and net devices libxl: fill HVM SDL and VNC settings based on <graphics/> entries libxl: pass ipaddr to libxl toolstack libxl: add tablet/mouse input device support libxl: prevent attaching multiple netdevs with the same MAC libxl: support domain config modification in virDomainRestoreFlags libxl: stubdom emulator type tests: add some simple libxl XML->XML tests docs/formatdomain.html.in | 43 ++++- docs/schemas/domaincommon.rng | 43 ++++- src/conf/domain_conf.c | 69 +++++++- src/conf/domain_conf.h | 10 ++ src/libxl/libxl_conf.c | 194 ++++++++++++++++++--- src/libxl/libxl_domain.c | 11 ++ src/libxl/libxl_driver.c | 61 ++++++- src/util/virstoragefile.c | 4 +- src/util/virstoragefile.h | 1 + tests/Makefile.am | 9 +- tests/domainschematest | 2 +- tests/xlxml2xmldata/xlxml2xml-hvm-stubdom.xml | 41 +++++ tests/xlxml2xmldata/xlxml2xml-hvm.xml | 40 +++++ tests/xlxml2xmldata/xlxml2xml-network-bridged.xml | 38 ++++ .../xlxml2xml-network-driver-domain.xml | 38 ++++ tests/xlxml2xmldata/xlxml2xml-network-routed.xml | 39 +++++ tests/xlxml2xmldata/xlxml2xml-pv.xml | 38 ++++ tests/xlxml2xmltest.c | 189 ++++++++++++++++++++ 18 files changed, 824 insertions(+), 46 deletions(-) create mode 100644 tests/xlxml2xmldata/xlxml2xml-hvm-stubdom.xml create mode 100644 tests/xlxml2xmldata/xlxml2xml-hvm.xml create mode 100644 tests/xlxml2xmldata/xlxml2xml-network-bridged.xml create mode 100644 tests/xlxml2xmldata/xlxml2xml-network-driver-domain.xml create mode 100644 tests/xlxml2xmldata/xlxml2xml-network-routed.xml create mode 100644 tests/xlxml2xmldata/xlxml2xml-pv.xml create mode 100644 tests/xlxml2xmltest.c -- 1.8.3.1 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> To: libvirt-list@redhat.com Cc: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> Subject: [PATCH 01/10] libxl: update dom->id in libxlDomainCreateWithFlags Date: Thu, 5 Feb 2015 06:17:07 +0100 Message-Id: <1423113436-18213-2-git-send-email-marmarek@invisiblethingslab.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> References: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Organization: Invisible Things Lab Otherwise domainCreateWithFlags via remote returns -1 as domid. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_driver.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index c95b387..ce3a99b 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2375,6 +2375,9 @@ libxlDomainCreateWithFlags(virDomainPtr dom, } ret = libxlDomainStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1); + if (ret < 0) + goto cleanup; + dom->id = vm->def->id; cleanup: if (vm) -- 1.8.3.1 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> To: libvirt-list@redhat.com Cc: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> Subject: [PATCH 02/10] conf: support backend domain name in disk and network devices Date: Thu, 5 Feb 2015 06:17:08 +0100 Message-Id: <1423113436-18213-3-git-send-email-marmarek@invisiblethingslab.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> References: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Organization: Invisible Things Lab At least Xen supports backend drivers in another domain (aka "driver domain"). This patch introduces XML config option for such setting as 'domain' attribute of 'source' element. Verification its content is left for the driver. In the future same option will be needed for USB devices (hostdev objects), but for now libxl doesn't have support for PVUSB. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - describe in docs/formatdomain.html.in - enforce empty domain tag (only 'name' attribute allowed) Changes in v3: - change <domain name='xx'/> element to domain='' attribute of source element - this is more logical place - grammar of docs docs/formatdomain.html.in | 29 +++++++++++++++++++++++++++-- docs/schemas/domaincommon.rng | 20 ++++++++++++++++++++ src/conf/domain_conf.c | 33 +++++++++++++++++++++++++++++---- src/conf/domain_conf.h | 1 + src/util/virstoragefile.c | 4 +++- src/util/virstoragefile.h | 1 + 6 files changed, 81 insertions(+), 7 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index c5ad6f4..38c42d5 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1907,13 +1907,17 @@ <span class="since">since 0.0.3</span></dt> <dd> The <code>file</code> attribute specifies the fully-qualified - path to the file holding the disk. + path to the file holding the disk. The optional + <code>domain</code> attribute allows specifying a backend domain + (aka driver domain) where the file is stored. </dd> <dt><code>type='block'</code> <span class="since">since 0.0.3</span></dt> <dd> The <code>dev</code> attribute specifies the path to the - host device to serve as the disk. + host device to serve as the disk. The optional + <code>domain</code> attribute allows specifying a backend domain + (aka driver domain) for the device. </dd> <dt><code>type='dir'</code> <span class="since">since 0.7.5</span></dt> @@ -4336,6 +4340,27 @@ qemu-kvm -net nic,model=? /dev/null element is unspecified is to have the link state <code>up</code>. <span class="since">Since 0.9.5</span> </p> + <h5><a name="elementDomain">Setting up a network backend in a driver domain</a></h5> +<pre> + ... + <devices> + ... + <interface type='bridge'> + <source bridge='br0' <b>domain='netvm'</b>/> + </interface> + ... + </devices> + ...</pre> + + <p> + The optional <code>domain</code> attribute allows specifying a backend + domain (aka driver domain) for the device. Use the <code>name</code> attribute + to specify its name. You can use it to create a direct network link between + domains (so data will not go through host system). Use with type 'ethernet' + to create plain network link, or with 'bridge' to connect to some bridge + inside the driver domain. + <span class="since">Since 1.0.7 (Xen only)</span> + </p> <h5><a name="ipconfig">IP configuration</a></h5> <pre> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index d467dce..a4321f1 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1340,6 +1340,11 @@ <attribute name="file"> <ref name="absFilePath"/> </attribute> + <optional> + <attribute name="domain"> + <ref name="domainName"/> + </attribute> + </optional> </optional> <optional> <ref name="storageStartupPolicy"/> @@ -1365,6 +1370,11 @@ </attribute> </optional> <optional> + <attribute name="domain"> + <ref name="domainName"/> + </attribute> + </optional> + <optional> <ref name="storageStartupPolicy"/> </optional> <optional> @@ -2040,6 +2050,11 @@ <attribute name="bridge"> <ref name="deviceName"/> </attribute> + <optional> + <attribute name="domain"> + <ref name="domainName"/> + </attribute> + </optional> <empty/> </element> </optional> @@ -2059,6 +2074,11 @@ <attribute name="dev"> <ref name="deviceName"/> </attribute> + <optional> + <attribute name="domain"> + <ref name="domainName"/> + </attribute> + </optional> <empty/> </element> </optional> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 4251b13..17b699a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1442,6 +1442,7 @@ void virDomainNetDefFree(virDomainNetDefPtr def) VIR_FREE(def->backend.vhost); VIR_FREE(def->virtPortProfile); VIR_FREE(def->script); + VIR_FREE(def->domain_name); VIR_FREE(def->ifname); VIR_FREE(def->ifname_guest); VIR_FREE(def->ifname_guest_actual); @@ -5520,9 +5521,11 @@ virDomainDiskSourceParse(xmlNodePtr node, switch ((virStorageType)src->type) { case VIR_STORAGE_TYPE_FILE: src->path = virXMLPropString(node, "file"); + src->domain_name = virXMLPropString(node, "domain"); break; case VIR_STORAGE_TYPE_BLOCK: src->path = virXMLPropString(node, "dev"); + src->domain_name = virXMLPropString(node, "domain"); break; case VIR_STORAGE_TYPE_DIR: src->path = virXMLPropString(node, "dir"); @@ -7369,6 +7372,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, char *vhostuser_path = NULL; char *vhostuser_type = NULL; char *trustGuestRxFilters = NULL; + char *domain_name = NULL; virNWFilterHashTablePtr filterparams = NULL; virDomainActualNetDefPtr actual = NULL; xmlNodePtr oldnode = ctxt->node; @@ -7423,12 +7427,14 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, def->type == VIR_DOMAIN_NET_TYPE_BRIDGE && xmlStrEqual(cur->name, BAD_CAST "source")) { bridge = virXMLPropString(cur, "bridge"); + domain_name = virXMLPropString(cur, "domain"); } else if (!dev && (def->type == VIR_DOMAIN_NET_TYPE_ETHERNET || def->type == VIR_DOMAIN_NET_TYPE_DIRECT) && xmlStrEqual(cur->name, BAD_CAST "source")) { dev = virXMLPropString(cur, "dev"); mode = virXMLPropString(cur, "mode"); + domain_name = virXMLPropString(cur, "domain"); } else if (!vhostuser_path && !vhostuser_mode && !vhostuser_type && def->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER && xmlStrEqual(cur->name, BAD_CAST "source")) { @@ -7802,6 +7808,10 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, def->script = script; script = NULL; } + if (domain_name != NULL) { + def->domain_name = domain_name; + domain_name = NULL; + } if (ifname != NULL) { def->ifname = ifname; ifname = NULL; @@ -8061,6 +8071,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, VIR_FREE(addrtype); VIR_FREE(trustGuestRxFilters); VIR_FREE(ips); + VIR_FREE(domain_name); virNWFilterHashTableFree(filterparams); return def; @@ -16544,6 +16555,7 @@ virDomainDiskSourceFormatInternal(virBufferPtr buf, virBufferAddLit(buf, "<source"); virBufferEscapeString(buf, " file='%s'", src->path); virBufferEscapeString(buf, " startupPolicy='%s'", startupPolicy); + virBufferEscapeString(buf, " domain='%s'", src->domain_name); virDomainDiskSourceDefFormatSeclabel(buf, src->nseclabels, src->seclabels, flags, @@ -16554,6 +16566,7 @@ virDomainDiskSourceFormatInternal(virBufferPtr buf, virBufferAddLit(buf, "<source"); virBufferEscapeString(buf, " dev='%s'", src->path); virBufferEscapeString(buf, " startupPolicy='%s'", startupPolicy); + virBufferEscapeString(buf, " domain='%s'", src->domain_name); virDomainDiskSourceDefFormatSeclabel(buf, src->nseclabels, src->seclabels, flags, @@ -17713,8 +17726,14 @@ virDomainNetDefFormat(virBufferPtr buf, break; case VIR_DOMAIN_NET_TYPE_ETHERNET: - virBufferEscapeString(buf, "<source dev='%s'/>\n", - def->data.ethernet.dev); + if (def->data.ethernet.dev || def->domain_name) { + virBufferAddLit(buf, "<source"); + virBufferEscapeString(buf, " dev='%s'", + def->data.ethernet.dev); + virBufferEscapeString(buf, " domain='%s'", + def->domain_name); + virBufferAddLit(buf, "/>\n"); + } break; case VIR_DOMAIN_NET_TYPE_VHOSTUSER: @@ -17730,8 +17749,14 @@ virDomainNetDefFormat(virBufferPtr buf, break; case VIR_DOMAIN_NET_TYPE_BRIDGE: - virBufferEscapeString(buf, "<source bridge='%s'/>\n", - def->data.bridge.brname); + if (def->data.bridge.brname || def->domain_name) { + virBufferAddLit(buf, "<source"); + virBufferEscapeString(buf, " bridge='%s'", + def->data.bridge.brname); + virBufferEscapeString(buf, " domain='%s'", + def->domain_name); + virBufferAddLit(buf, "/>\n"); + } break; case VIR_DOMAIN_NET_TYPE_SERVER: diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 93f2314..28c6920 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -995,6 +995,7 @@ struct _virDomainNetDef { unsigned long sndbuf; } tune; char *script; + char *domain_name; /* backend domain name */ char *ifname; char *ifname_guest; char *ifname_guest_actual; diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 8d3d1f5..c2703b7 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -1835,7 +1835,8 @@ virStorageSourceCopy(const virStorageSource *src, VIR_STRDUP(ret->backingStoreRaw, src->backingStoreRaw) < 0 || VIR_STRDUP(ret->snapshot, src->snapshot) < 0 || VIR_STRDUP(ret->configFile, src->configFile) < 0 || - VIR_STRDUP(ret->compat, src->compat) < 0) + VIR_STRDUP(ret->compat, src->compat) < 0 || + VIR_STRDUP(ret->domain_name, src->domain_name)) goto error; if (src->nhosts) { @@ -2023,6 +2024,7 @@ virStorageSourceClear(virStorageSourcePtr def) VIR_FREE(def->path); VIR_FREE(def->volume); + VIR_FREE(def->domain_name); virStorageSourcePoolDefFree(def->srcpool); VIR_FREE(def->driverName); virBitmapFree(def->features); diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index b4c3808..a3c7e1e 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -241,6 +241,7 @@ struct _virStorageSource { char *snapshot; /* for storage systems supporting internal snapshots */ char *configFile; /* some storage systems use config file as part of the source definition */ + char *domain_name; /* name of domain holding backing storage file/dev */ size_t nhosts; virStorageNetHostDefPtr hosts; virStorageSourcePoolDefPtr srcpool; -- 1.8.3.1 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> To: libvirt-list@redhat.com Cc: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> Subject: [PATCH 03/10] libxl: support backend domain setting for disk and net devices Date: Thu, 5 Feb 2015 06:17:09 +0100 Message-Id: <1423113436-18213-4-git-send-email-marmarek@invisiblethingslab.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> References: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Organization: Invisible Things Lab This implement handling of <source domain=''/> parameter introduced in previous patch. Lookup on domain name (to get domain ID) requires libxlDriverPrivate object, so it must be passed down to libxlMakeDisk and libxlMakeNet from top level callers. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - rebase on 1.0.6+ - fix indentation - make libxl_name_to_domid switch more defensive Changes in v3: - rebase on 1.2.12+ - leave name->XID resolution to libxl itself, which greatly simplify the code (but requires Xen at least 4.3) src/libxl/libxl_conf.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 0555b91..1811a83 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -971,6 +971,18 @@ libxlMakeDisk(virDomainDiskDefPtr l_disk, libxl_device_disk *x_disk) return -1; } + if (l_disk->src->domain_name) { +#ifdef LIBXL_HAVE_DEVICE_BACKEND_DOMNAME + if (VIR_STRDUP(x_disk->backend_domname, l_disk->src->domain_name) < 0) + return -1; +#else + virReportError(VIR_ERR_XML_DETAIL, "%s", + _("this version of libxenlight does not " + "support backend domain name")); + return -1; +#endif + } + return 0; } @@ -1098,6 +1110,18 @@ libxlMakeNic(virDomainDefPtr def, return -1; } + if (l_nic->domain_name) { +#ifdef LIBXL_HAVE_DEVICE_BACKEND_DOMNAME + if (VIR_STRDUP(x_nic->backend_domname, l_nic->domain_name) < 0) + return -1; +#else + virReportError(VIR_ERR_XML_DETAIL, "%s", + _("this version of libxenlight does not " + "support backend domain name")); + return -1; +#endif + } + return 0; } -- 1.8.3.1 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> To: libvirt-list@redhat.com Cc: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> Subject: [PATCH 04/10] libxl: fill HVM SDL and VNC settings based on <graphics/> entries Date: Thu, 5 Feb 2015 06:17:10 +0100 Message-Id: <1423113436-18213-5-git-send-email-marmarek@invisiblethingslab.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> References: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Organization: Invisible Things Lab Vfb entries in domain config are used only by PV drivers. Qemu parameters are build based on b_info struct. So fill it with the same data as vfb entries (actually the first one). This will additionally allow graphic-less domain, when no <graphics/> entries are present in domain XML (previously VNC was always enabled). Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_conf.c | 100 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 26 deletions(-) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 1811a83..c9f8ad5 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -618,12 +618,53 @@ libxlMakeChrdevStr(virDomainChrDefPtr def, char **buf) _("unsupported chardev '%s'"), type); return -1; } + return 0; +} + +static int +libxlMakeVNCInfo(virPortAllocatorPtr graphicsports, + virDomainGraphicsDefPtr l_vfb, + libxl_vnc_info *x_vnc) +{ + unsigned short port; + const char *listenAddr; + + libxl_defbool_set(&x_vnc->enable, 1); + /* driver handles selection of free port */ + libxl_defbool_set(&x_vnc->findunused, 0); + if (l_vfb->data.vnc.autoport) { + + if (virPortAllocatorAcquire(graphicsports, &port) < 0) + return -1; + l_vfb->data.vnc.port = port; + } + x_vnc->display = l_vfb->data.vnc.port - LIBXL_VNC_PORT_MIN; + listenAddr = virDomainGraphicsListenGetAddress(l_vfb, 0); + if (listenAddr) { + /* libxl_device_vfb_init() does VIR_STRDUP("127.0.0.1") */ + VIR_FREE(x_vnc->listen); + if (VIR_STRDUP(x_vnc->listen, listenAddr) < 0) + return -1; + } + return 0; +} + +static int +libxlMakeSDLInfo(virDomainGraphicsDefPtr l_vfb, + libxl_sdl_info *x_sdl) +{ + libxl_defbool_set(&x_sdl->enable, 1); + if (VIR_STRDUP(x_sdl->display, l_vfb->data.sdl.display) < 0) + return -1; + if (VIR_STRDUP(x_sdl->xauthority, l_vfb->data.sdl.xauth) < 0) + return -1; return 0; } static int libxlMakeDomBuildInfo(virDomainDefPtr def, + virPortAllocatorPtr graphicsports, libxl_ctx *ctx, libxl_domain_config *d_config) { @@ -745,6 +786,35 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, return -1; } + /* Disable VNC and SDL until explicitly enabled */ + libxl_defbool_set(&b_info->u.hvm.vnc.enable, 0); + libxl_defbool_set(&b_info->u.hvm.sdl.enable, 0); + + for (i = 0; i < def->ngraphics; i++) { + switch (def->graphics[i]->type) { + case VIR_DOMAIN_GRAPHICS_TYPE_VNC: + if (libxl_defbool_val(b_info->u.hvm.vnc.enable)) + continue; + if (libxlMakeVNCInfo(graphicsports, + def->graphics[i], + &b_info->u.hvm.vnc) < 0) + return -1; + if (def->graphics[i]->data.vnc.keymap && + VIR_STRDUP(b_info->u.hvm.keymap, + def->graphics[i]->data.vnc.keymap) < 0) { + virReportOOMError(); + return -1; + } + break; + case VIR_DOMAIN_GRAPHICS_TYPE_SDL: + if (libxl_defbool_val(b_info->u.hvm.sdl.enable)) + continue; + if (libxlMakeSDLInfo(def->graphics[i], &b_info->u.hvm.sdl) < 0) + return -1; + break; + } + } + /* * The following comment and calculation were taken directly from * libxenlight's internal function libxl_get_required_shadow_memory(): @@ -1171,38 +1241,16 @@ libxlMakeVfb(virPortAllocatorPtr graphicsports, virDomainGraphicsDefPtr l_vfb, libxl_device_vfb *x_vfb) { - unsigned short port; - const char *listenAddr; - libxl_device_vfb_init(x_vfb); switch (l_vfb->type) { case VIR_DOMAIN_GRAPHICS_TYPE_SDL: - libxl_defbool_set(&x_vfb->sdl.enable, 1); - if (VIR_STRDUP(x_vfb->sdl.display, l_vfb->data.sdl.display) < 0) - return -1; - if (VIR_STRDUP(x_vfb->sdl.xauthority, l_vfb->data.sdl.xauth) < 0) + if (libxlMakeSDLInfo(l_vfb, &x_vfb->sdl) < 0) return -1; break; case VIR_DOMAIN_GRAPHICS_TYPE_VNC: - libxl_defbool_set(&x_vfb->vnc.enable, 1); - /* driver handles selection of free port */ - libxl_defbool_set(&x_vfb->vnc.findunused, 0); - if (l_vfb->data.vnc.autoport) { - - if (virPortAllocatorAcquire(graphicsports, &port) < 0) - return -1; - l_vfb->data.vnc.port = port; - } - x_vfb->vnc.display = l_vfb->data.vnc.port - LIBXL_VNC_PORT_MIN; - - listenAddr = virDomainGraphicsListenGetAddress(l_vfb, 0); - if (listenAddr) { - /* libxl_device_vfb_init() does VIR_STRDUP("127.0.0.1") */ - VIR_FREE(x_vfb->vnc.listen); - if (VIR_STRDUP(x_vfb->vnc.listen, listenAddr) < 0) - return -1; - } + if (libxlMakeVNCInfo(graphicsports, l_vfb, &x_vfb->vnc) < 0) + return -1; if (VIR_STRDUP(x_vfb->keymap, l_vfb->data.vnc.keymap) < 0) return -1; break; @@ -1611,7 +1659,7 @@ libxlBuildDomainConfig(virPortAllocatorPtr graphicsports, if (libxlMakeDomCreateInfo(ctx, def, &d_config->c_info) < 0) return -1; - if (libxlMakeDomBuildInfo(def, ctx, d_config) < 0) + if (libxlMakeDomBuildInfo(def, graphicsports, ctx, d_config) < 0) return -1; if (libxlMakeDiskList(def, d_config) < 0) -- 1.8.3.1 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> To: libvirt-list@redhat.com Cc: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> Subject: [PATCH 05/10] libxl: pass ipaddr to libxl toolstack Date: Thu, 5 Feb 2015 06:17:11 +0100 Message-Id: <1423113436-18213-6-git-send-email-marmarek@invisiblethingslab.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> References: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Organization: Invisible Things Lab Do not silently ignore its value. LibXL support only one address, so refuse multiple IPs. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_conf.c | 5 +++++ src/libxl/libxl_domain.c | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index c9f8ad5..4730585 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1133,6 +1133,11 @@ libxlMakeNic(virDomainDefPtr def, case VIR_DOMAIN_NET_TYPE_ETHERNET: if (VIR_STRDUP(x_nic->script, l_nic->script) < 0) return -1; + if (l_nic->nips > 0) { + x_nic->ip = virSocketAddrFormat(&l_nic->ips[0]->address); + if (!x_nic->ip) + return -1; + } break; case VIR_DOMAIN_NET_TYPE_NETWORK: { diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 856cfb4..afb0b15 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -482,6 +482,17 @@ libxlDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, STRNEQ(def->os.type, "hvm")) dev->data.chr->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN; + if (dev->type == VIR_DOMAIN_DEVICE_NET && + (dev->data.net->type == VIR_DOMAIN_NET_TYPE_BRIDGE || + dev->data.net->type == VIR_DOMAIN_NET_TYPE_ETHERNET)) { + if (dev->data.net->nips > 1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("multiple IP addresses not supported on device type %s"), + virDomainNetTypeToString(dev->data.net->type)); + return -1; + } + } + if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV || (dev->type == VIR_DOMAIN_DEVICE_NET && dev->data.net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV)) { -- 1.8.3.1 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> To: libvirt-list@redhat.com Cc: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> Subject: [PATCH 06/10] libxl: add tablet/mouse input device support Date: Thu, 5 Feb 2015 06:17:12 +0100 Message-Id: <1423113436-18213-7-git-send-email-marmarek@invisiblethingslab.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> References: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Organization: Invisible Things Lab Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - rebase on 1.2.12+ - multiple devices support src/libxl/libxl_conf.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 4730585..b1131ea 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -815,6 +815,54 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, } } + if (def->ninputs) { +#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST + if (VIR_ALLOC_N(b_info->u.hvm.usbdevice_list, def->ninputs+1) < 0) + return -1; +#else + if (def->ninputs > 1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("libxenlight supports only one input device")); + return -1; + } +#endif + for (i = 0; i < def->ninputs; i++) { + if (def->inputs[i]->bus != VIR_DOMAIN_INPUT_BUS_USB) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("libxenlight supports only USB input")); + return -1; + } + } + for (i = 0; i < def->ninputs; i++) { + switch (def->inputs[i]->type) { + case VIR_DOMAIN_INPUT_TYPE_MOUSE: +#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST + if (VIR_STRDUP(b_info->u.hvm.usbdevice_list[i], "mouse") < 0) + return -1; +#else + VIR_FREE(b_info->u.hvm.usbdevice); + if (VIR_STRDUP(b_info->u.hvm.usbdevice, "mouse") < 0) + return -1; +#endif + break; + case VIR_DOMAIN_INPUT_TYPE_TABLET: +#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST + if (VIR_STRDUP(b_info->u.hvm.usbdevice_list[i], "tablet") < 0) + return -1; +#else + VIR_FREE(b_info->u.hvm.usbdevice); + if (VIR_STRDUP(b_info->u.hvm.usbdevice, "tablet") < 0) + return -1; +#endif + break; + default: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Unknown input device type")); + return -1; + } + } + } + /* * The following comment and calculation were taken directly from * libxenlight's internal function libxl_get_required_shadow_memory(): -- 1.8.3.1 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> To: libvirt-list@redhat.com Cc: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> Subject: [PATCH 07/10] libxl: prevent attaching multiple netdevs with the same MAC Date: Thu, 5 Feb 2015 06:17:13 +0100 Message-Id: <1423113436-18213-8-git-send-email-marmarek@invisiblethingslab.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> References: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Organization: Invisible Things Lab It will not be possible to detach such device later. Also improve logging in such cases. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_driver.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index ce3a99b..005cc96 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2787,6 +2787,7 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, int actualType; libxl_device_nic nic; int ret = -1; + char mac[VIR_MAC_STRING_BUFLEN]; /* preallocate new slot for device */ if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0) @@ -2801,6 +2802,14 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, actualType = virDomainNetGetActualType(net); + /* -2 means "multiple matches" so then fail also */ + if (virDomainNetFindIdx(vm->def, net) != -1) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("device matching mac address %s already exists"), + virMacAddrFormat(&net->mac, mac)); + return -1; + } + if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) { /* This is really a "smart hostdev", so it should be attached * as a hostdev (the hostdev code will reach over into the @@ -2879,6 +2888,7 @@ libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) virDomainHostdevDefPtr hostdev; virDomainHostdevDefPtr found; virDomainHostdevSubsysPCIPtr pcisrc; + char mac[VIR_MAC_STRING_BUFLEN]; switch (dev->type) { case VIR_DOMAIN_DEVICE_DISK: @@ -2896,6 +2906,12 @@ libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) case VIR_DOMAIN_DEVICE_NET: net = dev->data.net; + if (virDomainNetFindIdx(vmdef, net) >= 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("network device with mac %s already exists."), + virMacAddrFormat(&net->mac, mac)); + return -1; + } if (virDomainNetInsert(vmdef, net)) return -1; dev->data.net = NULL; @@ -3060,8 +3076,18 @@ libxlDomainDetachNetDevice(libxlDriverPrivatePtr driver, char mac[VIR_MAC_STRING_BUFLEN]; int ret = -1; - if ((detachidx = virDomainNetFindIdx(vm->def, net)) < 0) + if ((detachidx = virDomainNetFindIdx(vm->def, net)) < 0) { + if (detachidx == -2) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("multiple devices matching mac address %s found"), + virMacAddrFormat(&net->mac, mac)); + } else { + virReportError(VIR_ERR_OPERATION_FAILED, + _("network device %s not found"), + virMacAddrFormat(&net->mac, mac)); + } return -1; + } detach = vm->def->nets[detachidx]; @@ -3136,6 +3162,7 @@ libxlDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) virDomainHostdevDefPtr hostdev, det_hostdev; virDomainNetDefPtr net; int idx; + char mac[VIR_MAC_STRING_BUFLEN]; switch (dev->type) { case VIR_DOMAIN_DEVICE_DISK: @@ -3150,8 +3177,18 @@ libxlDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) case VIR_DOMAIN_DEVICE_NET: net = dev->data.net; - if ((idx = virDomainNetFindIdx(vmdef, net)) < 0) + if ((idx = virDomainNetFindIdx(vmdef, net)) < 0) { + if (idx == -2) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("multiple devices matching mac address %s found"), + virMacAddrFormat(&dev->data.net->mac, mac)); + } else { + virReportError(VIR_ERR_OPERATION_FAILED, + _("network device %s not found"), + virMacAddrFormat(&dev->data.net->mac, mac)); + } return -1; + } /* this is guaranteed to succeed */ virDomainNetDefFree(virDomainNetRemove(vmdef, idx)); -- 1.8.3.1 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> To: libvirt-list@redhat.com Cc: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> Subject: [PATCH 08/10] libxl: support domain config modification in virDomainRestoreFlags Date: Thu, 5 Feb 2015 06:17:14 +0100 Message-Id: <1423113436-18213-9-git-send-email-marmarek@invisiblethingslab.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> References: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Organization: Invisible Things Lab Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- There was a discussion about calling virDomainDefCheckABIStability. The use case I have for this is to start multiple domains from the same savefile. This require changing: - UUID - name - IP address Those are exactly type of changes blocked by virDomainDefCheckABIStability. Perhaps some "permissive" mode should be introduced to the virDomainDefCheckABIStability function? src/libxl/libxl_driver.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 005cc96..7539d33 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -1456,11 +1456,6 @@ libxlDomainRestoreFlags(virConnectPtr conn, const char *from, #endif virCheckFlags(VIR_DOMAIN_SAVE_PAUSED, -1); - if (dxml) { - virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", - _("xml modification unsupported")); - return -1; - } fd = libxlDomainSaveImageOpen(driver, cfg, from, &def, &hdr); if (fd < 0) @@ -1469,6 +1464,18 @@ libxlDomainRestoreFlags(virConnectPtr conn, const char *from, if (virDomainRestoreFlagsEnsureACL(conn, def) < 0) goto cleanup_unlock; + if (dxml) { + virDomainDefPtr def2 = NULL; + + if (!(def2 = virDomainDefParseString(dxml, cfg->caps, driver->xmlopt, + 1 << VIR_DOMAIN_VIRT_XEN, + VIR_DOMAIN_XML_INACTIVE))) { + goto cleanup; + } + virDomainDefFree(def); + def = def2; + } + if (!(vm = virDomainObjListAdd(driver->domains, def, driver->xmlopt, VIR_DOMAIN_OBJ_LIST_ADD_LIVE | -- 1.8.3.1 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> To: libvirt-list@redhat.com Cc: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> Subject: [PATCH 09/10] libxl: Stubdom emulator type Date: Thu, 5 Feb 2015 06:17:15 +0100 Message-Id: <1423113436-18213-10-git-send-email-marmarek@invisiblethingslab.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> References: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Organization: Invisible Things Lab Xen have feature of having device model in separate domain (called stub domain). Add a 'type' attribute to 'emulator' element to allow selecting such a configuration. Emulator path is still used for qemu running in dom0 (if any). Libxl currently do not allow to select stubdomain path. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- I think it would be good idea to introduce the same change to capabilities XML. The problem is I can't include domain_conf.h from capabilities.h, so probably that enum declaration needs to be moved to capabilities.h. Is it the right way? Or it should be done somehow different? docs/formatdomain.html.in | 14 ++++++++++++++ docs/schemas/domaincommon.rng | 23 ++++++++++++++++++++++- src/conf/domain_conf.c | 36 ++++++++++++++++++++++++++++++++++-- src/conf/domain_conf.h | 9 +++++++++ src/libxl/libxl_conf.c | 17 +++++++++++++++++ 5 files changed, 96 insertions(+), 3 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 38c42d5..4f539e2 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1652,6 +1652,20 @@ The <a href="formatcaps.html">capabilities XML</a> specifies the recommended default emulator to use for each particular domain type / architecture combination. + + <span class="since">Since 1.2.13</span>, the <code>emulator</code> + element may contain <code>type</code> attribute. Possible values are: + <dl> + <dt><code>type='default'</code></dt> + <dd>Equivalent to not setting <code>type</code> attribute at all. + </dd> + + <dt><code>type='stubdom'</code></dt> + <dd>Launch emulator in stub domain (Xen only). The emulator path + still indicate which binary is used in dom0 - there is no control + which binary is used as a stub domain. + </dd> + </dl> </dd> </dl> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index a4321f1..2a12073 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2519,7 +2519,28 @@ --> <define name="emulator"> <element name="emulator"> - <ref name="absFilePath"/> + <choice> + <group> + <optional> + <attribute name="type"> + <choice> + <value>qemu</value> + <value>stubdom</value> + </choice> + </attribute> + </optional> + <ref name="absFilePath"/> + </group> + <group> + <attribute name="type"> + <choice> + <value>qemu</value> + <value>stubdom</value> + </choice> + </attribute> + <empty/> + </group> + </choice> </element> </define> <!-- diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 17b699a..c268091 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -741,6 +741,10 @@ VIR_ENUM_IMPL(virDomainDiskTray, VIR_DOMAIN_DISK_TRAY_LAST, "closed", "open"); +VIR_ENUM_IMPL(virDomainEmulatorType, VIR_DOMAIN_EMULATOR_TYPE_LAST, + "qemu", + "stubdom"); + VIR_ENUM_IMPL(virDomainRNGModel, VIR_DOMAIN_RNG_MODEL_LAST, "virtio"); @@ -13712,6 +13716,14 @@ virDomainDefParseXML(xmlDocPtr xml, } def->emulator = virXPathString("string(./devices/emulator[1])", ctxt); + if ((tmp = virXPathString("string(./devices/emulator/@type)", ctxt))) { + def->emulator_type = virDomainEmulatorTypeTypeFromString(tmp); + VIR_FREE(tmp); + if (def->emulator_type < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unknown emulator type '%s'"), tmp); + } + } /* analysis of the disk devices */ if ((n = virXPathNodeSet("./devices/disk", ctxt, &nodes)) < 0) @@ -15690,6 +15702,14 @@ virDomainDefCheckABIStability(virDomainDefPtr src, goto error; } + if (src->emulator_type != dst->emulator_type) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target domain emulator type %s does not match source %s"), + virDomainEmulatorTypeTypeToString(dst->emulator_type), + virDomainEmulatorTypeTypeToString(src->emulator_type)); + goto error; + } + if (!virDomainDefFeaturesCheckABIStability(src, dst)) goto error; @@ -19893,8 +19913,20 @@ virDomainDefFormatInternal(virDomainDefPtr def, virBufferAddLit(buf, "<devices>\n"); virBufferAdjustIndent(buf, 2); - virBufferEscapeString(buf, "<emulator>%s</emulator>\n", - def->emulator); + if (def->emulator || + def->emulator_type != VIR_DOMAIN_EMULATOR_TYPE_DEFAULT) { + virBufferAddLit(buf, "<emulator"); + if (def->emulator_type != VIR_DOMAIN_EMULATOR_TYPE_DEFAULT) { + virBufferAsprintf(buf, " type='%s'", + virDomainEmulatorTypeTypeToString(def->emulator_type)); + } + if (!def->emulator) { + virBufferAddLit(buf, "/>\n"); + } else { + virBufferEscapeString(buf, ">%s</emulator>\n", + def->emulator); + } + } for (n = 0; n < def->ndisks; n++) if (virDomainDiskDefFormat(buf, def->disks[n], flags) < 0) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 28c6920..38b9037 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1918,6 +1918,13 @@ struct _virBlkioDevice { }; typedef enum { + VIR_DOMAIN_EMULATOR_TYPE_DEFAULT, + VIR_DOMAIN_EMULATOR_TYPE_STUBDOM, + + VIR_DOMAIN_EMULATOR_TYPE_LAST +} virDomainEmulatorType; + +typedef enum { VIR_DOMAIN_RNG_MODEL_VIRTIO, VIR_DOMAIN_RNG_MODEL_LAST @@ -2083,6 +2090,7 @@ struct _virDomainDef { virDomainOSDef os; char *emulator; + virDomainEmulatorType emulator_type; /* These three options are of type virTristateSwitch, * except VIR_DOMAIN_FEATURE_CAPABILITIES that is of type * virDomainCapabilitiesPolicy */ @@ -2841,6 +2849,7 @@ VIR_ENUM_DECL(virDomainGraphicsSpiceMouseMode) VIR_ENUM_DECL(virDomainGraphicsVNCSharePolicy) VIR_ENUM_DECL(virDomainHyperv) VIR_ENUM_DECL(virDomainKVM) +VIR_ENUM_DECL(virDomainEmulatorType) VIR_ENUM_DECL(virDomainRNGModel) VIR_ENUM_DECL(virDomainRNGBackend) VIR_ENUM_DECL(virDomainTPMModel) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index b1131ea..a84ce09 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -768,6 +768,23 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, b_info->device_model_version = libxlDomainGetEmulatorType(def); } + /* In case of stubdom there will be two qemu instances: + * - in stubdom (libxl uses hardcoded path for this one), + * - in dom0 as a backend for stubdom (if needed). + * Emulator path control only the second one. It makes a perfect sense + * to use <emulator type='stubdom'/> (yes, without emulator path). + */ + if (def->emulator_type == VIR_DOMAIN_EMULATOR_TYPE_STUBDOM) + libxl_defbool_set(&b_info->device_model_stubdomain, 1); + + if (def->os.cmdline && def->os.cmdline[0]) { + b_info->extra_hvm = virStringSplit(def->os.cmdline, " ", 0); + if (b_info->extra_hvm == NULL) { + virReportOOMError(); + return -1; + } + } + if (def->nserials) { if (def->nserials > 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, -- 1.8.3.1 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> To: libvirt-list@redhat.com Cc: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> Subject: [PATCH 10/10] tests: add some simple libxl XML->XML tests Date: Thu, 5 Feb 2015 06:17:16 +0100 Message-Id: <1423113436-18213-11-git-send-email-marmarek@invisiblethingslab.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> References: <1423113436-18213-1-git-send-email-marmarek@invisiblethingslab.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Organization: Invisible Things Lab Handle features supported only on xen: driver domains, qemu in stubdomain. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- tests/Makefile.am | 9 +- tests/domainschematest | 2 +- tests/xlxml2xmldata/xlxml2xml-hvm-stubdom.xml | 41 +++++ tests/xlxml2xmldata/xlxml2xml-hvm.xml | 40 +++++ tests/xlxml2xmldata/xlxml2xml-network-bridged.xml | 38 +++++ .../xlxml2xml-network-driver-domain.xml | 38 +++++ tests/xlxml2xmldata/xlxml2xml-network-routed.xml | 39 +++++ tests/xlxml2xmldata/xlxml2xml-pv.xml | 38 +++++ tests/xlxml2xmltest.c | 189 +++++++++++++++++++++ 9 files changed, 431 insertions(+), 3 deletions(-) create mode 100644 tests/xlxml2xmldata/xlxml2xml-hvm-stubdom.xml create mode 100644 tests/xlxml2xmldata/xlxml2xml-hvm.xml create mode 100644 tests/xlxml2xmldata/xlxml2xml-network-bridged.xml create mode 100644 tests/xlxml2xmldata/xlxml2xml-network-driver-domain.xml create mode 100644 tests/xlxml2xmldata/xlxml2xml-network-routed.xml create mode 100644 tests/xlxml2xmldata/xlxml2xml-pv.xml create mode 100644 tests/xlxml2xmltest.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 938270c..48648b9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -85,6 +85,7 @@ EXTRA_DIST = \ domainsnapshotxml2xmlout \ fchostdata \ interfaceschemadata \ + xlxml2xmldata \ lxcconf2xmldata \ lxcxml2xmldata \ lxcxml2xmloutdata \ @@ -230,7 +231,7 @@ test_programs += xml2sexprtest sexpr2xmltest \ endif WITH_XEN if WITH_LIBXL -test_programs += xlconfigtest +test_programs += xlconfigtest xlxml2xmltest endif WITH_LIBXL if WITH_QEMU @@ -515,8 +516,12 @@ xlconfigtest_SOURCES = \ xlconfigtest.c testutilsxen.c testutilsxen.h \ testutils.c testutils.h xlconfigtest_LDADD =$(libxl_LDADDS) +xlxml2xmltest_SOURCES = \ + xlxml2xmltest.c testutilsxen.c testutilsxen.h \ + testutils.c testutils.h +xlxml2xmltest_LDADD =$(libxl_LDADDS) else ! WITH_LIBXL -EXTRA_DIST += xlconfigtest.c +EXTRA_DIST += xlconfigtest.c xlxml2xmltest.c endif ! WITH_LIBXL QEMUMONITORTESTUTILS_SOURCES = \ diff --git a/tests/domainschematest b/tests/domainschematest index ba90180..18b442b 100755 --- a/tests/domainschematest +++ b/tests/domainschematest @@ -8,7 +8,7 @@ DIRS="" DIRS="$DIRS domainschemadata qemuxml2argvdata sexpr2xmldata" DIRS="$DIRS xmconfigdata xml2sexprdata qemuxml2xmloutdata" DIRS="$DIRS lxcxml2xmldata lxcxml2xmloutdata" -DIRS="$DIRS bhyvexml2argvdata" +DIRS="$DIRS bhyvexml2argvdata xlxml2xmldata" SCHEMA="domain.rng" check_schema "$DIRS" "$SCHEMA" diff --git a/tests/xlxml2xmldata/xlxml2xml-hvm-stubdom.xml b/tests/xlxml2xmldata/xlxml2xml-hvm-stubdom.xml new file mode 100644 index 0000000..ed6440c --- /dev/null +++ b/tests/xlxml2xmldata/xlxml2xml-hvm-stubdom.xml @@ -0,0 +1,41 @@ +<domain type='xen'> + <name>testhvm</name> + <uuid>a3d3fa04-dc23-4136-9eab-b579d2930817</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>2</vcpu> + <os> + <type arch='x86_64' machine='xenfv'>hvm</type> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> + <boot dev='cdrom'/> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + <viridian/> + </features> + <clock offset='variable' adjustment='0' basis='localtime'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>destroy</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator type='stubdom'>/usr/lib/xen/bin/qemu-dm</emulator> + <disk type='file' device='disk'> + <driver name='file'/> + <source file='/var/lib/libvirt/images/testhvm/root.img'/> + <target dev='xvda' bus='xen'/> + </disk> + <disk type='file' device='disk'> + <driver name='file'/> + <source file='/var/lib/libvirt/images/testhvm/private.img'/> + <target dev='xvdb' bus='xen'/> + </disk> + <interface type='network'> + <mac address='00:16:3e:5e:6c:09'/> + <source network='default'/> + </interface> + <input type='tablet' bus='usb'/> + </devices> +</domain> diff --git a/tests/xlxml2xmldata/xlxml2xml-hvm.xml b/tests/xlxml2xmldata/xlxml2xml-hvm.xml new file mode 100644 index 0000000..95d9b84 --- /dev/null +++ b/tests/xlxml2xmldata/xlxml2xml-hvm.xml @@ -0,0 +1,40 @@ +<domain type='xen'> + <name>testhvm</name> + <uuid>a3d3fa04-dc23-4136-9eab-b579d2930817</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>2</vcpu> + <os> + <type arch='x86_64' machine='xenfv'>hvm</type> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> + <boot dev='cdrom'/> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + <viridian/> + </features> + <clock offset='variable' adjustment='0' basis='localtime'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>destroy</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <disk type='file' device='disk'> + <driver name='file'/> + <source file='/var/lib/libvirt/images/testhvm/root.img'/> + <target dev='xvda' bus='xen'/> + </disk> + <disk type='file' device='disk'> + <driver name='file'/> + <source file='/var/lib/libvirt/images/testhvm/private.img'/> + <target dev='xvdb' bus='xen'/> + </disk> + <interface type='network'> + <mac address='00:16:3e:5e:6c:09'/> + <source network='default'/> + </interface> + <input type='tablet' bus='usb'/> + </devices> +</domain> diff --git a/tests/xlxml2xmldata/xlxml2xml-network-bridged.xml b/tests/xlxml2xmldata/xlxml2xml-network-bridged.xml new file mode 100644 index 0000000..a6b8f59 --- /dev/null +++ b/tests/xlxml2xmldata/xlxml2xml-network-bridged.xml @@ -0,0 +1,38 @@ +<domain type='xen'> + <name>testvm</name> + <uuid>900e3685-4998-41ad-a2c9-e496a5ed40a4</uuid> + <memory unit='KiB'>4096000</memory> + <currentMemory unit='KiB'>409600</currentMemory> + <vcpu placement='static'>2</vcpu> + <os> + <type arch='x86_64' machine='xenpv'>linux</type> + <kernel>/boot/vmlinuz-3.12.37-1</kernel> + <initrd>/boot/initramfs-3.12.37-1.img</initrd> + <cmdline>root=/dev/xvda ro nomodeset console=hvc0 rd_NO_PLYMOUTH 3</cmdline> + </os> + <clock offset='utc' adjustment='reset'> + <timer name='tsc' mode='native'/> + </clock> + <on_poweroff>destroy</on_poweroff> + <on_reboot>destroy</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <disk type='file' device='disk'> + <driver name='file'/> + <source file='/var/lib/libvirt/images/testvm/root.img'/> + <target dev='xvda' bus='xen'/> + </disk> + <disk type='block' device='disk'> + <driver name='file'/> + <source dev='/var/lib/libvirt/images/testvm/home.img'/> + <target dev='xvdb' bus='xen'/> + </disk> + <interface type='bridge'> + <mac address='00:16:3e:5e:6c:09'/> + <source bridge='xenbr0'/> + </interface> + <console type='pty'> + <target type='xen' port='0'/> + </console> + </devices> +</domain> diff --git a/tests/xlxml2xmldata/xlxml2xml-network-driver-domain.xml b/tests/xlxml2xmldata/xlxml2xml-network-driver-domain.xml new file mode 100644 index 0000000..31c0437 --- /dev/null +++ b/tests/xlxml2xmldata/xlxml2xml-network-driver-domain.xml @@ -0,0 +1,38 @@ +<domain type='xen'> + <name>testvm</name> + <uuid>900e3685-4998-41ad-a2c9-e496a5ed40a4</uuid> + <memory unit='KiB'>4096000</memory> + <currentMemory unit='KiB'>409600</currentMemory> + <vcpu placement='static'>2</vcpu> + <os> + <type arch='x86_64' machine='xenpv'>linux</type> + <kernel>/boot/vmlinuz-3.12.37-1</kernel> + <initrd>/boot/initramfs-3.12.37-1.img</initrd> + <cmdline>root=/dev/xvda ro nomodeset console=hvc0 rd_NO_PLYMOUTH 3</cmdline> + </os> + <clock offset='utc' adjustment='reset'> + <timer name='tsc' mode='native'/> + </clock> + <on_poweroff>destroy</on_poweroff> + <on_reboot>destroy</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <disk type='file' device='disk'> + <driver name='file'/> + <source file='/var/lib/libvirt/images/testvm/root.img'/> + <target dev='xvda' bus='xen'/> + </disk> + <disk type='block' device='disk'> + <driver name='file'/> + <source dev='/var/lib/libvirt/images/testvm/home.img'/> + <target dev='xvdb' bus='xen'/> + </disk> + <interface type='bridge'> + <mac address='00:16:3e:5e:6c:09'/> + <source bridge='xenbr0' domain='netvm'/> + </interface> + <console type='pty'> + <target type='xen' port='0'/> + </console> + </devices> +</domain> diff --git a/tests/xlxml2xmldata/xlxml2xml-network-routed.xml b/tests/xlxml2xmldata/xlxml2xml-network-routed.xml new file mode 100644 index 0000000..fac9d8d --- /dev/null +++ b/tests/xlxml2xmldata/xlxml2xml-network-routed.xml @@ -0,0 +1,39 @@ +<domain type='xen'> + <name>testvm</name> + <uuid>900e3685-4998-41ad-a2c9-e496a5ed40a4</uuid> + <memory unit='KiB'>4096000</memory> + <currentMemory unit='KiB'>409600</currentMemory> + <vcpu placement='static'>2</vcpu> + <os> + <type arch='x86_64' machine='xenpv'>linux</type> + <kernel>/boot/vmlinuz-3.12.37-1</kernel> + <initrd>/boot/initramfs-3.12.37-1.img</initrd> + <cmdline>root=/dev/xvda ro nomodeset console=hvc0 rd_NO_PLYMOUTH 3</cmdline> + </os> + <clock offset='utc' adjustment='reset'> + <timer name='tsc' mode='native'/> + </clock> + <on_poweroff>destroy</on_poweroff> + <on_reboot>destroy</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <disk type='file' device='disk'> + <driver name='file'/> + <source file='/var/lib/libvirt/images/testvm/root.img'/> + <target dev='xvda' bus='xen'/> + </disk> + <disk type='block' device='disk'> + <driver name='file'/> + <source dev='/var/lib/libvirt/images/testvm/home.img'/> + <target dev='xvdb' bus='xen'/> + </disk> + <interface type='ethernet'> + <mac address='00:16:3e:5e:6c:09'/> + <ip address='192.168.0.1' family='ipv4'/> + <script path='vif-route'/> + </interface> + <console type='pty'> + <target type='xen' port='0'/> + </console> + </devices> +</domain> diff --git a/tests/xlxml2xmldata/xlxml2xml-pv.xml b/tests/xlxml2xmldata/xlxml2xml-pv.xml new file mode 100644 index 0000000..b937b8b --- /dev/null +++ b/tests/xlxml2xmldata/xlxml2xml-pv.xml @@ -0,0 +1,38 @@ +<domain type='xen'> + <name>testvm</name> + <uuid>900e3685-4998-41ad-a2c9-e496a5ed40a4</uuid> + <memory unit='KiB'>4096000</memory> + <currentMemory unit='KiB'>409600</currentMemory> + <vcpu placement='static'>2</vcpu> + <os> + <type arch='x86_64' machine='xenpv'>linux</type> + <kernel>/boot/vmlinuz-3.12.37-1</kernel> + <initrd>/boot/initramfs-3.12.37-1.img</initrd> + <cmdline>root=/dev/xvda ro nomodeset console=hvc0 rd_NO_PLYMOUTH 3</cmdline> + </os> + <clock offset='utc' adjustment='reset'> + <timer name='tsc' mode='native'/> + </clock> + <on_poweroff>destroy</on_poweroff> + <on_reboot>destroy</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <disk type='file' device='disk'> + <driver name='file'/> + <source file='/var/lib/libvirt/images/testvm/root.img'/> + <target dev='xvda' bus='xen'/> + </disk> + <disk type='block' device='disk'> + <driver name='file'/> + <source dev='/var/lib/libvirt/images/testvm/home.img'/> + <target dev='xvdb' bus='xen'/> + </disk> + <interface type='network'> + <mac address='00:16:3e:5e:6c:09'/> + <source network='default'/> + </interface> + <console type='pty'> + <target type='xen' port='0'/> + </console> + </devices> +</domain> diff --git a/tests/xlxml2xmltest.c b/tests/xlxml2xmltest.c new file mode 100644 index 0000000..131e43b --- /dev/null +++ b/tests/xlxml2xmltest.c @@ -0,0 +1,189 @@ +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include <sys/types.h> +#include <fcntl.h> + +#include "testutils.h" + +#ifdef WITH_LIBXL + +# include "internal.h" +# include "libxl/libxl_conf.h" +# include "libxl/libxl_domain.h" +# include "testutilsxen.h" +# include "virstring.h" + +# define VIR_FROM_THIS VIR_FROM_NONE + +static virCapsPtr caps; +static virDomainXMLOptionPtr xmlopt; + +static int +testCompareXMLToXMLFiles(const char *inxml, const char *outxml, bool live) +{ + char *inXmlData = NULL; + char *outXmlData = NULL; + char *actual = NULL; + int ret = -1; + virDomainDefPtr def = NULL; + unsigned int parse_flags = live ? 0 : VIR_DOMAIN_DEF_PARSE_INACTIVE; + unsigned int format_flags = VIR_DOMAIN_DEF_FORMAT_SECURE; + if (!live) + format_flags |= VIR_DOMAIN_DEF_FORMAT_INACTIVE; + + if (virtTestLoadFile(inxml, &inXmlData) < 0) + goto fail; + if (virtTestLoadFile(outxml, &outXmlData) < 0) + goto fail; + + if (!(def = virDomainDefParseString(inXmlData, caps, xmlopt, + 1 << VIR_DOMAIN_VIRT_XEN, parse_flags))) + goto fail; + + if (!virDomainDefCheckABIStability(def, def)) { + fprintf(stderr, "ABI stability check failed on %s", inxml); + goto fail; + } + + if (!(actual = virDomainDefFormat(def, format_flags))) + goto fail; + + if (STRNEQ(outXmlData, actual)) { + virtTestDifferenceFull(stderr, outXmlData, outxml, actual, inxml); + goto fail; + } + + ret = 0; + fail: + VIR_FREE(inXmlData); + VIR_FREE(outXmlData); + VIR_FREE(actual); + virDomainDefFree(def); + return ret; +} + +enum { + WHEN_INACTIVE = 1, + WHEN_ACTIVE = 2, + WHEN_EITHER = 3, +}; + +struct testInfo { + const char *name; + bool different; + int when; +}; + +static int +testCompareXMLToXMLHelper(const void *data) +{ + const struct testInfo *info = data; + char *xml_in = NULL; + char *xml_out = NULL; + char *xml_out_active = NULL; + char *xml_out_inactive = NULL; + int ret = -1; + + if (virAsprintf(&xml_in, "%s/xlxml2xmldata/xlxml2xml-%s.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&xml_out, "%s/xlxml2xmldata/xlxml2xml-%s-out.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&xml_out_active, + "%s/xlxml2xmldata/xlxml2xml-%s-active.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&xml_out_inactive, + "%s/xlxml2xmldata/xlxml2xml-%s-inactive.xml", + abs_srcdir, info->name) < 0) + goto cleanup; + + if ((info->when & WHEN_INACTIVE)) { + char *out; + if (!info->different) + out = xml_in; + else if (virFileExists(xml_out_inactive)) + out = xml_out_inactive; + else + out = xml_out; + + if (testCompareXMLToXMLFiles(xml_in, out, false) < 0) + goto cleanup; + } + + if ((info->when & WHEN_ACTIVE)) { + char *out; + if (!info->different) + out = xml_in; + else if (virFileExists(xml_out_active)) + out = xml_out_active; + else + out = xml_out; + + if (testCompareXMLToXMLFiles(xml_in, out, true) < 0) + goto cleanup; + } + + ret = 0; + + cleanup: + VIR_FREE(xml_in); + VIR_FREE(xml_out); + VIR_FREE(xml_out_active); + VIR_FREE(xml_out_inactive); + return ret; +} + + +static int +mymain(void) +{ + int ret = 0; + + if ((caps = testXLInitCaps()) == NULL) + return EXIT_FAILURE; + + if (!(xmlopt = libxlCreateXMLConf())) + return EXIT_FAILURE; + +# define DO_TEST_FULL(name, is_different, when) \ + do { \ + const struct testInfo info = {name, is_different, when}; \ + if (virtTestRun("LibXL XML-2-XML " name, \ + testCompareXMLToXMLHelper, &info) < 0) \ + ret = -1; \ + } while (0) + +# define DO_TEST(name) \ + DO_TEST_FULL(name, false, WHEN_EITHER) + +# define DO_TEST_DIFFERENT(name) \ + DO_TEST_FULL(name, true, WHEN_EITHER) + + DO_TEST("hvm"); + DO_TEST("pv"); + DO_TEST("hvm-stubdom"); + DO_TEST("network-bridged"); + DO_TEST("network-routed"); + DO_TEST("network-driver-domain"); + + virObjectUnref(caps); + virObjectUnref(xmlopt); + + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +VIRT_TEST_MAIN(mymain) + +#else + +int +main(void) +{ + return EXIT_AM_SKIP; +} + +#endif /* WITH_LIBXL */ -- 1.8.3.1

Otherwise domainCreateWithFlags via remote returns -1 as domid. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_driver.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index c95b387..ce3a99b 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2375,6 +2375,9 @@ libxlDomainCreateWithFlags(virDomainPtr dom, } ret = libxlDomainStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1); + if (ret < 0) + goto cleanup; + dom->id = vm->def->id; cleanup: if (vm) -- 1.8.3.1

Marek Marczykowski-Górecki wrote:
Otherwise domainCreateWithFlags via remote returns -1 as domid.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_driver.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index c95b387..ce3a99b 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2375,6 +2375,9 @@ libxlDomainCreateWithFlags(virDomainPtr dom, }
ret = libxlDomainStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1); + if (ret < 0) + goto cleanup; + dom->id = vm->def->id;
It looks at though this is the only callsite of libxlDomainStart that needs this change. Have you noticed this with other APIs that call libxlDomainStart? ACK to the fix here though; pushed. Thanks! Regards, Jim
cleanup: if (vm)

On Thu, Feb 05, 2015 at 02:25:41PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
Otherwise domainCreateWithFlags via remote returns -1 as domid.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_driver.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index c95b387..ce3a99b 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2375,6 +2375,9 @@ libxlDomainCreateWithFlags(virDomainPtr dom, }
ret = libxlDomainStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1); + if (ret < 0) + goto cleanup; + dom->id = vm->def->id;
It looks at though this is the only callsite of libxlDomainStart that needs this change. Have you noticed this with other APIs that call libxlDomainStart?
Not directly. But there is a problem if domain gets restarted by some other client - the first one will still use old domid. IIUC for now the only workaround is to listen to lifecycle events for every domain. -- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing?

At least Xen supports backend drivers in another domain (aka "driver domain"). This patch introduces XML config option for such setting as 'domain' attribute of 'source' element. Verification its content is left for the driver. In the future same option will be needed for USB devices (hostdev objects), but for now libxl doesn't have support for PVUSB. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - describe in docs/formatdomain.html.in - enforce empty domain tag (only 'name' attribute allowed) Changes in v3: - change <domain name='xx'/> element to domain='' attribute of source element - this is more logical place - grammar of docs docs/formatdomain.html.in | 29 +++++++++++++++++++++++++++-- docs/schemas/domaincommon.rng | 20 ++++++++++++++++++++ src/conf/domain_conf.c | 33 +++++++++++++++++++++++++++++---- src/conf/domain_conf.h | 1 + src/util/virstoragefile.c | 4 +++- src/util/virstoragefile.h | 1 + 6 files changed, 81 insertions(+), 7 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index c5ad6f4..38c42d5 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1907,13 +1907,17 @@ <span class="since">since 0.0.3</span></dt> <dd> The <code>file</code> attribute specifies the fully-qualified - path to the file holding the disk. + path to the file holding the disk. The optional + <code>domain</code> attribute allows specifying a backend domain + (aka driver domain) where the file is stored. </dd> <dt><code>type='block'</code> <span class="since">since 0.0.3</span></dt> <dd> The <code>dev</code> attribute specifies the path to the - host device to serve as the disk. + host device to serve as the disk. The optional + <code>domain</code> attribute allows specifying a backend domain + (aka driver domain) for the device. </dd> <dt><code>type='dir'</code> <span class="since">since 0.7.5</span></dt> @@ -4336,6 +4340,27 @@ qemu-kvm -net nic,model=? /dev/null element is unspecified is to have the link state <code>up</code>. <span class="since">Since 0.9.5</span> </p> + <h5><a name="elementDomain">Setting up a network backend in a driver domain</a></h5> +<pre> + ... + <devices> + ... + <interface type='bridge'> + <source bridge='br0' <b>domain='netvm'</b>/> + </interface> + ... + </devices> + ...</pre> + + <p> + The optional <code>domain</code> attribute allows specifying a backend + domain (aka driver domain) for the device. Use the <code>name</code> attribute + to specify its name. You can use it to create a direct network link between + domains (so data will not go through host system). Use with type 'ethernet' + to create plain network link, or with 'bridge' to connect to some bridge + inside the driver domain. + <span class="since">Since 1.0.7 (Xen only)</span> + </p> <h5><a name="ipconfig">IP configuration</a></h5> <pre> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index d467dce..a4321f1 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1340,6 +1340,11 @@ <attribute name="file"> <ref name="absFilePath"/> </attribute> + <optional> + <attribute name="domain"> + <ref name="domainName"/> + </attribute> + </optional> </optional> <optional> <ref name="storageStartupPolicy"/> @@ -1365,6 +1370,11 @@ </attribute> </optional> <optional> + <attribute name="domain"> + <ref name="domainName"/> + </attribute> + </optional> + <optional> <ref name="storageStartupPolicy"/> </optional> <optional> @@ -2040,6 +2050,11 @@ <attribute name="bridge"> <ref name="deviceName"/> </attribute> + <optional> + <attribute name="domain"> + <ref name="domainName"/> + </attribute> + </optional> <empty/> </element> </optional> @@ -2059,6 +2074,11 @@ <attribute name="dev"> <ref name="deviceName"/> </attribute> + <optional> + <attribute name="domain"> + <ref name="domainName"/> + </attribute> + </optional> <empty/> </element> </optional> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 4251b13..17b699a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1442,6 +1442,7 @@ void virDomainNetDefFree(virDomainNetDefPtr def) VIR_FREE(def->backend.vhost); VIR_FREE(def->virtPortProfile); VIR_FREE(def->script); + VIR_FREE(def->domain_name); VIR_FREE(def->ifname); VIR_FREE(def->ifname_guest); VIR_FREE(def->ifname_guest_actual); @@ -5520,9 +5521,11 @@ virDomainDiskSourceParse(xmlNodePtr node, switch ((virStorageType)src->type) { case VIR_STORAGE_TYPE_FILE: src->path = virXMLPropString(node, "file"); + src->domain_name = virXMLPropString(node, "domain"); break; case VIR_STORAGE_TYPE_BLOCK: src->path = virXMLPropString(node, "dev"); + src->domain_name = virXMLPropString(node, "domain"); break; case VIR_STORAGE_TYPE_DIR: src->path = virXMLPropString(node, "dir"); @@ -7369,6 +7372,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, char *vhostuser_path = NULL; char *vhostuser_type = NULL; char *trustGuestRxFilters = NULL; + char *domain_name = NULL; virNWFilterHashTablePtr filterparams = NULL; virDomainActualNetDefPtr actual = NULL; xmlNodePtr oldnode = ctxt->node; @@ -7423,12 +7427,14 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, def->type == VIR_DOMAIN_NET_TYPE_BRIDGE && xmlStrEqual(cur->name, BAD_CAST "source")) { bridge = virXMLPropString(cur, "bridge"); + domain_name = virXMLPropString(cur, "domain"); } else if (!dev && (def->type == VIR_DOMAIN_NET_TYPE_ETHERNET || def->type == VIR_DOMAIN_NET_TYPE_DIRECT) && xmlStrEqual(cur->name, BAD_CAST "source")) { dev = virXMLPropString(cur, "dev"); mode = virXMLPropString(cur, "mode"); + domain_name = virXMLPropString(cur, "domain"); } else if (!vhostuser_path && !vhostuser_mode && !vhostuser_type && def->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER && xmlStrEqual(cur->name, BAD_CAST "source")) { @@ -7802,6 +7808,10 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, def->script = script; script = NULL; } + if (domain_name != NULL) { + def->domain_name = domain_name; + domain_name = NULL; + } if (ifname != NULL) { def->ifname = ifname; ifname = NULL; @@ -8061,6 +8071,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, VIR_FREE(addrtype); VIR_FREE(trustGuestRxFilters); VIR_FREE(ips); + VIR_FREE(domain_name); virNWFilterHashTableFree(filterparams); return def; @@ -16544,6 +16555,7 @@ virDomainDiskSourceFormatInternal(virBufferPtr buf, virBufferAddLit(buf, "<source"); virBufferEscapeString(buf, " file='%s'", src->path); virBufferEscapeString(buf, " startupPolicy='%s'", startupPolicy); + virBufferEscapeString(buf, " domain='%s'", src->domain_name); virDomainDiskSourceDefFormatSeclabel(buf, src->nseclabels, src->seclabels, flags, @@ -16554,6 +16566,7 @@ virDomainDiskSourceFormatInternal(virBufferPtr buf, virBufferAddLit(buf, "<source"); virBufferEscapeString(buf, " dev='%s'", src->path); virBufferEscapeString(buf, " startupPolicy='%s'", startupPolicy); + virBufferEscapeString(buf, " domain='%s'", src->domain_name); virDomainDiskSourceDefFormatSeclabel(buf, src->nseclabels, src->seclabels, flags, @@ -17713,8 +17726,14 @@ virDomainNetDefFormat(virBufferPtr buf, break; case VIR_DOMAIN_NET_TYPE_ETHERNET: - virBufferEscapeString(buf, "<source dev='%s'/>\n", - def->data.ethernet.dev); + if (def->data.ethernet.dev || def->domain_name) { + virBufferAddLit(buf, "<source"); + virBufferEscapeString(buf, " dev='%s'", + def->data.ethernet.dev); + virBufferEscapeString(buf, " domain='%s'", + def->domain_name); + virBufferAddLit(buf, "/>\n"); + } break; case VIR_DOMAIN_NET_TYPE_VHOSTUSER: @@ -17730,8 +17749,14 @@ virDomainNetDefFormat(virBufferPtr buf, break; case VIR_DOMAIN_NET_TYPE_BRIDGE: - virBufferEscapeString(buf, "<source bridge='%s'/>\n", - def->data.bridge.brname); + if (def->data.bridge.brname || def->domain_name) { + virBufferAddLit(buf, "<source"); + virBufferEscapeString(buf, " bridge='%s'", + def->data.bridge.brname); + virBufferEscapeString(buf, " domain='%s'", + def->domain_name); + virBufferAddLit(buf, "/>\n"); + } break; case VIR_DOMAIN_NET_TYPE_SERVER: diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 93f2314..28c6920 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -995,6 +995,7 @@ struct _virDomainNetDef { unsigned long sndbuf; } tune; char *script; + char *domain_name; /* backend domain name */ char *ifname; char *ifname_guest; char *ifname_guest_actual; diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 8d3d1f5..c2703b7 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -1835,7 +1835,8 @@ virStorageSourceCopy(const virStorageSource *src, VIR_STRDUP(ret->backingStoreRaw, src->backingStoreRaw) < 0 || VIR_STRDUP(ret->snapshot, src->snapshot) < 0 || VIR_STRDUP(ret->configFile, src->configFile) < 0 || - VIR_STRDUP(ret->compat, src->compat) < 0) + VIR_STRDUP(ret->compat, src->compat) < 0 || + VIR_STRDUP(ret->domain_name, src->domain_name)) goto error; if (src->nhosts) { @@ -2023,6 +2024,7 @@ virStorageSourceClear(virStorageSourcePtr def) VIR_FREE(def->path); VIR_FREE(def->volume); + VIR_FREE(def->domain_name); virStorageSourcePoolDefFree(def->srcpool); VIR_FREE(def->driverName); virBitmapFree(def->features); diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index b4c3808..a3c7e1e 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -241,6 +241,7 @@ struct _virStorageSource { char *snapshot; /* for storage systems supporting internal snapshots */ char *configFile; /* some storage systems use config file as part of the source definition */ + char *domain_name; /* name of domain holding backing storage file/dev */ size_t nhosts; virStorageNetHostDefPtr hosts; virStorageSourcePoolDefPtr srcpool; -- 1.8.3.1

Marek Marczykowski-Górecki wrote:
At least Xen supports backend drivers in another domain (aka "driver domain"). This patch introduces XML config option for such setting as 'domain' attribute of 'source' element. Verification its content is left for the driver.
In the future same option will be needed for USB devices (hostdev objects), but for now libxl doesn't have support for PVUSB.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - describe in docs/formatdomain.html.in - enforce empty domain tag (only 'name' attribute allowed)
Changes in v3: - change <domain name='xx'/> element to domain='' attribute of source element - this is more logical place - grammar of docs
docs/formatdomain.html.in | 29 +++++++++++++++++++++++++++-- docs/schemas/domaincommon.rng | 20 ++++++++++++++++++++ src/conf/domain_conf.c | 33 +++++++++++++++++++++++++++++---- src/conf/domain_conf.h | 1 + src/util/virstoragefile.c | 4 +++- src/util/virstoragefile.h | 1 + 6 files changed, 81 insertions(+), 7 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index c5ad6f4..38c42d5 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1907,13 +1907,17 @@ <span class="since">since 0.0.3</span></dt> <dd> The <code>file</code> attribute specifies the fully-qualified - path to the file holding the disk. + path to the file holding the disk. The optional + <code>domain</code> attribute allows specifying a backend domain
Interesting approach. It almost feels like this is a different type of disk, e.g. <disk type='brokered'> :). There's a fair bit of experience on the list wrt extending the XML. Let's see if other have suggestions. Regards, Jim
+ (aka driver domain) where the file is stored. </dd> <dt><code>type='block'</code> <span class="since">since 0.0.3</span></dt> <dd> The <code>dev</code> attribute specifies the path to the - host device to serve as the disk. + host device to serve as the disk. The optional + <code>domain</code> attribute allows specifying a backend domain + (aka driver domain) for the device. </dd> <dt><code>type='dir'</code> <span class="since">since 0.7.5</span></dt> @@ -4336,6 +4340,27 @@ qemu-kvm -net nic,model=? /dev/null element is unspecified is to have the link state <code>up</code>. <span class="since">Since 0.9.5</span> </p> + <h5><a name="elementDomain">Setting up a network backend in a driver domain</a></h5> +<pre> + ... + <devices> + ... + <interface type='bridge'> + <source bridge='br0' <b>domain='netvm'</b>/> + </interface> + ... + </devices> + ...</pre> + + <p> + The optional <code>domain</code> attribute allows specifying a backend + domain (aka driver domain) for the device. Use the <code>name</code> attribute + to specify its name. You can use it to create a direct network link between + domains (so data will not go through host system). Use with type 'ethernet' + to create plain network link, or with 'bridge' to connect to some bridge + inside the driver domain. + <span class="since">Since 1.0.7 (Xen only)</span> + </p>
<h5><a name="ipconfig">IP configuration</a></h5> <pre> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index d467dce..a4321f1 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1340,6 +1340,11 @@ <attribute name="file"> <ref name="absFilePath"/> </attribute> + <optional> + <attribute name="domain"> + <ref name="domainName"/> + </attribute> + </optional> </optional> <optional> <ref name="storageStartupPolicy"/> @@ -1365,6 +1370,11 @@ </attribute> </optional> <optional> + <attribute name="domain"> + <ref name="domainName"/> + </attribute> + </optional> + <optional> <ref name="storageStartupPolicy"/> </optional> <optional> @@ -2040,6 +2050,11 @@ <attribute name="bridge"> <ref name="deviceName"/> </attribute> + <optional> + <attribute name="domain"> + <ref name="domainName"/> + </attribute> + </optional> <empty/> </element> </optional> @@ -2059,6 +2074,11 @@ <attribute name="dev"> <ref name="deviceName"/> </attribute> + <optional> + <attribute name="domain"> + <ref name="domainName"/> + </attribute> + </optional> <empty/> </element> </optional> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 4251b13..17b699a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1442,6 +1442,7 @@ void virDomainNetDefFree(virDomainNetDefPtr def) VIR_FREE(def->backend.vhost); VIR_FREE(def->virtPortProfile); VIR_FREE(def->script); + VIR_FREE(def->domain_name); VIR_FREE(def->ifname); VIR_FREE(def->ifname_guest); VIR_FREE(def->ifname_guest_actual); @@ -5520,9 +5521,11 @@ virDomainDiskSourceParse(xmlNodePtr node, switch ((virStorageType)src->type) { case VIR_STORAGE_TYPE_FILE: src->path = virXMLPropString(node, "file"); + src->domain_name = virXMLPropString(node, "domain"); break; case VIR_STORAGE_TYPE_BLOCK: src->path = virXMLPropString(node, "dev"); + src->domain_name = virXMLPropString(node, "domain"); break; case VIR_STORAGE_TYPE_DIR: src->path = virXMLPropString(node, "dir"); @@ -7369,6 +7372,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, char *vhostuser_path = NULL; char *vhostuser_type = NULL; char *trustGuestRxFilters = NULL; + char *domain_name = NULL; virNWFilterHashTablePtr filterparams = NULL; virDomainActualNetDefPtr actual = NULL; xmlNodePtr oldnode = ctxt->node; @@ -7423,12 +7427,14 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, def->type == VIR_DOMAIN_NET_TYPE_BRIDGE && xmlStrEqual(cur->name, BAD_CAST "source")) { bridge = virXMLPropString(cur, "bridge"); + domain_name = virXMLPropString(cur, "domain"); } else if (!dev && (def->type == VIR_DOMAIN_NET_TYPE_ETHERNET || def->type == VIR_DOMAIN_NET_TYPE_DIRECT) && xmlStrEqual(cur->name, BAD_CAST "source")) { dev = virXMLPropString(cur, "dev"); mode = virXMLPropString(cur, "mode"); + domain_name = virXMLPropString(cur, "domain"); } else if (!vhostuser_path && !vhostuser_mode && !vhostuser_type && def->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER && xmlStrEqual(cur->name, BAD_CAST "source")) { @@ -7802,6 +7808,10 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, def->script = script; script = NULL; } + if (domain_name != NULL) { + def->domain_name = domain_name; + domain_name = NULL; + } if (ifname != NULL) { def->ifname = ifname; ifname = NULL; @@ -8061,6 +8071,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, VIR_FREE(addrtype); VIR_FREE(trustGuestRxFilters); VIR_FREE(ips); + VIR_FREE(domain_name); virNWFilterHashTableFree(filterparams);
return def; @@ -16544,6 +16555,7 @@ virDomainDiskSourceFormatInternal(virBufferPtr buf, virBufferAddLit(buf, "<source"); virBufferEscapeString(buf, " file='%s'", src->path); virBufferEscapeString(buf, " startupPolicy='%s'", startupPolicy); + virBufferEscapeString(buf, " domain='%s'", src->domain_name);
virDomainDiskSourceDefFormatSeclabel(buf, src->nseclabels, src->seclabels, flags, @@ -16554,6 +16566,7 @@ virDomainDiskSourceFormatInternal(virBufferPtr buf, virBufferAddLit(buf, "<source"); virBufferEscapeString(buf, " dev='%s'", src->path); virBufferEscapeString(buf, " startupPolicy='%s'", startupPolicy); + virBufferEscapeString(buf, " domain='%s'", src->domain_name);
virDomainDiskSourceDefFormatSeclabel(buf, src->nseclabels, src->seclabels, flags, @@ -17713,8 +17726,14 @@ virDomainNetDefFormat(virBufferPtr buf, break;
case VIR_DOMAIN_NET_TYPE_ETHERNET: - virBufferEscapeString(buf, "<source dev='%s'/>\n", - def->data.ethernet.dev); + if (def->data.ethernet.dev || def->domain_name) { + virBufferAddLit(buf, "<source"); + virBufferEscapeString(buf, " dev='%s'", + def->data.ethernet.dev); + virBufferEscapeString(buf, " domain='%s'", + def->domain_name); + virBufferAddLit(buf, "/>\n"); + } break;
case VIR_DOMAIN_NET_TYPE_VHOSTUSER: @@ -17730,8 +17749,14 @@ virDomainNetDefFormat(virBufferPtr buf, break;
case VIR_DOMAIN_NET_TYPE_BRIDGE: - virBufferEscapeString(buf, "<source bridge='%s'/>\n", - def->data.bridge.brname); + if (def->data.bridge.brname || def->domain_name) { + virBufferAddLit(buf, "<source"); + virBufferEscapeString(buf, " bridge='%s'", + def->data.bridge.brname); + virBufferEscapeString(buf, " domain='%s'", + def->domain_name); + virBufferAddLit(buf, "/>\n"); + } break;
case VIR_DOMAIN_NET_TYPE_SERVER: diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 93f2314..28c6920 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -995,6 +995,7 @@ struct _virDomainNetDef { unsigned long sndbuf; } tune; char *script; + char *domain_name; /* backend domain name */ char *ifname; char *ifname_guest; char *ifname_guest_actual; diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 8d3d1f5..c2703b7 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -1835,7 +1835,8 @@ virStorageSourceCopy(const virStorageSource *src, VIR_STRDUP(ret->backingStoreRaw, src->backingStoreRaw) < 0 || VIR_STRDUP(ret->snapshot, src->snapshot) < 0 || VIR_STRDUP(ret->configFile, src->configFile) < 0 || - VIR_STRDUP(ret->compat, src->compat) < 0) + VIR_STRDUP(ret->compat, src->compat) < 0 || + VIR_STRDUP(ret->domain_name, src->domain_name)) goto error;
if (src->nhosts) { @@ -2023,6 +2024,7 @@ virStorageSourceClear(virStorageSourcePtr def)
VIR_FREE(def->path); VIR_FREE(def->volume); + VIR_FREE(def->domain_name); virStorageSourcePoolDefFree(def->srcpool); VIR_FREE(def->driverName); virBitmapFree(def->features); diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index b4c3808..a3c7e1e 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -241,6 +241,7 @@ struct _virStorageSource { char *snapshot; /* for storage systems supporting internal snapshots */ char *configFile; /* some storage systems use config file as part of the source definition */ + char *domain_name; /* name of domain holding backing storage file/dev */ size_t nhosts; virStorageNetHostDefPtr hosts; virStorageSourcePoolDefPtr srcpool;

On Thu, Feb 05, 2015 at 06:17:08AM +0100, Marek Marczykowski-Górecki wrote:
At least Xen supports backend drivers in another domain (aka "driver domain"). This patch introduces XML config option for such setting as 'domain' attribute of 'source' element. Verification its content is left for the driver.
In the future same option will be needed for USB devices (hostdev objects), but for now libxl doesn't have support for PVUSB.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - describe in docs/formatdomain.html.in - enforce empty domain tag (only 'name' attribute allowed)
Changes in v3: - change <domain name='xx'/> element to domain='' attribute of source element - this is more logical place - grammar of docs
I hate to say this, but I think the previous way you had it was a better approach. A <domain name='xxxx'/> element is something we can potentially add to any type of device, whereas the <source domain='xxx'> approach will need to have different XML for each type of device as they don't all have a <source> element present. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On Fri, Feb 06, 2015 at 05:36:40PM +0000, Daniel P. Berrange wrote:
On Thu, Feb 05, 2015 at 06:17:08AM +0100, Marek Marczykowski-Górecki wrote:
At least Xen supports backend drivers in another domain (aka "driver domain"). This patch introduces XML config option for such setting as 'domain' attribute of 'source' element. Verification its content is left for the driver.
In the future same option will be needed for USB devices (hostdev objects), but for now libxl doesn't have support for PVUSB.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - describe in docs/formatdomain.html.in - enforce empty domain tag (only 'name' attribute allowed)
Changes in v3: - change <domain name='xx'/> element to domain='' attribute of source element - this is more logical place - grammar of docs
I hate to say this, but I think the previous way you had it was a better approach. A <domain name='xxxx'/> element is something we can potentially add to any type of device, whereas the <source domain='xxx'> approach will need to have different XML for each type of device as they don't all have a <source> element present.
Ok, but perhaps some better name? When I read something like: <interface type='bridge'> <ip address='1.2.3.4'/> <domain name='netvm'/> </interface> it is really not obvious what domain this is about. When the same would be supported for PCI passthrough, it will be even more confusing: <interface type='hostdev' managed='yes'> <driver name='vfio'/> <source> <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> </source> <mac address='52:54:00:6d:90:02'/> <domain name='netvm'/> </interface> Any ideas for a better name? -- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing?

On 02/06/2015 11:11 AM, Marek Marczykowski-Górecki wrote:
On Fri, Feb 06, 2015 at 05:36:40PM +0000, Daniel P. Berrange wrote:
On Thu, Feb 05, 2015 at 06:17:08AM +0100, Marek Marczykowski-Górecki wrote:
At least Xen supports backend drivers in another domain (aka "driver domain"). This patch introduces XML config option for such setting as 'domain' attribute of 'source' element. Verification its content is left for the driver.
Ok, but perhaps some better name? When I read something like: <interface type='bridge'> <ip address='1.2.3.4'/> <domain name='netvm'/> </interface> it is really not obvious what domain this is about. When the same would be supported for PCI passthrough, it will be even more confusing: <interface type='hostdev' managed='yes'> <driver name='vfio'/> <source> <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> </source> <mac address='52:54:00:6d:90:02'/> <domain name='netvm'/> </interface>
Any ideas for a better name?
Maybe allow a new type of <driver> element? <interface type='hostdev' managed='yes'> <driver name='domain-vfio'> <domain name='netvm'/> </driver> <source>...</source> </interface> Maybe not. But I agree that we want to nail the XML naming convention first. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On Fri, Feb 06, 2015 at 07:11:40PM +0100, Marek Marczykowski-Górecki wrote:
On Fri, Feb 06, 2015 at 05:36:40PM +0000, Daniel P. Berrange wrote:
On Thu, Feb 05, 2015 at 06:17:08AM +0100, Marek Marczykowski-Górecki wrote:
At least Xen supports backend drivers in another domain (aka "driver domain"). This patch introduces XML config option for such setting as 'domain' attribute of 'source' element. Verification its content is left for the driver.
In the future same option will be needed for USB devices (hostdev objects), but for now libxl doesn't have support for PVUSB.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - describe in docs/formatdomain.html.in - enforce empty domain tag (only 'name' attribute allowed)
Changes in v3: - change <domain name='xx'/> element to domain='' attribute of source element - this is more logical place - grammar of docs
I hate to say this, but I think the previous way you had it was a better approach. A <domain name='xxxx'/> element is something we can potentially add to any type of device, whereas the <source domain='xxx'> approach will need to have different XML for each type of device as they don't all have a <source> element present.
Ok, but perhaps some better name? When I read something like: <interface type='bridge'> <ip address='1.2.3.4'/> <domain name='netvm'/> </interface> it is really not obvious what domain this is about. When the same would be supported for PCI passthrough, it will be even more confusing: <interface type='hostdev' managed='yes'> <driver name='vfio'/> <source> <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> </source> <mac address='52:54:00:6d:90:02'/> <domain name='netvm'/> </interface>
Any ideas for a better name?
Perhaps <iodomain name="netvm"> to clarify it a little ? Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On Fri, Feb 06, 2015 at 08:03:43PM +0000, Daniel P. Berrange wrote:
On Fri, Feb 06, 2015 at 07:11:40PM +0100, Marek Marczykowski-Górecki wrote:
On Fri, Feb 06, 2015 at 05:36:40PM +0000, Daniel P. Berrange wrote:
On Thu, Feb 05, 2015 at 06:17:08AM +0100, Marek Marczykowski-Górecki wrote:
At least Xen supports backend drivers in another domain (aka "driver domain"). This patch introduces XML config option for such setting as 'domain' attribute of 'source' element. Verification its content is left for the driver.
In the future same option will be needed for USB devices (hostdev objects), but for now libxl doesn't have support for PVUSB.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - describe in docs/formatdomain.html.in - enforce empty domain tag (only 'name' attribute allowed)
Changes in v3: - change <domain name='xx'/> element to domain='' attribute of source element - this is more logical place - grammar of docs
I hate to say this, but I think the previous way you had it was a better approach. A <domain name='xxxx'/> element is something we can potentially add to any type of device, whereas the <source domain='xxx'> approach will need to have different XML for each type of device as they don't all have a <source> element present.
Ok, but perhaps some better name? When I read something like: <interface type='bridge'> <ip address='1.2.3.4'/> <domain name='netvm'/> </interface> it is really not obvious what domain this is about. When the same would be supported for PCI passthrough, it will be even more confusing: <interface type='hostdev' managed='yes'> <driver name='vfio'/> <source> <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> </source> <mac address='52:54:00:6d:90:02'/> <domain name='netvm'/> </interface>
Any ideas for a better name?
Perhaps <iodomain name="netvm"> to clarify it a little ?
Hmm, if we consider multi-word names, perhaps <backenddomain name='netvm'>? -- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing?

On Fri, Feb 06, 2015 at 09:09:56PM +0100, Marek Marczykowski-Górecki wrote:
On Fri, Feb 06, 2015 at 08:03:43PM +0000, Daniel P. Berrange wrote:
On Fri, Feb 06, 2015 at 07:11:40PM +0100, Marek Marczykowski-Górecki wrote:
On Fri, Feb 06, 2015 at 05:36:40PM +0000, Daniel P. Berrange wrote:
On Thu, Feb 05, 2015 at 06:17:08AM +0100, Marek Marczykowski-Górecki wrote:
At least Xen supports backend drivers in another domain (aka "driver domain"). This patch introduces XML config option for such setting as 'domain' attribute of 'source' element. Verification its content is left for the driver.
In the future same option will be needed for USB devices (hostdev objects), but for now libxl doesn't have support for PVUSB.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - describe in docs/formatdomain.html.in - enforce empty domain tag (only 'name' attribute allowed)
Changes in v3: - change <domain name='xx'/> element to domain='' attribute of source element - this is more logical place - grammar of docs
I hate to say this, but I think the previous way you had it was a better approach. A <domain name='xxxx'/> element is something we can potentially add to any type of device, whereas the <source domain='xxx'> approach will need to have different XML for each type of device as they don't all have a <source> element present.
Ok, but perhaps some better name? When I read something like: <interface type='bridge'> <ip address='1.2.3.4'/> <domain name='netvm'/> </interface> it is really not obvious what domain this is about. When the same would be supported for PCI passthrough, it will be even more confusing: <interface type='hostdev' managed='yes'> <driver name='vfio'/> <source> <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> </source> <mac address='52:54:00:6d:90:02'/> <domain name='netvm'/> </interface>
Any ideas for a better name?
Perhaps <iodomain name="netvm"> to clarify it a little ?
Hmm, if we consider multi-word names, perhaps <backenddomain name='netvm'>?
A little verbose, but I think that's ok, since use of this feature won't be the common case. So this is fine with me unless someone has better ideas. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

From: Marek Marczykowski <marmarek@invisiblethingslab.com> At least Xen supports backend drivers in another domain (aka "driver domain"). This patch introduces XML config option for such setting as 'domain' attribute of 'source' element. Verification its content is left for the driver. In the future same option will be needed for USB devices (hostdev objects), but for now libxl doesn't have support for PVUSB. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - describe in docs/formatdomain.html.in - enforce empty domain tag (only 'name' attribute allowed) Changes in v3: - change <domain name='xx'/> element to domain='' attribute of source element - this is more logical place - grammar of docs Changes in v4: - revert back to separate element, named <backenddomain name='xx'/> docs/formatdomain.html.in | 29 +++++++++++++++++++++++++++++ docs/schemas/domaincommon.rng | 16 ++++++++++++++++ src/conf/domain_conf.c | 21 +++++++++++++++++++++ src/conf/domain_conf.h | 2 ++ 4 files changed, 68 insertions(+) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index c5ad6f4..16d8b5c 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2357,6 +2357,13 @@ </li> </ul> </dd> + <dt><code>backenddomain</code></dt> + <dd>The optional <code>backenddomain</code> element allows specifying a backend + domain (aka driver domain) for the device. If the real device/file resides + in some other domain on the same host, use the <code>name</code> + attribute to specify its name. + <span class="since">Since 1.2.13 (Xen only)</span> + </dd> <dt><code>boot</code></dt> <dd>Specifies that the disk is bootable. The <code>order</code> attribute determines the order in which devices will be tried during @@ -4235,6 +4242,28 @@ qemu-kvm -net nic,model=? /dev/null network device. <span class="since">Since 0.9.10 (QEMU and KVM only)</span>. </p> + <h5><a name="elementDomain">Setting up a network backend in a driver domain</a></h5> +<pre> + ... + <devices> + ... + <interface type='bridge'> + <source bridge='br0'/> + <b><backenddomain name='netvm'/></b> + </interface> + ... + </devices> + ...</pre> + + <p> + The optional <code>backenddomain</code> element allows specifying a backend + domain (aka driver domain) for the device. Use the <code>name</code> attribute + to specify its name. You can use it to create a direct network link between + domains (so data will not go through host system). Use with type 'ethernet' + to create plain network link, or with 'bridge' to connect to some bridge + inside the driver domain. + <span class="since">Since 1.2.13 (Xen only)</span> + </p> <h5><a name="elementQoS">Quality of service</a></h5> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index d467dce..6721431 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1127,6 +1127,14 @@ </optional> <ref name="target"/> <optional> + <element name="backenddomain"> + <attribute name="name"> + <ref name="domainName"/> + </attribute> + <empty/> + </element> + </optional> + <optional> <ref name="deviceBoot"/> </optional> <optional> @@ -2328,6 +2336,14 @@ </element> </optional> <optional> + <element name="backenddomain"> + <attribute name="name"> + <ref name="domainName"/> + </attribute> + <empty/> + </element> + </optional> + <optional> <element name="model"> <attribute name="type"> <data type="string"> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 4251b13..657b71f 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1260,6 +1260,7 @@ virDomainDiskDefFree(virDomainDiskDefPtr def) VIR_FREE(def->wwn); VIR_FREE(def->vendor); VIR_FREE(def->product); + VIR_FREE(def->domain_name); virDomainDeviceInfoClear(&def->info); VIR_FREE(def); @@ -1442,6 +1443,7 @@ void virDomainNetDefFree(virDomainNetDefPtr def) VIR_FREE(def->backend.vhost); VIR_FREE(def->virtPortProfile); VIR_FREE(def->script); + VIR_FREE(def->domain_name); VIR_FREE(def->ifname); VIR_FREE(def->ifname_guest); VIR_FREE(def->ifname_guest_actual); @@ -5725,6 +5727,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, char *discard = NULL; char *mirrorFormat = NULL; char *mirrorType = NULL; + char *domain_name = NULL; int expected_secret_usage = -1; int auth_secret_usage = -1; int ret = 0; @@ -5790,6 +5793,9 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, if (target && STRPREFIX(target, "ioemu:")) memmove(target, target+6, strlen(target)-5); + } else if (!domain_name && + xmlStrEqual(cur->name, BAD_CAST "backenddomain")) { + domain_name = virXMLPropString(cur, "name"); } else if (xmlStrEqual(cur->name, BAD_CAST "geometry")) { if (virXPathUInt("string(./geometry/@cyls)", ctxt, &def->geometry.cylinders) < 0) { @@ -6514,6 +6520,8 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, driverName = NULL; def->src->encryption = encryption; encryption = NULL; + def->domain_name = domain_name; + domain_name = NULL; def->serial = serial; serial = NULL; def->wwn = wwn; @@ -6576,6 +6584,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, VIR_FREE(product); VIR_FREE(mirrorType); VIR_FREE(mirrorFormat); + VIR_FREE(domain_name); ctxt->node = save_ctxt; return def; @@ -7365,6 +7374,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, char *mode = NULL; char *linkstate = NULL; char *addrtype = NULL; + char *domain_name = NULL; char *vhostuser_mode = NULL; char *vhostuser_path = NULL; char *vhostuser_type = NULL; @@ -7503,6 +7513,9 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, } else if (!script && xmlStrEqual(cur->name, BAD_CAST "script")) { script = virXMLPropString(cur, "path"); + } else if (!domain_name && + xmlStrEqual(cur->name, BAD_CAST "backenddomain")) { + domain_name = virXMLPropString(cur, "name"); } else if (xmlStrEqual(cur->name, BAD_CAST "model")) { model = virXMLPropString(cur, "type"); } else if (xmlStrEqual(cur->name, BAD_CAST "driver")) { @@ -7802,6 +7815,10 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, def->script = script; script = NULL; } + if (domain_name != NULL) { + def->domain_name = domain_name; + domain_name = NULL; + } if (ifname != NULL) { def->ifname = ifname; ifname = NULL; @@ -8059,6 +8076,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, VIR_FREE(mode); VIR_FREE(linkstate); VIR_FREE(addrtype); + VIR_FREE(domain_name); VIR_FREE(trustGuestRxFilters); VIR_FREE(ips); virNWFilterHashTableFree(filterparams); @@ -16820,6 +16838,8 @@ virDomainDiskDefFormat(virBufferPtr buf, def->src->backingStoreRaw, 1) < 0) return -1; + virBufferEscapeString(buf, "<backenddomain name='%s'/>\n", def->domain_name); + virDomainDiskGeometryDefFormat(buf, def); virDomainDiskBlockIoDefFormat(buf, def); @@ -17786,6 +17806,7 @@ virDomainNetDefFormat(virBufferPtr buf, virBufferEscapeString(buf, "<script path='%s'/>\n", def->script); + virBufferEscapeString(buf, "<backenddomain name='%s'/>\n", def->domain_name); if (def->ifname && !((flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE) && (STRPREFIX(def->ifname, VIR_NET_GENERATED_PREFIX)))) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 93f2314..b2ef8db 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -700,6 +700,7 @@ struct _virDomainDiskDef { int sgio; /* enum virDomainDeviceSGIO */ int discard; /* enum virDomainDiskDiscard */ unsigned int iothread; /* unused = 0, > 0 specific thread # */ + char *domain_name; /* backend domain name */ }; @@ -995,6 +996,7 @@ struct _virDomainNetDef { unsigned long sndbuf; } tune; char *script; + char *domain_name; /* backend domain name */ char *ifname; char *ifname_guest; char *ifname_guest_actual; -- 1.8.3.1

From: Marek Marczykowski <marmarek@invisiblethingslab.com> This implement handling of <backenddomain name=''/> parameter introduced in previous patch. Works on Xen >= 4.3, because only there libxl supports setting backend domain by name, not XID. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - rebase on 1.0.6+ - fix indentation - make libxl_name_to_domid switch more defensive Changes in v3: - rebase on 1.2.12+ - leave name->XID resolution to libxl itself, which greatly simplify the code (but requires Xen at least 4.3) Changes in v4: - change back to def->domain_name in disk handling code src/libxl/libxl_conf.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 0555b91..5cf3d8f 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -971,6 +971,18 @@ libxlMakeDisk(virDomainDiskDefPtr l_disk, libxl_device_disk *x_disk) return -1; } + if (l_disk->domain_name) { +#ifdef LIBXL_HAVE_DEVICE_BACKEND_DOMNAME + if (VIR_STRDUP(x_disk->backend_domname, l_disk->src->domain_name) < 0) + return -1; +#else + virReportError(VIR_ERR_XML_DETAIL, "%s", + _("this version of libxenlight does not " + "support backend domain name")); + return -1; +#endif + } + return 0; } @@ -1098,6 +1110,18 @@ libxlMakeNic(virDomainDefPtr def, return -1; } + if (l_nic->domain_name) { +#ifdef LIBXL_HAVE_DEVICE_BACKEND_DOMNAME + if (VIR_STRDUP(x_nic->backend_domname, l_nic->domain_name) < 0) + return -1; +#else + virReportError(VIR_ERR_XML_DETAIL, "%s", + _("this version of libxenlight does not " + "support backend domain name")); + return -1; +#endif + } + return 0; } -- 1.8.3.1

Marek Marczykowski-Górecki wrote:
From: Marek Marczykowski <marmarek@invisiblethingslab.com>
This implement handling of <backenddomain name=''/> parameter introduced in previous patch.
Works on Xen >= 4.3, because only there libxl supports setting backend domain by name, not XID.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - rebase on 1.0.6+ - fix indentation - make libxl_name_to_domid switch more defensive
Changes in v3: - rebase on 1.2.12+ - leave name->XID resolution to libxl itself, which greatly simplify the code (but requires Xen at least 4.3)
Changes in v4: - change back to def->domain_name in disk handling code
src/libxl/libxl_conf.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 0555b91..5cf3d8f 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -971,6 +971,18 @@ libxlMakeDisk(virDomainDiskDefPtr l_disk, libxl_device_disk *x_disk) return -1; }
+ if (l_disk->domain_name) { +#ifdef LIBXL_HAVE_DEVICE_BACKEND_DOMNAME + if (VIR_STRDUP(x_disk->backend_domname, l_disk->src->domain_name) < 0)
l_disk->domain_name.
+ return -1; +#else + virReportError(VIR_ERR_XML_DETAIL, "%s", + _("this version of libxenlight does not " + "support backend domain name")); + return -1; +#endif + } + return 0; }
@@ -1098,6 +1110,18 @@ libxlMakeNic(virDomainDefPtr def, return -1; }
+ if (l_nic->domain_name) { +#ifdef LIBXL_HAVE_DEVICE_BACKEND_DOMNAME + if (VIR_STRDUP(x_nic->backend_domname, l_nic->domain_name) < 0) + return -1; +#else + virReportError(VIR_ERR_XML_DETAIL, "%s", + _("this version of libxenlight does not " + "support backend domain name")); + return -1; +#endif + } + return 0; }
ACK. I've added the above fix and pushed 2 and 3. BTW, similar to 6/10, can you add parsing/formating of backenddomain in src/xenconfig? Regards, Jim

Marek Marczykowski-Górecki wrote:
From: Marek Marczykowski <marmarek@invisiblethingslab.com>
At least Xen supports backend drivers in another domain (aka "driver domain"). This patch introduces XML config option for such setting as 'domain' attribute of 'source' element. Verification its content is left for the driver.
In the future same option will be needed for USB devices (hostdev objects), but for now libxl doesn't have support for PVUSB.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - describe in docs/formatdomain.html.in - enforce empty domain tag (only 'name' attribute allowed)
Changes in v3: - change <domain name='xx'/> element to domain='' attribute of source element - this is more logical place - grammar of docs
Changes in v4: - revert back to separate element, named <backenddomain name='xx'/>
docs/formatdomain.html.in | 29 +++++++++++++++++++++++++++++ docs/schemas/domaincommon.rng | 16 ++++++++++++++++ src/conf/domain_conf.c | 21 +++++++++++++++++++++ src/conf/domain_conf.h | 2 ++ 4 files changed, 68 insertions(+)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index c5ad6f4..16d8b5c 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2357,6 +2357,13 @@ </li> </ul> </dd> + <dt><code>backenddomain</code></dt> + <dd>The optional <code>backenddomain</code> element allows specifying a backend + domain (aka driver domain) for the device. If the real device/file resides + in some other domain on the same host, use the <code>name</code> + attribute to specify its name.
I shortened the long lines and changed the text a bit.
+ <span class="since">Since 1.2.13 (Xen only)</span> + </dd> <dt><code>boot</code></dt> <dd>Specifies that the disk is bootable. The <code>order</code> attribute determines the order in which devices will be tried during @@ -4235,6 +4242,28 @@ qemu-kvm -net nic,model=? /dev/null network device. <span class="since">Since 0.9.10 (QEMU and KVM only)</span>. </p> + <h5><a name="elementDomain">Setting up a network backend in a driver domain</a></h5> +<pre> + ... + <devices> + ... + <interface type='bridge'> + <source bridge='br0'/> + <b><backenddomain name='netvm'/></b> + </interface> + ... + </devices> + ...</pre> + + <p> + The optional <code>backenddomain</code> element allows specifying a backend + domain (aka driver domain) for the device. Use the <code>name</code> attribute + to specify its name. You can use it to create a direct network link between + domains (so data will not go through host system). Use with type 'ethernet' + to create plain network link, or with 'bridge' to connect to some bridge + inside the driver domain.
Same here.
+ <span class="since">Since 1.2.13 (Xen only)</span> + </p>
<h5><a name="elementQoS">Quality of service</a></h5>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index d467dce..6721431 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1127,6 +1127,14 @@ </optional> <ref name="target"/> <optional> + <element name="backenddomain"> + <attribute name="name"> + <ref name="domainName"/> + </attribute> + <empty/> + </element> + </optional> + <optional>
I moved this below "devcieBoot", since it seemed to fit there better :-).
<ref name="deviceBoot"/> </optional> <optional> @@ -2328,6 +2336,14 @@ </element> </optional> <optional> + <element name="backenddomain"> + <attribute name="name"> + <ref name="domainName"/> + </attribute> + <empty/> + </element> + </optional> + <optional> <element name="model"> <attribute name="type"> <data type="string"> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 4251b13..657b71f 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1260,6 +1260,7 @@ virDomainDiskDefFree(virDomainDiskDefPtr def) VIR_FREE(def->wwn); VIR_FREE(def->vendor); VIR_FREE(def->product); + VIR_FREE(def->domain_name); virDomainDeviceInfoClear(&def->info);
VIR_FREE(def); @@ -1442,6 +1443,7 @@ void virDomainNetDefFree(virDomainNetDefPtr def) VIR_FREE(def->backend.vhost); VIR_FREE(def->virtPortProfile); VIR_FREE(def->script); + VIR_FREE(def->domain_name); VIR_FREE(def->ifname); VIR_FREE(def->ifname_guest); VIR_FREE(def->ifname_guest_actual); @@ -5725,6 +5727,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, char *discard = NULL; char *mirrorFormat = NULL; char *mirrorType = NULL; + char *domain_name = NULL; int expected_secret_usage = -1; int auth_secret_usage = -1; int ret = 0; @@ -5790,6 +5793,9 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, if (target && STRPREFIX(target, "ioemu:")) memmove(target, target+6, strlen(target)-5); + } else if (!domain_name && + xmlStrEqual(cur->name, BAD_CAST "backenddomain")) { + domain_name = virXMLPropString(cur, "name"); } else if (xmlStrEqual(cur->name, BAD_CAST "geometry")) { if (virXPathUInt("string(./geometry/@cyls)", ctxt, &def->geometry.cylinders) < 0) { @@ -6514,6 +6520,8 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, driverName = NULL; def->src->encryption = encryption; encryption = NULL; + def->domain_name = domain_name; + domain_name = NULL; def->serial = serial; serial = NULL; def->wwn = wwn; @@ -6576,6 +6584,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, VIR_FREE(product); VIR_FREE(mirrorType); VIR_FREE(mirrorFormat); + VIR_FREE(domain_name);
ctxt->node = save_ctxt; return def; @@ -7365,6 +7374,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, char *mode = NULL; char *linkstate = NULL; char *addrtype = NULL; + char *domain_name = NULL; char *vhostuser_mode = NULL; char *vhostuser_path = NULL; char *vhostuser_type = NULL; @@ -7503,6 +7513,9 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, } else if (!script && xmlStrEqual(cur->name, BAD_CAST "script")) { script = virXMLPropString(cur, "path"); + } else if (!domain_name && + xmlStrEqual(cur->name, BAD_CAST "backenddomain")) { + domain_name = virXMLPropString(cur, "name"); } else if (xmlStrEqual(cur->name, BAD_CAST "model")) { model = virXMLPropString(cur, "type"); } else if (xmlStrEqual(cur->name, BAD_CAST "driver")) { @@ -7802,6 +7815,10 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, def->script = script; script = NULL; } + if (domain_name != NULL) { + def->domain_name = domain_name; + domain_name = NULL; + } if (ifname != NULL) { def->ifname = ifname; ifname = NULL; @@ -8059,6 +8076,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, VIR_FREE(mode); VIR_FREE(linkstate); VIR_FREE(addrtype); + VIR_FREE(domain_name); VIR_FREE(trustGuestRxFilters); VIR_FREE(ips); virNWFilterHashTableFree(filterparams); @@ -16820,6 +16838,8 @@ virDomainDiskDefFormat(virBufferPtr buf, def->src->backingStoreRaw, 1) < 0) return -1;
+ virBufferEscapeString(buf, "<backenddomain name='%s'/>\n", def->domain_name); + virDomainDiskGeometryDefFormat(buf, def); virDomainDiskBlockIoDefFormat(buf, def);
@@ -17786,6 +17806,7 @@ virDomainNetDefFormat(virBufferPtr buf,
virBufferEscapeString(buf, "<script path='%s'/>\n", def->script); + virBufferEscapeString(buf, "<backenddomain name='%s'/>\n", def->domain_name); if (def->ifname && !((flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE) && (STRPREFIX(def->ifname, VIR_NET_GENERATED_PREFIX)))) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 93f2314..b2ef8db 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -700,6 +700,7 @@ struct _virDomainDiskDef { int sgio; /* enum virDomainDeviceSGIO */ int discard; /* enum virDomainDiskDiscard */ unsigned int iothread; /* unused = 0, > 0 specific thread # */ + char *domain_name; /* backend domain name */ };
@@ -995,6 +996,7 @@ struct _virDomainNetDef { unsigned long sndbuf; } tune; char *script; + char *domain_name; /* backend domain name */ char *ifname; char *ifname_guest; char *ifname_guest_actual;
ACK. I'll squash in the below diff before pushing. Regards, Jim diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index eb6a412..fb0a0d1 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2373,11 +2373,10 @@ </ul> </dd> <dt><code>backenddomain</code></dt> - <dd>The optional <code>backenddomain</code> element allows specifying a backend - domain (aka driver domain) for the device. If the real device/file resides - in some other domain on the same host, use the <code>name</code> - attribute to specify its name. - <span class="since">Since 1.2.13 (Xen only)</span> + <dd>The optional <code>backenddomain</code> element allows specifying a + backend domain (aka driver domain) hosting the disk. Use the + <code>name</code> attribute to specify the backend domain name. + <span class="since">Since 1.2.13 (Xen only)</span> </dd> <dt><code>boot</code></dt> <dd>Specifies that the disk is bootable. The <code>order</code> @@ -4277,12 +4276,13 @@ qemu-kvm -net nic,model=? /dev/null ...</pre> <p> - The optional <code>backenddomain</code> element allows specifying a backend - domain (aka driver domain) for the device. Use the <code>name</code> attribute - to specify its name. You can use it to create a direct network link between - domains (so data will not go through host system). Use with type 'ethernet' - to create plain network link, or with 'bridge' to connect to some bridge - inside the driver domain. + The optional <code>backenddomain</code> element allows specifying a + backend domain (aka driver domain) for the interface. Use the + <code>name</code> attribute to specify the backend domain name. You + can use it to create a direct network link between domains (so data + will not go through host system). Use with type 'ethernet' to create + plain network link, or with type 'bridge' to connect to a bridge inside + the backend domain. <span class="since">Since 1.2.13 (Xen only)</span> </p> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 5476f5d..f41ca43 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1171,6 +1171,9 @@ </optional> <ref name="target"/> <optional> + <ref name="deviceBoot"/> + </optional> + <optional> <element name="backenddomain"> <attribute name="name"> <ref name="domainName"/> @@ -1179,9 +1182,6 @@ </element> </optional> <optional> - <ref name="deviceBoot"/> - </optional> - <optional> <element name="readonly"> <empty/> </element>

Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
From: Marek Marczykowski <marmarek@invisiblethingslab.com>
At least Xen supports backend drivers in another domain (aka "driver domain"). This patch introduces XML config option for such setting as 'domain' attribute of 'source' element. Verification its content is left for the driver.
I forgot to mention that I corrected the commit message and added an example XML snippet before pushing. Regards, Jim

On 02/19/2015 08:22 PM, Marek Marczykowski-Górecki wrote:
From: Marek Marczykowski <marmarek@invisiblethingslab.com>
At least Xen supports backend drivers in another domain (aka "driver domain"). This patch introduces XML config option for such setting as 'domain' attribute of 'source' element. Verification its content is left for the driver.
In the future same option will be needed for USB devices (hostdev objects), but for now libxl doesn't have support for PVUSB.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - describe in docs/formatdomain.html.in - enforce empty domain tag (only 'name' attribute allowed)
Changes in v3: - change <domain name='xx'/> element to domain='' attribute of source element - this is more logical place - grammar of docs
Changes in v4: - revert back to separate element, named <backenddomain name='xx'/>
Meta-note (don't feel bad about it this time, but food for thought for future submissions): It's a little bit easier on reviewers to send a patch series revision (in this case, v4) as a new top-level thread rather than buried in-reply-to an existing thread. For now, that just seems to be an unwritten convention on libvirt (the qemu project has actually documented it: http://wiki.qemu.org/Contribute/SubmitAPatch - but their policies are sometimes stricter than what we require here, so read that page with a grain of salt). Of course, a patch to libvirt's HACKING to make it an explicit convention might not hurt :) -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

This implement handling of <source domain=''/> parameter introduced in previous patch. Lookup on domain name (to get domain ID) requires libxlDriverPrivate object, so it must be passed down to libxlMakeDisk and libxlMakeNet from top level callers. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - rebase on 1.0.6+ - fix indentation - make libxl_name_to_domid switch more defensive Changes in v3: - rebase on 1.2.12+ - leave name->XID resolution to libxl itself, which greatly simplify the code (but requires Xen at least 4.3) src/libxl/libxl_conf.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 0555b91..1811a83 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -971,6 +971,18 @@ libxlMakeDisk(virDomainDiskDefPtr l_disk, libxl_device_disk *x_disk) return -1; } + if (l_disk->src->domain_name) { +#ifdef LIBXL_HAVE_DEVICE_BACKEND_DOMNAME + if (VIR_STRDUP(x_disk->backend_domname, l_disk->src->domain_name) < 0) + return -1; +#else + virReportError(VIR_ERR_XML_DETAIL, "%s", + _("this version of libxenlight does not " + "support backend domain name")); + return -1; +#endif + } + return 0; } @@ -1098,6 +1110,18 @@ libxlMakeNic(virDomainDefPtr def, return -1; } + if (l_nic->domain_name) { +#ifdef LIBXL_HAVE_DEVICE_BACKEND_DOMNAME + if (VIR_STRDUP(x_nic->backend_domname, l_nic->domain_name) < 0) + return -1; +#else + virReportError(VIR_ERR_XML_DETAIL, "%s", + _("this version of libxenlight does not " + "support backend domain name")); + return -1; +#endif + } + return 0; } -- 1.8.3.1

Vfb entries in domain config are used only by PV drivers. Qemu parameters are build based on b_info struct. So fill it with the same data as vfb entries (actually the first one). This will additionally allow graphic-less domain, when no <graphics/> entries are present in domain XML (previously VNC was always enabled). Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_conf.c | 100 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 26 deletions(-) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 1811a83..c9f8ad5 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -618,12 +618,53 @@ libxlMakeChrdevStr(virDomainChrDefPtr def, char **buf) _("unsupported chardev '%s'"), type); return -1; } + return 0; +} + +static int +libxlMakeVNCInfo(virPortAllocatorPtr graphicsports, + virDomainGraphicsDefPtr l_vfb, + libxl_vnc_info *x_vnc) +{ + unsigned short port; + const char *listenAddr; + + libxl_defbool_set(&x_vnc->enable, 1); + /* driver handles selection of free port */ + libxl_defbool_set(&x_vnc->findunused, 0); + if (l_vfb->data.vnc.autoport) { + + if (virPortAllocatorAcquire(graphicsports, &port) < 0) + return -1; + l_vfb->data.vnc.port = port; + } + x_vnc->display = l_vfb->data.vnc.port - LIBXL_VNC_PORT_MIN; + listenAddr = virDomainGraphicsListenGetAddress(l_vfb, 0); + if (listenAddr) { + /* libxl_device_vfb_init() does VIR_STRDUP("127.0.0.1") */ + VIR_FREE(x_vnc->listen); + if (VIR_STRDUP(x_vnc->listen, listenAddr) < 0) + return -1; + } + return 0; +} + +static int +libxlMakeSDLInfo(virDomainGraphicsDefPtr l_vfb, + libxl_sdl_info *x_sdl) +{ + libxl_defbool_set(&x_sdl->enable, 1); + if (VIR_STRDUP(x_sdl->display, l_vfb->data.sdl.display) < 0) + return -1; + if (VIR_STRDUP(x_sdl->xauthority, l_vfb->data.sdl.xauth) < 0) + return -1; return 0; } static int libxlMakeDomBuildInfo(virDomainDefPtr def, + virPortAllocatorPtr graphicsports, libxl_ctx *ctx, libxl_domain_config *d_config) { @@ -745,6 +786,35 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, return -1; } + /* Disable VNC and SDL until explicitly enabled */ + libxl_defbool_set(&b_info->u.hvm.vnc.enable, 0); + libxl_defbool_set(&b_info->u.hvm.sdl.enable, 0); + + for (i = 0; i < def->ngraphics; i++) { + switch (def->graphics[i]->type) { + case VIR_DOMAIN_GRAPHICS_TYPE_VNC: + if (libxl_defbool_val(b_info->u.hvm.vnc.enable)) + continue; + if (libxlMakeVNCInfo(graphicsports, + def->graphics[i], + &b_info->u.hvm.vnc) < 0) + return -1; + if (def->graphics[i]->data.vnc.keymap && + VIR_STRDUP(b_info->u.hvm.keymap, + def->graphics[i]->data.vnc.keymap) < 0) { + virReportOOMError(); + return -1; + } + break; + case VIR_DOMAIN_GRAPHICS_TYPE_SDL: + if (libxl_defbool_val(b_info->u.hvm.sdl.enable)) + continue; + if (libxlMakeSDLInfo(def->graphics[i], &b_info->u.hvm.sdl) < 0) + return -1; + break; + } + } + /* * The following comment and calculation were taken directly from * libxenlight's internal function libxl_get_required_shadow_memory(): @@ -1171,38 +1241,16 @@ libxlMakeVfb(virPortAllocatorPtr graphicsports, virDomainGraphicsDefPtr l_vfb, libxl_device_vfb *x_vfb) { - unsigned short port; - const char *listenAddr; - libxl_device_vfb_init(x_vfb); switch (l_vfb->type) { case VIR_DOMAIN_GRAPHICS_TYPE_SDL: - libxl_defbool_set(&x_vfb->sdl.enable, 1); - if (VIR_STRDUP(x_vfb->sdl.display, l_vfb->data.sdl.display) < 0) - return -1; - if (VIR_STRDUP(x_vfb->sdl.xauthority, l_vfb->data.sdl.xauth) < 0) + if (libxlMakeSDLInfo(l_vfb, &x_vfb->sdl) < 0) return -1; break; case VIR_DOMAIN_GRAPHICS_TYPE_VNC: - libxl_defbool_set(&x_vfb->vnc.enable, 1); - /* driver handles selection of free port */ - libxl_defbool_set(&x_vfb->vnc.findunused, 0); - if (l_vfb->data.vnc.autoport) { - - if (virPortAllocatorAcquire(graphicsports, &port) < 0) - return -1; - l_vfb->data.vnc.port = port; - } - x_vfb->vnc.display = l_vfb->data.vnc.port - LIBXL_VNC_PORT_MIN; - - listenAddr = virDomainGraphicsListenGetAddress(l_vfb, 0); - if (listenAddr) { - /* libxl_device_vfb_init() does VIR_STRDUP("127.0.0.1") */ - VIR_FREE(x_vfb->vnc.listen); - if (VIR_STRDUP(x_vfb->vnc.listen, listenAddr) < 0) - return -1; - } + if (libxlMakeVNCInfo(graphicsports, l_vfb, &x_vfb->vnc) < 0) + return -1; if (VIR_STRDUP(x_vfb->keymap, l_vfb->data.vnc.keymap) < 0) return -1; break; @@ -1611,7 +1659,7 @@ libxlBuildDomainConfig(virPortAllocatorPtr graphicsports, if (libxlMakeDomCreateInfo(ctx, def, &d_config->c_info) < 0) return -1; - if (libxlMakeDomBuildInfo(def, ctx, d_config) < 0) + if (libxlMakeDomBuildInfo(def, graphicsports, ctx, d_config) < 0) return -1; if (libxlMakeDiskList(def, d_config) < 0) -- 1.8.3.1

Marek Marczykowski-Górecki wrote:
Vfb entries in domain config are used only by PV drivers. Qemu parameters are build based on b_info struct. So fill it with the same data as vfb entries (actually the first one). This will additionally allow graphic-less domain, when no <graphics/> entries are present in domain XML (previously VNC was always enabled).
This should already be handled in libxlMakeVfbList(). Is there something missing in that function? Regards, Jim
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_conf.c | 100 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 26 deletions(-)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 1811a83..c9f8ad5 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -618,12 +618,53 @@ libxlMakeChrdevStr(virDomainChrDefPtr def, char **buf) _("unsupported chardev '%s'"), type); return -1; } + return 0; +} + +static int +libxlMakeVNCInfo(virPortAllocatorPtr graphicsports, + virDomainGraphicsDefPtr l_vfb, + libxl_vnc_info *x_vnc) +{ + unsigned short port; + const char *listenAddr; + + libxl_defbool_set(&x_vnc->enable, 1); + /* driver handles selection of free port */ + libxl_defbool_set(&x_vnc->findunused, 0); + if (l_vfb->data.vnc.autoport) { + + if (virPortAllocatorAcquire(graphicsports, &port) < 0) + return -1; + l_vfb->data.vnc.port = port; + } + x_vnc->display = l_vfb->data.vnc.port - LIBXL_VNC_PORT_MIN;
+ listenAddr = virDomainGraphicsListenGetAddress(l_vfb, 0); + if (listenAddr) { + /* libxl_device_vfb_init() does VIR_STRDUP("127.0.0.1") */ + VIR_FREE(x_vnc->listen); + if (VIR_STRDUP(x_vnc->listen, listenAddr) < 0) + return -1; + } + return 0; +} + +static int +libxlMakeSDLInfo(virDomainGraphicsDefPtr l_vfb, + libxl_sdl_info *x_sdl) +{ + libxl_defbool_set(&x_sdl->enable, 1); + if (VIR_STRDUP(x_sdl->display, l_vfb->data.sdl.display) < 0) + return -1; + if (VIR_STRDUP(x_sdl->xauthority, l_vfb->data.sdl.xauth) < 0) + return -1; return 0; }
static int libxlMakeDomBuildInfo(virDomainDefPtr def, + virPortAllocatorPtr graphicsports, libxl_ctx *ctx, libxl_domain_config *d_config) { @@ -745,6 +786,35 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, return -1; }
+ /* Disable VNC and SDL until explicitly enabled */ + libxl_defbool_set(&b_info->u.hvm.vnc.enable, 0); + libxl_defbool_set(&b_info->u.hvm.sdl.enable, 0); + + for (i = 0; i < def->ngraphics; i++) { + switch (def->graphics[i]->type) { + case VIR_DOMAIN_GRAPHICS_TYPE_VNC: + if (libxl_defbool_val(b_info->u.hvm.vnc.enable)) + continue; + if (libxlMakeVNCInfo(graphicsports, + def->graphics[i], + &b_info->u.hvm.vnc) < 0) + return -1; + if (def->graphics[i]->data.vnc.keymap && + VIR_STRDUP(b_info->u.hvm.keymap, + def->graphics[i]->data.vnc.keymap) < 0) { + virReportOOMError(); + return -1; + } + break; + case VIR_DOMAIN_GRAPHICS_TYPE_SDL: + if (libxl_defbool_val(b_info->u.hvm.sdl.enable)) + continue; + if (libxlMakeSDLInfo(def->graphics[i], &b_info->u.hvm.sdl) < 0) + return -1; + break; + } + } + /* * The following comment and calculation were taken directly from * libxenlight's internal function libxl_get_required_shadow_memory(): @@ -1171,38 +1241,16 @@ libxlMakeVfb(virPortAllocatorPtr graphicsports, virDomainGraphicsDefPtr l_vfb, libxl_device_vfb *x_vfb) { - unsigned short port; - const char *listenAddr; - libxl_device_vfb_init(x_vfb);
switch (l_vfb->type) { case VIR_DOMAIN_GRAPHICS_TYPE_SDL: - libxl_defbool_set(&x_vfb->sdl.enable, 1); - if (VIR_STRDUP(x_vfb->sdl.display, l_vfb->data.sdl.display) < 0) - return -1; - if (VIR_STRDUP(x_vfb->sdl.xauthority, l_vfb->data.sdl.xauth) < 0) + if (libxlMakeSDLInfo(l_vfb, &x_vfb->sdl) < 0) return -1; break; case VIR_DOMAIN_GRAPHICS_TYPE_VNC: - libxl_defbool_set(&x_vfb->vnc.enable, 1); - /* driver handles selection of free port */ - libxl_defbool_set(&x_vfb->vnc.findunused, 0); - if (l_vfb->data.vnc.autoport) { - - if (virPortAllocatorAcquire(graphicsports, &port) < 0) - return -1; - l_vfb->data.vnc.port = port; - } - x_vfb->vnc.display = l_vfb->data.vnc.port - LIBXL_VNC_PORT_MIN; - - listenAddr = virDomainGraphicsListenGetAddress(l_vfb, 0); - if (listenAddr) { - /* libxl_device_vfb_init() does VIR_STRDUP("127.0.0.1") */ - VIR_FREE(x_vfb->vnc.listen); - if (VIR_STRDUP(x_vfb->vnc.listen, listenAddr) < 0) - return -1; - } + if (libxlMakeVNCInfo(graphicsports, l_vfb, &x_vfb->vnc) < 0) + return -1; if (VIR_STRDUP(x_vfb->keymap, l_vfb->data.vnc.keymap) < 0) return -1; break; @@ -1611,7 +1659,7 @@ libxlBuildDomainConfig(virPortAllocatorPtr graphicsports, if (libxlMakeDomCreateInfo(ctx, def, &d_config->c_info) < 0) return -1;
- if (libxlMakeDomBuildInfo(def, ctx, d_config) < 0) + if (libxlMakeDomBuildInfo(def, graphicsports, ctx, d_config) < 0) return -1;
if (libxlMakeDiskList(def, d_config) < 0)

On Thu, Feb 05, 2015 at 02:53:44PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
Vfb entries in domain config are used only by PV drivers. Qemu parameters are build based on b_info struct. So fill it with the same data as vfb entries (actually the first one). This will additionally allow graphic-less domain, when no <graphics/> entries are present in domain XML (previously VNC was always enabled).
This should already be handled in libxlMakeVfbList().
Indeed, I've blindly rebased that patch from older version, but...
Is there something missing in that function?
... yes, if there is no graphics defined, the driver will set b_info->u.hvm.nographic to 1. Which isn't enough to disable graphic, because actual condition in libxl is: if (info->nographic && (!info->sdl && !info->vnc)) { flexarray_append(dm_args, "-nographic"); } I'll think about some better solution (perhaps only part about initially setting vnc and sdl to false?).
Regards, Jim
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_conf.c | 100 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 26 deletions(-)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 1811a83..c9f8ad5 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -618,12 +618,53 @@ libxlMakeChrdevStr(virDomainChrDefPtr def, char **buf) _("unsupported chardev '%s'"), type); return -1; } + return 0; +} + +static int +libxlMakeVNCInfo(virPortAllocatorPtr graphicsports, + virDomainGraphicsDefPtr l_vfb, + libxl_vnc_info *x_vnc) +{ + unsigned short port; + const char *listenAddr; + + libxl_defbool_set(&x_vnc->enable, 1); + /* driver handles selection of free port */ + libxl_defbool_set(&x_vnc->findunused, 0); + if (l_vfb->data.vnc.autoport) { + + if (virPortAllocatorAcquire(graphicsports, &port) < 0) + return -1; + l_vfb->data.vnc.port = port; + } + x_vnc->display = l_vfb->data.vnc.port - LIBXL_VNC_PORT_MIN;
+ listenAddr = virDomainGraphicsListenGetAddress(l_vfb, 0); + if (listenAddr) { + /* libxl_device_vfb_init() does VIR_STRDUP("127.0.0.1") */ + VIR_FREE(x_vnc->listen); + if (VIR_STRDUP(x_vnc->listen, listenAddr) < 0) + return -1; + } + return 0; +} + +static int +libxlMakeSDLInfo(virDomainGraphicsDefPtr l_vfb, + libxl_sdl_info *x_sdl) +{ + libxl_defbool_set(&x_sdl->enable, 1); + if (VIR_STRDUP(x_sdl->display, l_vfb->data.sdl.display) < 0) + return -1; + if (VIR_STRDUP(x_sdl->xauthority, l_vfb->data.sdl.xauth) < 0) + return -1; return 0; }
static int libxlMakeDomBuildInfo(virDomainDefPtr def, + virPortAllocatorPtr graphicsports, libxl_ctx *ctx, libxl_domain_config *d_config) { @@ -745,6 +786,35 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, return -1; }
+ /* Disable VNC and SDL until explicitly enabled */ + libxl_defbool_set(&b_info->u.hvm.vnc.enable, 0); + libxl_defbool_set(&b_info->u.hvm.sdl.enable, 0); + + for (i = 0; i < def->ngraphics; i++) { + switch (def->graphics[i]->type) { + case VIR_DOMAIN_GRAPHICS_TYPE_VNC: + if (libxl_defbool_val(b_info->u.hvm.vnc.enable)) + continue; + if (libxlMakeVNCInfo(graphicsports, + def->graphics[i], + &b_info->u.hvm.vnc) < 0) + return -1; + if (def->graphics[i]->data.vnc.keymap && + VIR_STRDUP(b_info->u.hvm.keymap, + def->graphics[i]->data.vnc.keymap) < 0) { + virReportOOMError(); + return -1; + } + break; + case VIR_DOMAIN_GRAPHICS_TYPE_SDL: + if (libxl_defbool_val(b_info->u.hvm.sdl.enable)) + continue; + if (libxlMakeSDLInfo(def->graphics[i], &b_info->u.hvm.sdl) < 0) + return -1; + break; + } + } + /* * The following comment and calculation were taken directly from * libxenlight's internal function libxl_get_required_shadow_memory(): @@ -1171,38 +1241,16 @@ libxlMakeVfb(virPortAllocatorPtr graphicsports, virDomainGraphicsDefPtr l_vfb, libxl_device_vfb *x_vfb) { - unsigned short port; - const char *listenAddr; - libxl_device_vfb_init(x_vfb);
switch (l_vfb->type) { case VIR_DOMAIN_GRAPHICS_TYPE_SDL: - libxl_defbool_set(&x_vfb->sdl.enable, 1); - if (VIR_STRDUP(x_vfb->sdl.display, l_vfb->data.sdl.display) < 0) - return -1; - if (VIR_STRDUP(x_vfb->sdl.xauthority, l_vfb->data.sdl.xauth) < 0) + if (libxlMakeSDLInfo(l_vfb, &x_vfb->sdl) < 0) return -1; break; case VIR_DOMAIN_GRAPHICS_TYPE_VNC: - libxl_defbool_set(&x_vfb->vnc.enable, 1); - /* driver handles selection of free port */ - libxl_defbool_set(&x_vfb->vnc.findunused, 0); - if (l_vfb->data.vnc.autoport) { - - if (virPortAllocatorAcquire(graphicsports, &port) < 0) - return -1; - l_vfb->data.vnc.port = port; - } - x_vfb->vnc.display = l_vfb->data.vnc.port - LIBXL_VNC_PORT_MIN; - - listenAddr = virDomainGraphicsListenGetAddress(l_vfb, 0); - if (listenAddr) { - /* libxl_device_vfb_init() does VIR_STRDUP("127.0.0.1") */ - VIR_FREE(x_vfb->vnc.listen); - if (VIR_STRDUP(x_vfb->vnc.listen, listenAddr) < 0) - return -1; - } + if (libxlMakeVNCInfo(graphicsports, l_vfb, &x_vfb->vnc) < 0) + return -1; if (VIR_STRDUP(x_vfb->keymap, l_vfb->data.vnc.keymap) < 0) return -1; break; @@ -1611,7 +1659,7 @@ libxlBuildDomainConfig(virPortAllocatorPtr graphicsports, if (libxlMakeDomCreateInfo(ctx, def, &d_config->c_info) < 0) return -1;
- if (libxlMakeDomBuildInfo(def, ctx, d_config) < 0) + if (libxlMakeDomBuildInfo(def, graphicsports, ctx, d_config) < 0) return -1;
if (libxlMakeDiskList(def, d_config) < 0)
-- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing?

On Sat, Feb 07, 2015 at 12:22:51PM +0100, Marek Marczykowski-Górecki wrote:
On Thu, Feb 05, 2015 at 02:53:44PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
Vfb entries in domain config are used only by PV drivers. Qemu parameters are build based on b_info struct. So fill it with the same data as vfb entries (actually the first one). This will additionally allow graphic-less domain, when no <graphics/> entries are present in domain XML (previously VNC was always enabled).
This should already be handled in libxlMakeVfbList().
Indeed, I've blindly rebased that patch from older version, but...
Is there something missing in that function?
... yes, if there is no graphics defined, the driver will set b_info->u.hvm.nographic to 1. Which isn't enough to disable graphic, because actual condition in libxl is: if (info->nographic && (!info->sdl && !info->vnc)) { flexarray_append(dm_args, "-nographic"); }
I'll think about some better solution (perhaps only part about initially setting vnc and sdl to false?).
The problem is when domain XML contains no <video/> nor <graphics/> elements - libxl defaults then to setting up VNC (on 127.0.0.1). The solution here is to disable VNC/SDL and enable only when domain config says so. This still make VNC set when only <video/> is present (without <graphics type='vnc'/>), but at least there is a way make domain really headless. Below is patch which implement that approach. Note that it makes a big change in behaviour - it can make user's configuration broken (if he/she relied on this bug). Disclaimer: I've tested it only with qemu in stubdomain. -----8<----- From 37126eea6927f38fcb7f7f1190143fd7de54e9e6 Mon Sep 17 00:00:00 2001 From: Marek Marczykowski <marmarek@invisiblethingslab.com> Date: Sun, 7 Apr 2013 19:48:03 +0200 Subject: [PATCH] libxl: disable VNC and SDL until explicitly enabled Cc: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> Otherwise when VM have no graphics defined, it is still enabled (with some libxl defaults). Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_conf.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 1811a83..7ee4e54 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -745,6 +745,10 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, return -1; } + /* Disable VNC and SDL until explicitly enabled */ + libxl_defbool_set(&b_info->u.hvm.vnc.enable, 0); + libxl_defbool_set(&b_info->u.hvm.sdl.enable, 0); + /* * The following comment and calculation were taken directly from * libxenlight's internal function libxl_get_required_shadow_memory(): -- 1.8.3.1 -- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing?

Marek Marczykowski-Górecki wrote:
On Sat, Feb 07, 2015 at 12:22:51PM +0100, Marek Marczykowski-Górecki wrote:
On Thu, Feb 05, 2015 at 02:53:44PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
Vfb entries in domain config are used only by PV drivers. Qemu parameters are build based on b_info struct. So fill it with the same data as vfb entries (actually the first one). This will additionally allow graphic-less domain, when no <graphics/> entries are present in domain XML (previously VNC was always enabled).
This should already be handled in libxlMakeVfbList().
Indeed, I've blindly rebased that patch from older version, but...
Is there something missing in that function?
... yes, if there is no graphics defined, the driver will set b_info->u.hvm.nographic to 1. Which isn't enough to disable graphic, because actual condition in libxl is: if (info->nographic && (!info->sdl && !info->vnc)) { flexarray_append(dm_args, "-nographic"); }
I'll think about some better solution (perhaps only part about initially setting vnc and sdl to false?).
The problem is when domain XML contains no <video/> nor <graphics/> elements - libxl defaults then to setting up VNC (on 127.0.0.1). The solution here is to disable VNC/SDL and enable only when domain config says so. This still make VNC set when only <video/> is present (without <graphics type='vnc'/>), but at least there is a way make domain really headless.
Below is patch which implement that approach. Note that it makes a big change in behaviour - it can make user's configuration broken (if he/she relied on this bug).
The current behavior is a regression wrt the legacy Xen driver. In that driver, the absence of <video> and <graphics> results in invoking qemu with -nographic. Since we aim for compatibility with the old Xen driver, I'd argue you are fixing the bug :-).
Disclaimer: I've tested it only with qemu in stubdomain.
I've tested it with a regular HVM domain.
-----8<----- From 37126eea6927f38fcb7f7f1190143fd7de54e9e6 Mon Sep 17 00:00:00 2001 From: Marek Marczykowski <marmarek@invisiblethingslab.com> Date: Sun, 7 Apr 2013 19:48:03 +0200 Subject: [PATCH] libxl: disable VNC and SDL until explicitly enabled Cc: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Otherwise when VM have no graphics defined, it is still enabled (with some libxl defaults).
The commit message should indicate this fixes a regression wrt the legacy Xen driver.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_conf.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 1811a83..7ee4e54 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -745,6 +745,10 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, return -1; }
+ /* Disable VNC and SDL until explicitly enabled */ + libxl_defbool_set(&b_info->u.hvm.vnc.enable, 0); + libxl_defbool_set(&b_info->u.hvm.sdl.enable, 0);
ACK. I'll adjust the commit message and push shortly. Regards, Jim

Do not silently ignore its value. LibXL support only one address, so refuse multiple IPs. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_conf.c | 5 +++++ src/libxl/libxl_domain.c | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index c9f8ad5..4730585 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1133,6 +1133,11 @@ libxlMakeNic(virDomainDefPtr def, case VIR_DOMAIN_NET_TYPE_ETHERNET: if (VIR_STRDUP(x_nic->script, l_nic->script) < 0) return -1; + if (l_nic->nips > 0) { + x_nic->ip = virSocketAddrFormat(&l_nic->ips[0]->address); + if (!x_nic->ip) + return -1; + } break; case VIR_DOMAIN_NET_TYPE_NETWORK: { diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 856cfb4..afb0b15 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -482,6 +482,17 @@ libxlDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, STRNEQ(def->os.type, "hvm")) dev->data.chr->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN; + if (dev->type == VIR_DOMAIN_DEVICE_NET && + (dev->data.net->type == VIR_DOMAIN_NET_TYPE_BRIDGE || + dev->data.net->type == VIR_DOMAIN_NET_TYPE_ETHERNET)) { + if (dev->data.net->nips > 1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("multiple IP addresses not supported on device type %s"), + virDomainNetTypeToString(dev->data.net->type)); + return -1; + } + } + if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV || (dev->type == VIR_DOMAIN_DEVICE_NET && dev->data.net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV)) { -- 1.8.3.1

Marek Marczykowski-Górecki wrote:
Do not silently ignore its value. LibXL support only one address, so refuse multiple IPs.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_conf.c | 5 +++++ src/libxl/libxl_domain.c | 11 +++++++++++ 2 files changed, 16 insertions(+)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index c9f8ad5..4730585 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1133,6 +1133,11 @@ libxlMakeNic(virDomainDefPtr def, case VIR_DOMAIN_NET_TYPE_ETHERNET: if (VIR_STRDUP(x_nic->script, l_nic->script) < 0) return -1; + if (l_nic->nips > 0) { + x_nic->ip = virSocketAddrFormat(&l_nic->ips[0]->address); + if (!x_nic->ip) + return -1; + }
IP address should be supported on VIR_DOMAIN_NET_TYPE_NETWORK interface types too. The domainXML docs even contain an example http://libvirt.org/formatdomain.html#ipconfig Regards, Jim
break; case VIR_DOMAIN_NET_TYPE_NETWORK: { diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 856cfb4..afb0b15 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -482,6 +482,17 @@ libxlDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, STRNEQ(def->os.type, "hvm")) dev->data.chr->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN;
+ if (dev->type == VIR_DOMAIN_DEVICE_NET && + (dev->data.net->type == VIR_DOMAIN_NET_TYPE_BRIDGE || + dev->data.net->type == VIR_DOMAIN_NET_TYPE_ETHERNET)) { + if (dev->data.net->nips > 1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("multiple IP addresses not supported on device type %s"), + virDomainNetTypeToString(dev->data.net->type)); + return -1; + } + } + if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV || (dev->type == VIR_DOMAIN_DEVICE_NET && dev->data.net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV)) {

On Thu, Feb 05, 2015 at 03:36:17PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
Do not silently ignore its value. LibXL support only one address, so refuse multiple IPs.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_conf.c | 5 +++++ src/libxl/libxl_domain.c | 11 +++++++++++ 2 files changed, 16 insertions(+)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index c9f8ad5..4730585 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1133,6 +1133,11 @@ libxlMakeNic(virDomainDefPtr def, case VIR_DOMAIN_NET_TYPE_ETHERNET: if (VIR_STRDUP(x_nic->script, l_nic->script) < 0) return -1; + if (l_nic->nips > 0) { + x_nic->ip = virSocketAddrFormat(&l_nic->ips[0]->address); + if (!x_nic->ip) + return -1; + }
IP address should be supported on VIR_DOMAIN_NET_TYPE_NETWORK interface types too. The domainXML docs even contain an example
Updated patch below. -----8<----- From c1bd7134d4d70a06229243c41284eb37daa35f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> Date: Thu, 5 Feb 2015 05:59:30 +0100 Subject: [PATCH] libxl: pass ipaddr to libxl toolstack Cc: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> Do not silently ignore its value. LibXL support only one address, so refuse multiple IPs. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_conf.c | 11 +++++++++++ src/libxl/libxl_domain.c | 12 ++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index c9f8ad5..ec0f67a 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1133,6 +1133,11 @@ libxlMakeNic(virDomainDefPtr def, case VIR_DOMAIN_NET_TYPE_ETHERNET: if (VIR_STRDUP(x_nic->script, l_nic->script) < 0) return -1; + if (l_nic->nips > 0) { + x_nic->ip = virSocketAddrFormat(&l_nic->ips[0]->address); + if (!x_nic->ip) + return -1; + } break; case VIR_DOMAIN_NET_TYPE_NETWORK: { @@ -1150,6 +1155,12 @@ libxlMakeNic(virDomainDefPtr def, return -1; } + if (l_nic->nips > 0) { + x_nic->ip = virSocketAddrFormat(&l_nic->ips[0]->address); + if (!x_nic->ip) + return -1; + } + if ((brname = virNetworkGetBridgeName(network))) { if (VIR_STRDUP(x_nic->bridge, brname) < 0) fail = true; diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 856cfb4..f0eaf6c 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -482,6 +482,18 @@ libxlDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, STRNEQ(def->os.type, "hvm")) dev->data.chr->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN; + if (dev->type == VIR_DOMAIN_DEVICE_NET && + (dev->data.net->type == VIR_DOMAIN_NET_TYPE_BRIDGE || + dev->data.net->type == VIR_DOMAIN_NET_TYPE_ETHERNET || + dev->data.net->type == VIR_DOMAIN_NET_TYPE_NETWORK)) { + if (dev->data.net->nips > 1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("multiple IP addresses not supported on device type %s"), + virDomainNetTypeToString(dev->data.net->type)); + return -1; + } + } + if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV || (dev->type == VIR_DOMAIN_DEVICE_NET && dev->data.net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV)) { -- 1.8.3.1 -- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing?

Marek Marczykowski-Górecki wrote:
Updated patch below.
-----8<----- From c1bd7134d4d70a06229243c41284eb37daa35f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= <marmarek@invisiblethingslab.com> Date: Thu, 5 Feb 2015 05:59:30 +0100 Subject: [PATCH] libxl: pass ipaddr to libxl toolstack Cc: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Do not silently ignore its value. LibXL support only one address, so refuse multiple IPs.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_conf.c | 11 +++++++++++ src/libxl/libxl_domain.c | 12 ++++++++++++ 2 files changed, 23 insertions(+)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index c9f8ad5..ec0f67a 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1133,6 +1133,11 @@ libxlMakeNic(virDomainDefPtr def, case VIR_DOMAIN_NET_TYPE_ETHERNET: if (VIR_STRDUP(x_nic->script, l_nic->script) < 0) return -1; + if (l_nic->nips > 0) { + x_nic->ip = virSocketAddrFormat(&l_nic->ips[0]->address); + if (!x_nic->ip) + return -1; + } break; case VIR_DOMAIN_NET_TYPE_NETWORK: { @@ -1150,6 +1155,12 @@ libxlMakeNic(virDomainDefPtr def, return -1; }
+ if (l_nic->nips > 0) { + x_nic->ip = virSocketAddrFormat(&l_nic->ips[0]->address); + if (!x_nic->ip) + return -1; + } + if ((brname = virNetworkGetBridgeName(network))) { if (VIR_STRDUP(x_nic->bridge, brname) < 0) fail = true; diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 856cfb4..f0eaf6c 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -482,6 +482,18 @@ libxlDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, STRNEQ(def->os.type, "hvm")) dev->data.chr->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN;
+ if (dev->type == VIR_DOMAIN_DEVICE_NET && + (dev->data.net->type == VIR_DOMAIN_NET_TYPE_BRIDGE || + dev->data.net->type == VIR_DOMAIN_NET_TYPE_ETHERNET || + dev->data.net->type == VIR_DOMAIN_NET_TYPE_NETWORK)) { + if (dev->data.net->nips > 1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("multiple IP addresses not supported on device type %s"), + virDomainNetTypeToString(dev->data.net->type)); + return -1; + } + } + if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV || (dev->type == VIR_DOMAIN_DEVICE_NET && dev->data.net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV)) {
ACK and pushed. Sorry I've stalled on reviewing your series. My libvirt timeslices have been consumed by fixing deadlocks and libxl assertions https://www.redhat.com/archives/libvir-list/2015-February/msg00024.html As suggested by Ian Jackson, I'm working on a series to remove the per-domain libxl_ctx. Those are remnants from the Xen 4.1 libxl days and are no longer required in newer libxl. I have a fair bit of testing to finish, but the series is looking promising thus far. Regards, Jim

Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - rebase on 1.2.12+ - multiple devices support src/libxl/libxl_conf.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 4730585..b1131ea 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -815,6 +815,54 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, } } + if (def->ninputs) { +#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST + if (VIR_ALLOC_N(b_info->u.hvm.usbdevice_list, def->ninputs+1) < 0) + return -1; +#else + if (def->ninputs > 1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("libxenlight supports only one input device")); + return -1; + } +#endif + for (i = 0; i < def->ninputs; i++) { + if (def->inputs[i]->bus != VIR_DOMAIN_INPUT_BUS_USB) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("libxenlight supports only USB input")); + return -1; + } + } + for (i = 0; i < def->ninputs; i++) { + switch (def->inputs[i]->type) { + case VIR_DOMAIN_INPUT_TYPE_MOUSE: +#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST + if (VIR_STRDUP(b_info->u.hvm.usbdevice_list[i], "mouse") < 0) + return -1; +#else + VIR_FREE(b_info->u.hvm.usbdevice); + if (VIR_STRDUP(b_info->u.hvm.usbdevice, "mouse") < 0) + return -1; +#endif + break; + case VIR_DOMAIN_INPUT_TYPE_TABLET: +#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST + if (VIR_STRDUP(b_info->u.hvm.usbdevice_list[i], "tablet") < 0) + return -1; +#else + VIR_FREE(b_info->u.hvm.usbdevice); + if (VIR_STRDUP(b_info->u.hvm.usbdevice, "tablet") < 0) + return -1; +#endif + break; + default: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Unknown input device type")); + return -1; + } + } + } + /* * The following comment and calculation were taken directly from * libxenlight's internal function libxl_get_required_shadow_memory(): -- 1.8.3.1

Marek Marczykowski-Górecki wrote:
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - rebase on 1.2.12+ - multiple devices support
src/libxl/libxl_conf.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 4730585..b1131ea 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -815,6 +815,54 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, } }
+ if (def->ninputs) { +#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST + if (VIR_ALLOC_N(b_info->u.hvm.usbdevice_list, def->ninputs+1) < 0) + return -1; +#else + if (def->ninputs > 1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("libxenlight supports only one input device")); + return -1; + } +#endif + for (i = 0; i < def->ninputs; i++) { + if (def->inputs[i]->bus != VIR_DOMAIN_INPUT_BUS_USB) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("libxenlight supports only USB input")); + return -1; + } + }
+ for (i = 0; i < def->ninputs; i++) { + switch (def->inputs[i]->type) { + case VIR_DOMAIN_INPUT_TYPE_MOUSE: +#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST + if (VIR_STRDUP(b_info->u.hvm.usbdevice_list[i], "mouse") < 0) + return -1; +#else + VIR_FREE(b_info->u.hvm.usbdevice); + if (VIR_STRDUP(b_info->u.hvm.usbdevice, "mouse") < 0) + return -1; +#endif + break; + case VIR_DOMAIN_INPUT_TYPE_TABLET: +#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST + if (VIR_STRDUP(b_info->u.hvm.usbdevice_list[i], "tablet") < 0) + return -1; +#else + VIR_FREE(b_info->u.hvm.usbdevice); + if (VIR_STRDUP(b_info->u.hvm.usbdevice, "tablet") < 0) + return -1; +#endif
One of the #ifdef could be dropped with something like for (i=0; i < def->ninputs; i++) { char *temp; #ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST temp = b_info->u.hvm.usbdevice_list[i]; #else temp = b_info->u.hvm.usbdevice; #endif ... VIR_STRDUP(temp, "mouse"); ... } Also, could you look into adding support for usbdevice_list to the parsing/formating code in src/xenconfig? Regards, Jim
+ break; + default: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Unknown input device type")); + return -1; + } + } + } + /* * The following comment and calculation were taken directly from * libxenlight's internal function libxl_get_required_shadow_memory():

On Wed, Feb 18, 2015 at 08:22:12PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - rebase on 1.2.12+ - multiple devices support
src/libxl/libxl_conf.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 4730585..b1131ea 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -815,6 +815,54 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, } }
+ if (def->ninputs) { +#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST + if (VIR_ALLOC_N(b_info->u.hvm.usbdevice_list, def->ninputs+1) < 0) + return -1; +#else + if (def->ninputs > 1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("libxenlight supports only one input device")); + return -1; + } +#endif + for (i = 0; i < def->ninputs; i++) { + if (def->inputs[i]->bus != VIR_DOMAIN_INPUT_BUS_USB) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("libxenlight supports only USB input")); + return -1; + } + }
+ for (i = 0; i < def->ninputs; i++) { + switch (def->inputs[i]->type) { + case VIR_DOMAIN_INPUT_TYPE_MOUSE: +#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST + if (VIR_STRDUP(b_info->u.hvm.usbdevice_list[i], "mouse") < 0) + return -1; +#else + VIR_FREE(b_info->u.hvm.usbdevice); + if (VIR_STRDUP(b_info->u.hvm.usbdevice, "mouse") < 0) + return -1; +#endif + break; + case VIR_DOMAIN_INPUT_TYPE_TABLET: +#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST + if (VIR_STRDUP(b_info->u.hvm.usbdevice_list[i], "tablet") < 0) + return -1; +#else + VIR_FREE(b_info->u.hvm.usbdevice); + if (VIR_STRDUP(b_info->u.hvm.usbdevice, "tablet") < 0) + return -1; +#endif
One of the #ifdef could be dropped with something like
for (i=0; i < def->ninputs; i++) { char *temp; #ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST temp = b_info->u.hvm.usbdevice_list[i]; #else temp = b_info->u.hvm.usbdevice; #endif ... VIR_STRDUP(temp, "mouse"); ... }
I'll send v3 in a moment...
Also, could you look into adding support for usbdevice_list to the parsing/formating code in src/xenconfig?
...together with additional patches for this. -- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing?

From: Marek Marczykowski <marmarek@invisiblethingslab.com> Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - rebase on 1.2.12+ - multiple devices support Changes in v3: - reduce code duplication src/libxl/libxl_conf.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index b873622..c7108b0 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -749,6 +749,50 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, libxl_defbool_set(&b_info->u.hvm.vnc.enable, 0); libxl_defbool_set(&b_info->u.hvm.sdl.enable, 0); + if (def->ninputs) { + for (i = 0; i < def->ninputs; i++) { + if (def->inputs[i]->bus != VIR_DOMAIN_INPUT_BUS_USB) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("libxenlight supports only USB input")); + return -1; + } + } +#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST + if (VIR_ALLOC_N(b_info->u.hvm.usbdevice_list, def->ninputs+1) < 0) + return -1; +#else + if (def->ninputs > 1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("libxenlight supports only one input device")); + return -1; + } +#endif + for (i = 0; i < def->ninputs; i++) { + char **usbdevice; +#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST + usbdevice = &b_info->u.hvm.usbdevice_list[i]; +#else + usbdevice = &b_info->u.hvm.usbdevice; +#endif + switch (def->inputs[i]->type) { + case VIR_DOMAIN_INPUT_TYPE_MOUSE: + VIR_FREE(*usbdevice); + if (VIR_STRDUP(*usbdevice, "mouse") < 0) + return -1; + break; + case VIR_DOMAIN_INPUT_TYPE_TABLET: + VIR_FREE(*usbdevice); + if (VIR_STRDUP(*usbdevice, "tablet") < 0) + return -1; + break; + default: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Unknown input device type")); + return -1; + } + } + } + /* * The following comment and calculation were taken directly from * libxenlight's internal function libxl_get_required_shadow_memory(): -- 1.8.3.1

In Xen>=4.3, libxl supports new syntax for USB devices: usbdevice=[ "DEVICE", "DEVICE", ... ] Add support for that in xenconfig driver. When only one device is defined, keep using old syntax for backward compatibility. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/xenconfig/xen_common.c | 108 +++++++++++++++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 32 deletions(-) diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c index a2a1474..4494f1d 100644 --- a/src/xenconfig/xen_common.c +++ b/src/xenconfig/xen_common.c @@ -964,6 +964,7 @@ static int xenParseEmulatedDevices(virConfPtr conf, virDomainDefPtr def) { const char *str; + virConfValuePtr val; if (STREQ(def->os.type, "hvm")) { if (xenConfigGetString(conf, "soundhw", &str, NULL) < 0) @@ -973,31 +974,42 @@ xenParseEmulatedDevices(virConfPtr conf, virDomainDefPtr def) xenParseSxprSound(def, str) < 0) return -1; - if (xenConfigGetString(conf, "usbdevice", &str, NULL) < 0) - return -1; - if (str && - (STREQ(str, "tablet") || - STREQ(str, "mouse") || - STREQ(str, "keyboard"))) { - virDomainInputDefPtr input; - if (VIR_ALLOC(input) < 0) - return -1; - - input->bus = VIR_DOMAIN_INPUT_BUS_USB; - if (STREQ(str, "mouse")) - input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE; - else if (STREQ(str, "tablet")) - input->type = VIR_DOMAIN_INPUT_TYPE_TABLET; - else if (STREQ(str, "keyboard")) - input->type = VIR_DOMAIN_INPUT_TYPE_KBD; - if (VIR_ALLOC_N(def->inputs, 1) < 0) { - virDomainInputDefFree(input); + val = virConfGetValue(conf, "usbdevice"); + /* usbdevice can be defined as either a single string or a list */ + if (val && val->type == VIR_CONF_LIST) + val = val->list; + /* otherwise val->next is NULL, so can be handled by the same code */ + while (val) { + if (val->type != VIR_CONF_STRING) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("config value %s was malformed"), + "usbdevice"); return -1; + } + str = val->str; + + if (str && + (STREQ(str, "tablet") || + STREQ(str, "mouse") || + STREQ(str, "keyboard"))) { + virDomainInputDefPtr input; + if (VIR_ALLOC(input) < 0) + return -1; + input->bus = VIR_DOMAIN_INPUT_BUS_USB; + if (STREQ(str, "mouse")) + input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE; + else if (STREQ(str, "tablet")) + input->type = VIR_DOMAIN_INPUT_TYPE_TABLET; + else if (STREQ(str, "keyboard")) + input->type = VIR_DOMAIN_INPUT_TYPE_KBD; + if (VIR_APPEND_ELEMENT(def->inputs, def->ninputs, input) < 0) { + virDomainInputDefFree(input); + return -1; + } } - def->inputs[0] = input; - def->ninputs = 1; + val = val->next; } } @@ -1953,36 +1965,68 @@ static int xenFormatInputDevs(virConfPtr conf, virDomainDefPtr def) { size_t i; + const char *devtype; + virConfValuePtr usbdevices = NULL, lastdev; if (STREQ(def->os.type, "hvm")) { + if (VIR_ALLOC(usbdevices) < 0) + goto error; + + usbdevices->type = VIR_CONF_LIST; + usbdevices->list = NULL; + lastdev = NULL; for (i = 0; i < def->ninputs; i++) { if (def->inputs[i]->bus == VIR_DOMAIN_INPUT_BUS_USB) { if (xenConfigSetInt(conf, "usb", 1) < 0) - return -1; + goto error; switch (def->inputs[i]->type) { case VIR_DOMAIN_INPUT_TYPE_MOUSE: - if (xenConfigSetString(conf, "usbdevice", "mouse") < 0) - return -1; - + devtype = "mouse"; break; case VIR_DOMAIN_INPUT_TYPE_TABLET: - if (xenConfigSetString(conf, "usbdevice", "tablet") < 0) - return -1; - + devtype = "tablet"; break; case VIR_DOMAIN_INPUT_TYPE_KBD: - if (xenConfigSetString(conf, "usbdevice", "keyboard") < 0) - return -1; - + devtype = "keyboard"; break; + default: + continue; } - break; + + if (lastdev == NULL) { + if (VIR_ALLOC(lastdev) < 0) + goto error; + usbdevices->list = lastdev; + } else { + if (VIR_ALLOC(lastdev->next) < 0) + goto error; + lastdev = lastdev->next; + } + lastdev->type = VIR_CONF_STRING; + if (VIR_STRDUP(lastdev->str, devtype) < 0) + goto error; } } + if (usbdevices->list != NULL) { + if (usbdevices->list->next == NULL) { + /* for compatibility with Xen <= 4.2, use old syntax when + * only one device present */ + if (xenConfigSetString(conf, "usbdevice", usbdevices->list->str) < 0) + goto error; + virConfFreeValue(usbdevices); + } else { + virConfSetValue(conf, "usbdevice", usbdevices); + } + } else { + VIR_FREE(usbdevices); + } } return 0; + error: + virConfFreeValue(usbdevices); + return -1; } -- 1.8.3.1

Marek Marczykowski-Górecki wrote:
In Xen>=4.3, libxl supports new syntax for USB devices: usbdevice=[ "DEVICE", "DEVICE", ... ] Add support for that in xenconfig driver. When only one device is defined, keep using old syntax for backward compatibility.
Cool, thanks for doing this! But I have a "small" nit...
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/xenconfig/xen_common.c | 108 +++++++++++++++++++++++++++++++--------------
xm only supported the usbdevice=DEVICE syntax, but the code in xen_common is used to parse/format both xm and xl config. I think parsing/formating of these devices should be moved to xen-xm and xen-xl. Regards, Jim
1 file changed, 76 insertions(+), 32 deletions(-)
diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c index a2a1474..4494f1d 100644 --- a/src/xenconfig/xen_common.c +++ b/src/xenconfig/xen_common.c @@ -964,6 +964,7 @@ static int xenParseEmulatedDevices(virConfPtr conf, virDomainDefPtr def) { const char *str; + virConfValuePtr val;
if (STREQ(def->os.type, "hvm")) { if (xenConfigGetString(conf, "soundhw", &str, NULL) < 0) @@ -973,31 +974,42 @@ xenParseEmulatedDevices(virConfPtr conf, virDomainDefPtr def) xenParseSxprSound(def, str) < 0) return -1;
- if (xenConfigGetString(conf, "usbdevice", &str, NULL) < 0) - return -1;
- if (str && - (STREQ(str, "tablet") || - STREQ(str, "mouse") || - STREQ(str, "keyboard"))) { - virDomainInputDefPtr input; - if (VIR_ALLOC(input) < 0) - return -1; - - input->bus = VIR_DOMAIN_INPUT_BUS_USB; - if (STREQ(str, "mouse")) - input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE; - else if (STREQ(str, "tablet")) - input->type = VIR_DOMAIN_INPUT_TYPE_TABLET; - else if (STREQ(str, "keyboard")) - input->type = VIR_DOMAIN_INPUT_TYPE_KBD; - if (VIR_ALLOC_N(def->inputs, 1) < 0) { - virDomainInputDefFree(input); + val = virConfGetValue(conf, "usbdevice"); + /* usbdevice can be defined as either a single string or a list */ + if (val && val->type == VIR_CONF_LIST) + val = val->list; + /* otherwise val->next is NULL, so can be handled by the same code */ + while (val) { + if (val->type != VIR_CONF_STRING) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("config value %s was malformed"), + "usbdevice"); return -1; + } + str = val->str; + + if (str && + (STREQ(str, "tablet") || + STREQ(str, "mouse") || + STREQ(str, "keyboard"))) { + virDomainInputDefPtr input; + if (VIR_ALLOC(input) < 0) + return -1;
+ input->bus = VIR_DOMAIN_INPUT_BUS_USB; + if (STREQ(str, "mouse")) + input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE; + else if (STREQ(str, "tablet")) + input->type = VIR_DOMAIN_INPUT_TYPE_TABLET; + else if (STREQ(str, "keyboard")) + input->type = VIR_DOMAIN_INPUT_TYPE_KBD; + if (VIR_APPEND_ELEMENT(def->inputs, def->ninputs, input) < 0) { + virDomainInputDefFree(input); + return -1; + } } - def->inputs[0] = input; - def->ninputs = 1; + val = val->next; } }
@@ -1953,36 +1965,68 @@ static int xenFormatInputDevs(virConfPtr conf, virDomainDefPtr def) { size_t i; + const char *devtype; + virConfValuePtr usbdevices = NULL, lastdev;
if (STREQ(def->os.type, "hvm")) { + if (VIR_ALLOC(usbdevices) < 0) + goto error; + + usbdevices->type = VIR_CONF_LIST; + usbdevices->list = NULL; + lastdev = NULL; for (i = 0; i < def->ninputs; i++) { if (def->inputs[i]->bus == VIR_DOMAIN_INPUT_BUS_USB) { if (xenConfigSetInt(conf, "usb", 1) < 0) - return -1; + goto error;
switch (def->inputs[i]->type) { case VIR_DOMAIN_INPUT_TYPE_MOUSE: - if (xenConfigSetString(conf, "usbdevice", "mouse") < 0) - return -1; - + devtype = "mouse"; break; case VIR_DOMAIN_INPUT_TYPE_TABLET: - if (xenConfigSetString(conf, "usbdevice", "tablet") < 0) - return -1; - + devtype = "tablet"; break; case VIR_DOMAIN_INPUT_TYPE_KBD: - if (xenConfigSetString(conf, "usbdevice", "keyboard") < 0) - return -1; - + devtype = "keyboard"; break; + default: + continue; } - break; + + if (lastdev == NULL) { + if (VIR_ALLOC(lastdev) < 0) + goto error; + usbdevices->list = lastdev; + } else { + if (VIR_ALLOC(lastdev->next) < 0) + goto error; + lastdev = lastdev->next; + } + lastdev->type = VIR_CONF_STRING; + if (VIR_STRDUP(lastdev->str, devtype) < 0) + goto error; } } + if (usbdevices->list != NULL) { + if (usbdevices->list->next == NULL) { + /* for compatibility with Xen <= 4.2, use old syntax when + * only one device present */ + if (xenConfigSetString(conf, "usbdevice", usbdevices->list->str) < 0) + goto error; + virConfFreeValue(usbdevices); + } else { + virConfSetValue(conf, "usbdevice", usbdevices); + } + } else { + VIR_FREE(usbdevices); + } }
return 0; + error: + virConfFreeValue(usbdevices); + return -1; }

On Fri, Feb 20, 2015 at 04:10:47PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
In Xen>=4.3, libxl supports new syntax for USB devices: usbdevice=[ "DEVICE", "DEVICE", ... ] Add support for that in xenconfig driver. When only one device is defined, keep using old syntax for backward compatibility.
Cool, thanks for doing this! But I have a "small" nit...
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/xenconfig/xen_common.c | 108 +++++++++++++++++++++++++++++++--------------
xm only supported the usbdevice=DEVICE syntax, but the code in xen_common is used to parse/format both xm and xl config. I think parsing/formating of these devices should be moved to xen-xm and xen-xl.
Also multiple devices are supported only in Xen >= 4.3. I haven't seen any constants for 4.x versions so haven't added new for that. Also names (XEND_CONFIG_VERSION_*) and its place (xenconfig/xen_sxpr.h) suggests it shouldn't be used for xl... Should I add a new version somewhere there anyway? I guess it applies also to other code there (which also doesn't bother with different libxl versions), so I guess I can simply ignore this issue. -- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing?

Marek Marczykowski-Górecki wrote:
On Fri, Feb 20, 2015 at 04:10:47PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
In Xen>=4.3, libxl supports new syntax for USB devices: usbdevice=[ "DEVICE", "DEVICE", ... ] Add support for that in xenconfig driver. When only one device is defined, keep using old syntax for backward compatibility.
Cool, thanks for doing this! But I have a "small" nit...
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/xenconfig/xen_common.c | 108 +++++++++++++++++++++++++++++++--------------
xm only supported the usbdevice=DEVICE syntax, but the code in xen_common is used to parse/format both xm and xl config. I think parsing/formating of these devices should be moved to xen-xm and xen-xl.
Also multiple devices are supported only in Xen >= 4.3. I haven't seen any constants for 4.x versions so haven't added new for that. Also names (XEND_CONFIG_VERSION_*) and its place (xenconfig/xen_sxpr.h) suggests it shouldn't be used for xl...
For the xen-xl config format, I think it is fine to use the LIBXL_HAVE_* pattern for detecting libxl features. My suggestion was to move the usbdevice formating/parsing from xen_common.c to xen_xm.c and xen_xl.c, similar to disk formating/parsing. The impl in xen_xm.c would provide the existing formating/parsing functionality for xen-xm config. The impl in xen_xl.c would format/parse usbdevice as a list if LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST. Regards, Jim
Should I add a new version somewhere there anyway?
I guess it applies also to other code there (which also doesn't bother with different libxl versions), so I guess I can simply ignore this issue.

Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- tests/xlconfigdata/test-fullvirt-multiusb.cfg | 29 ++++++++++++++++ tests/xlconfigdata/test-fullvirt-multiusb.xml | 48 +++++++++++++++++++++++++++ tests/xlconfigtest.c | 1 + 3 files changed, 78 insertions(+) create mode 100755 tests/xlconfigdata/test-fullvirt-multiusb.cfg create mode 100644 tests/xlconfigdata/test-fullvirt-multiusb.xml diff --git a/tests/xlconfigdata/test-fullvirt-multiusb.cfg b/tests/xlconfigdata/test-fullvirt-multiusb.cfg new file mode 100755 index 0000000..a84413d --- /dev/null +++ b/tests/xlconfigdata/test-fullvirt-multiusb.cfg @@ -0,0 +1,29 @@ +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 +hap = 0 +viridian = 0 +localtime = 0 +on_poweroff = "destroy" +on_reboot = "restart" +on_crash = "restart" +device_model = "/usr/lib/xen/bin/qemu-dm" +usb = 1 +usbdevice = [ "mouse", "tablet" ] +sdl = 0 +vnc = 1 +vncunused = 1 +vnclisten = "127.0.0.1" +vncpasswd = "123poi" +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,script=vif-bridge,model=e1000,type=ioemu" ] +parallel = "none" +serial = "none" +disk = [ "/dev/HostVG/XenGuest2,raw,hda,w,backendtype=phy", "/root/boot.iso,raw,hdc,r,backendtype=qdisk,devtype=cdrom" ] diff --git a/tests/xlconfigdata/test-fullvirt-multiusb.xml b/tests/xlconfigdata/test-fullvirt-multiusb.xml new file mode 100644 index 0000000..642c242 --- /dev/null +++ b/tests/xlconfigdata/test-fullvirt-multiusb.xml @@ -0,0 +1,48 @@ +<domain type='xen'> + <name>XenGuest2</name> + <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>592896</memory> + <currentMemory unit='KiB'>403456</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='xenfv'>hvm</type> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> + <boot dev='cdrom'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc' adjustment='reset'/> + <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' type='raw'/> + <source dev='/dev/HostVG/XenGuest2'/> + <target dev='hda' bus='ide'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <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> + <input type='mouse' bus='usb'/> + <input type='tablet' bus='usb'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'> + <listen type='address' address='127.0.0.1'/> + </graphics> + </devices> +</domain> diff --git a/tests/xlconfigtest.c b/tests/xlconfigtest.c index 8c4c82c..6d4aa6d 100644 --- a/tests/xlconfigtest.c +++ b/tests/xlconfigtest.c @@ -215,6 +215,7 @@ mymain(void) DO_TEST("new-disk", 3); DO_TEST("spice", 3); + DO_TEST("fullvirt-multiusb", 3); virObjectUnref(caps); virObjectUnref(xmlopt); -- 1.8.3.1

Marek Marczykowski-Górecki wrote:
From: Marek Marczykowski <marmarek@invisiblethingslab.com>
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - rebase on 1.2.12+ - multiple devices support Changes in v3: - reduce code duplication
src/libxl/libxl_conf.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index b873622..c7108b0 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -749,6 +749,50 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, libxl_defbool_set(&b_info->u.hvm.vnc.enable, 0); libxl_defbool_set(&b_info->u.hvm.sdl.enable, 0);
+ if (def->ninputs) { + for (i = 0; i < def->ninputs; i++) { + if (def->inputs[i]->bus != VIR_DOMAIN_INPUT_BUS_USB) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("libxenlight supports only USB input")); + return -1; + } + } +#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST + if (VIR_ALLOC_N(b_info->u.hvm.usbdevice_list, def->ninputs+1) < 0) + return -1; +#else + if (def->ninputs > 1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("libxenlight supports only one input device")); + return -1; + } +#endif + for (i = 0; i < def->ninputs; i++) { + char **usbdevice;
I'm no C expert, but I think 'char *' is fine, avoiding the subsequent addressof and dereferencing. Regards, Jim
+#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST + usbdevice = &b_info->u.hvm.usbdevice_list[i]; +#else + usbdevice = &b_info->u.hvm.usbdevice; +#endif + switch (def->inputs[i]->type) { + case VIR_DOMAIN_INPUT_TYPE_MOUSE: + VIR_FREE(*usbdevice); + if (VIR_STRDUP(*usbdevice, "mouse") < 0) + return -1; + break; + case VIR_DOMAIN_INPUT_TYPE_TABLET: + VIR_FREE(*usbdevice); + if (VIR_STRDUP(*usbdevice, "tablet") < 0) + return -1; + break; + default: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Unknown input device type")); + return -1; + } + } + } + /* * The following comment and calculation were taken directly from * libxenlight's internal function libxl_get_required_shadow_memory():

On Fri, Feb 20, 2015 at 03:45:02PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
From: Marek Marczykowski <marmarek@invisiblethingslab.com>
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes in v2: - rebase on 1.2.12+ - multiple devices support Changes in v3: - reduce code duplication
src/libxl/libxl_conf.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index b873622..c7108b0 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -749,6 +749,50 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, libxl_defbool_set(&b_info->u.hvm.vnc.enable, 0); libxl_defbool_set(&b_info->u.hvm.sdl.enable, 0);
+ if (def->ninputs) { + for (i = 0; i < def->ninputs; i++) { + if (def->inputs[i]->bus != VIR_DOMAIN_INPUT_BUS_USB) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("libxenlight supports only USB input")); + return -1; + } + } +#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST + if (VIR_ALLOC_N(b_info->u.hvm.usbdevice_list, def->ninputs+1) < 0) + return -1; +#else + if (def->ninputs > 1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("libxenlight supports only one input device")); + return -1; + } +#endif + for (i = 0; i < def->ninputs; i++) { + char **usbdevice;
I'm no C expert, but I think 'char *' is fine, avoiding the subsequent addressof and dereferencing.
Actually no, because VIR_STRDUP is a macro, which takes address of its argument. In case of simple 'char *', the result will be placed in usbdevice instead of original place. IOW the code would behave like this: char *usbdevice; usbdevice = b_info->u.hvm.usbdevice_list[i]; (...) usbdevice = strdup("mouse"); Which of course is not what we want here...
Regards, Jim
+#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST + usbdevice = &b_info->u.hvm.usbdevice_list[i]; +#else + usbdevice = &b_info->u.hvm.usbdevice; +#endif + switch (def->inputs[i]->type) { + case VIR_DOMAIN_INPUT_TYPE_MOUSE: + VIR_FREE(*usbdevice); + if (VIR_STRDUP(*usbdevice, "mouse") < 0) + return -1; + break; + case VIR_DOMAIN_INPUT_TYPE_TABLET: + VIR_FREE(*usbdevice); + if (VIR_STRDUP(*usbdevice, "tablet") < 0) + return -1; + break; + default: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Unknown input device type")); + return -1; + } + } + } + /* * The following comment and calculation were taken directly from * libxenlight's internal function libxl_get_required_shadow_memory():
-- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing?

It will not be possible to detach such device later. Also improve logging in such cases. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_driver.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index ce3a99b..005cc96 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2787,6 +2787,7 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, int actualType; libxl_device_nic nic; int ret = -1; + char mac[VIR_MAC_STRING_BUFLEN]; /* preallocate new slot for device */ if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0) @@ -2801,6 +2802,14 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, actualType = virDomainNetGetActualType(net); + /* -2 means "multiple matches" so then fail also */ + if (virDomainNetFindIdx(vm->def, net) != -1) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("device matching mac address %s already exists"), + virMacAddrFormat(&net->mac, mac)); + return -1; + } + if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) { /* This is really a "smart hostdev", so it should be attached * as a hostdev (the hostdev code will reach over into the @@ -2879,6 +2888,7 @@ libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) virDomainHostdevDefPtr hostdev; virDomainHostdevDefPtr found; virDomainHostdevSubsysPCIPtr pcisrc; + char mac[VIR_MAC_STRING_BUFLEN]; switch (dev->type) { case VIR_DOMAIN_DEVICE_DISK: @@ -2896,6 +2906,12 @@ libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) case VIR_DOMAIN_DEVICE_NET: net = dev->data.net; + if (virDomainNetFindIdx(vmdef, net) >= 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("network device with mac %s already exists."), + virMacAddrFormat(&net->mac, mac)); + return -1; + } if (virDomainNetInsert(vmdef, net)) return -1; dev->data.net = NULL; @@ -3060,8 +3076,18 @@ libxlDomainDetachNetDevice(libxlDriverPrivatePtr driver, char mac[VIR_MAC_STRING_BUFLEN]; int ret = -1; - if ((detachidx = virDomainNetFindIdx(vm->def, net)) < 0) + if ((detachidx = virDomainNetFindIdx(vm->def, net)) < 0) { + if (detachidx == -2) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("multiple devices matching mac address %s found"), + virMacAddrFormat(&net->mac, mac)); + } else { + virReportError(VIR_ERR_OPERATION_FAILED, + _("network device %s not found"), + virMacAddrFormat(&net->mac, mac)); + } return -1; + } detach = vm->def->nets[detachidx]; @@ -3136,6 +3162,7 @@ libxlDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) virDomainHostdevDefPtr hostdev, det_hostdev; virDomainNetDefPtr net; int idx; + char mac[VIR_MAC_STRING_BUFLEN]; switch (dev->type) { case VIR_DOMAIN_DEVICE_DISK: @@ -3150,8 +3177,18 @@ libxlDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) case VIR_DOMAIN_DEVICE_NET: net = dev->data.net; - if ((idx = virDomainNetFindIdx(vmdef, net)) < 0) + if ((idx = virDomainNetFindIdx(vmdef, net)) < 0) { + if (idx == -2) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("multiple devices matching mac address %s found"), + virMacAddrFormat(&dev->data.net->mac, mac)); + } else { + virReportError(VIR_ERR_OPERATION_FAILED, + _("network device %s not found"), + virMacAddrFormat(&dev->data.net->mac, mac)); + } return -1; + } /* this is guaranteed to succeed */ virDomainNetDefFree(virDomainNetRemove(vmdef, idx)); -- 1.8.3.1

Marek Marczykowski-Górecki wrote:
It will not be possible to detach such device later. Also improve logging in such cases.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_driver.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-)
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index ce3a99b..005cc96 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2787,6 +2787,7 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, int actualType; libxl_device_nic nic; int ret = -1; + char mac[VIR_MAC_STRING_BUFLEN];
/* preallocate new slot for device */ if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0) @@ -2801,6 +2802,14 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver,
actualType = virDomainNetGetActualType(net);
+ /* -2 means "multiple matches" so then fail also */
No longer true after commit 2fbae1b2. I think you just want to check if virDomainNetFindIdx() >= 0, meaning the def already contains a net device with the same mac address.
+ if (virDomainNetFindIdx(vm->def, net) != -1) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("device matching mac address %s already exists"), + virMacAddrFormat(&net->mac, mac)); + return -1; + } + if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) { /* This is really a "smart hostdev", so it should be attached * as a hostdev (the hostdev code will reach over into the @@ -2879,6 +2888,7 @@ libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) virDomainHostdevDefPtr hostdev; virDomainHostdevDefPtr found; virDomainHostdevSubsysPCIPtr pcisrc; + char mac[VIR_MAC_STRING_BUFLEN];
switch (dev->type) { case VIR_DOMAIN_DEVICE_DISK: @@ -2896,6 +2906,12 @@ libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
case VIR_DOMAIN_DEVICE_NET: net = dev->data.net; + if (virDomainNetFindIdx(vmdef, net) >= 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("network device with mac %s already exists."), + virMacAddrFormat(&net->mac, mac)); + return -1; + }
Ah, like you've done here :-).
if (virDomainNetInsert(vmdef, net)) return -1; dev->data.net = NULL; @@ -3060,8 +3076,18 @@ libxlDomainDetachNetDevice(libxlDriverPrivatePtr driver, char mac[VIR_MAC_STRING_BUFLEN]; int ret = -1;
- if ((detachidx = virDomainNetFindIdx(vm->def, net)) < 0) + if ((detachidx = virDomainNetFindIdx(vm->def, net)) < 0) { + if (detachidx == -2) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("multiple devices matching mac address %s found"), + virMacAddrFormat(&net->mac, mac)); + } else { + virReportError(VIR_ERR_OPERATION_FAILED, + _("network device %s not found"), + virMacAddrFormat(&net->mac, mac)); + }
virDomainNetFindIdx() handles the error reporting now.
return -1; + }
detach = vm->def->nets[detachidx];
@@ -3136,6 +3162,7 @@ libxlDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) virDomainHostdevDefPtr hostdev, det_hostdev; virDomainNetDefPtr net; int idx; + char mac[VIR_MAC_STRING_BUFLEN];
switch (dev->type) { case VIR_DOMAIN_DEVICE_DISK: @@ -3150,8 +3177,18 @@ libxlDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
case VIR_DOMAIN_DEVICE_NET: net = dev->data.net; - if ((idx = virDomainNetFindIdx(vmdef, net)) < 0) + if ((idx = virDomainNetFindIdx(vmdef, net)) < 0) { + if (idx == -2) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("multiple devices matching mac address %s found"), + virMacAddrFormat(&dev->data.net->mac, mac)); + } else { + virReportError(VIR_ERR_OPERATION_FAILED, + _("network device %s not found"), + virMacAddrFormat(&dev->data.net->mac, mac)); + }
Same here. Regards, Jim

On Thu, Feb 19, 2015 at 11:43:15AM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
It will not be possible to detach such device later. Also improve logging in such cases.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_driver.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-)
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index ce3a99b..005cc96 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2787,6 +2787,7 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, int actualType; libxl_device_nic nic; int ret = -1; + char mac[VIR_MAC_STRING_BUFLEN];
/* preallocate new slot for device */ if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0) @@ -2801,6 +2802,14 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver,
actualType = virDomainNetGetActualType(net);
+ /* -2 means "multiple matches" so then fail also */
No longer true after commit 2fbae1b2. I think you just want to check if virDomainNetFindIdx() >= 0, meaning the def already contains a net device with the same mac address.
But here the error is when the device *is* found, so the opposite case than already reported as an error by virDomainNetFindIdx. Is it correct (harmless) to call virReportError when no error occurred (function returns >=0)? Maybe libvirt should check for duplicated devices at higher level (-> for all drivers in the same place)?
+ if (virDomainNetFindIdx(vm->def, net) != -1) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("device matching mac address %s already exists"), + virMacAddrFormat(&net->mac, mac)); + return -1; + } + if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) { /* This is really a "smart hostdev", so it should be attached * as a hostdev (the hostdev code will reach over into the @@ -2879,6 +2888,7 @@ libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) virDomainHostdevDefPtr hostdev; virDomainHostdevDefPtr found; virDomainHostdevSubsysPCIPtr pcisrc; + char mac[VIR_MAC_STRING_BUFLEN];
switch (dev->type) { case VIR_DOMAIN_DEVICE_DISK: @@ -2896,6 +2906,12 @@ libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
case VIR_DOMAIN_DEVICE_NET: net = dev->data.net; + if (virDomainNetFindIdx(vmdef, net) >= 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("network device with mac %s already exists."), + virMacAddrFormat(&net->mac, mac)); + return -1; + }
Ah, like you've done here :-).
if (virDomainNetInsert(vmdef, net)) return -1; dev->data.net = NULL; @@ -3060,8 +3076,18 @@ libxlDomainDetachNetDevice(libxlDriverPrivatePtr driver, char mac[VIR_MAC_STRING_BUFLEN]; int ret = -1;
- if ((detachidx = virDomainNetFindIdx(vm->def, net)) < 0) + if ((detachidx = virDomainNetFindIdx(vm->def, net)) < 0) { + if (detachidx == -2) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("multiple devices matching mac address %s found"), + virMacAddrFormat(&net->mac, mac)); + } else { + virReportError(VIR_ERR_OPERATION_FAILED, + _("network device %s not found"), + virMacAddrFormat(&net->mac, mac)); + }
virDomainNetFindIdx() handles the error reporting now.
return -1; + }
detach = vm->def->nets[detachidx];
@@ -3136,6 +3162,7 @@ libxlDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) virDomainHostdevDefPtr hostdev, det_hostdev; virDomainNetDefPtr net; int idx; + char mac[VIR_MAC_STRING_BUFLEN];
switch (dev->type) { case VIR_DOMAIN_DEVICE_DISK: @@ -3150,8 +3177,18 @@ libxlDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
case VIR_DOMAIN_DEVICE_NET: net = dev->data.net; - if ((idx = virDomainNetFindIdx(vmdef, net)) < 0) + if ((idx = virDomainNetFindIdx(vmdef, net)) < 0) { + if (idx == -2) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("multiple devices matching mac address %s found"), + virMacAddrFormat(&dev->data.net->mac, mac)); + } else { + virReportError(VIR_ERR_OPERATION_FAILED, + _("network device %s not found"), + virMacAddrFormat(&dev->data.net->mac, mac)); + }
Same here.
Regards, Jim
-- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing?

Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 11:43:15AM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
It will not be possible to detach such device later. Also improve logging in such cases.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_driver.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-)
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index ce3a99b..005cc96 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2787,6 +2787,7 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, int actualType; libxl_device_nic nic; int ret = -1; + char mac[VIR_MAC_STRING_BUFLEN];
/* preallocate new slot for device */ if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0) @@ -2801,6 +2802,14 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver,
actualType = virDomainNetGetActualType(net);
+ /* -2 means "multiple matches" so then fail also */
No longer true after commit 2fbae1b2. I think you just want to check if virDomainNetFindIdx() >= 0, meaning the def already contains a net device with the same mac address.
But here the error is when the device *is* found, so the opposite case than already reported as an error by virDomainNetFindIdx.
If you find an idx >= 0, then the domain def already contains a net device with the same mac address, right? In that case, you report an error and return failure from libxlDomainAttachNetDevice(). Regards, Jim
Is it correct (harmless) to call virReportError when no error occurred (function returns >=0)? Maybe libvirt should check for duplicated devices at higher level (-> for all drivers in the same place)?
+ if (virDomainNetFindIdx(vm->def, net) != -1) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("device matching mac address %s already exists"), + virMacAddrFormat(&net->mac, mac)); + return -1; + } + if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) { /* This is really a "smart hostdev", so it should be attached * as a hostdev (the hostdev code will reach over into the @@ -2879,6 +2888,7 @@ libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) virDomainHostdevDefPtr hostdev; virDomainHostdevDefPtr found; virDomainHostdevSubsysPCIPtr pcisrc; + char mac[VIR_MAC_STRING_BUFLEN];
switch (dev->type) { case VIR_DOMAIN_DEVICE_DISK: @@ -2896,6 +2906,12 @@ libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
case VIR_DOMAIN_DEVICE_NET: net = dev->data.net; + if (virDomainNetFindIdx(vmdef, net) >= 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("network device with mac %s already exists."), + virMacAddrFormat(&net->mac, mac)); + return -1; + }
Ah, like you've done here :-).
if (virDomainNetInsert(vmdef, net)) return -1; dev->data.net = NULL; @@ -3060,8 +3076,18 @@ libxlDomainDetachNetDevice(libxlDriverPrivatePtr driver, char mac[VIR_MAC_STRING_BUFLEN]; int ret = -1;
- if ((detachidx = virDomainNetFindIdx(vm->def, net)) < 0) + if ((detachidx = virDomainNetFindIdx(vm->def, net)) < 0) { + if (detachidx == -2) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("multiple devices matching mac address %s found"), + virMacAddrFormat(&net->mac, mac)); + } else { + virReportError(VIR_ERR_OPERATION_FAILED, + _("network device %s not found"), + virMacAddrFormat(&net->mac, mac)); + }
virDomainNetFindIdx() handles the error reporting now.
return -1; + }
detach = vm->def->nets[detachidx];
@@ -3136,6 +3162,7 @@ libxlDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) virDomainHostdevDefPtr hostdev, det_hostdev; virDomainNetDefPtr net; int idx; + char mac[VIR_MAC_STRING_BUFLEN];
switch (dev->type) { case VIR_DOMAIN_DEVICE_DISK: @@ -3150,8 +3177,18 @@ libxlDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
case VIR_DOMAIN_DEVICE_NET: net = dev->data.net; - if ((idx = virDomainNetFindIdx(vmdef, net)) < 0) + if ((idx = virDomainNetFindIdx(vmdef, net)) < 0) { + if (idx == -2) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("multiple devices matching mac address %s found"), + virMacAddrFormat(&dev->data.net->mac, mac)); + } else { + virReportError(VIR_ERR_OPERATION_FAILED, + _("network device %s not found"), + virMacAddrFormat(&dev->data.net->mac, mac)); + }
Same here.
Regards, Jim

On Thu, Feb 19, 2015 at 01:58:02PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 11:43:15AM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
It will not be possible to detach such device later. Also improve logging in such cases.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_driver.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-)
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index ce3a99b..005cc96 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2787,6 +2787,7 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, int actualType; libxl_device_nic nic; int ret = -1; + char mac[VIR_MAC_STRING_BUFLEN];
/* preallocate new slot for device */ if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0) @@ -2801,6 +2802,14 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver,
actualType = virDomainNetGetActualType(net);
+ /* -2 means "multiple matches" so then fail also */
No longer true after commit 2fbae1b2. I think you just want to check if virDomainNetFindIdx() >= 0, meaning the def already contains a net device with the same mac address.
But here the error is when the device *is* found, so the opposite case than already reported as an error by virDomainNetFindIdx.
If you find an idx >= 0, then the domain def already contains a net device with the same mac address, right? In that case, you report an error and return failure from libxlDomainAttachNetDevice().
Right, but if I do not find one (idx == -1), I will proceed with (possibly successful) adding the device, while the error was already reported by virDomainNetFindIdx. -- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing?

Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 01:58:02PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 11:43:15AM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
It will not be possible to detach such device later. Also improve logging in such cases.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_driver.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-)
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index ce3a99b..005cc96 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2787,6 +2787,7 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, int actualType; libxl_device_nic nic; int ret = -1; + char mac[VIR_MAC_STRING_BUFLEN];
/* preallocate new slot for device */ if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0) @@ -2801,6 +2802,14 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver,
actualType = virDomainNetGetActualType(net);
+ /* -2 means "multiple matches" so then fail also */
No longer true after commit 2fbae1b2. I think you just want to check if virDomainNetFindIdx() >= 0, meaning the def already contains a net device with the same mac address.
But here the error is when the device *is* found, so the opposite case than already reported as an error by virDomainNetFindIdx.
If you find an idx >= 0, then the domain def already contains a net device with the same mac address, right? In that case, you report an error and return failure from libxlDomainAttachNetDevice().
Right, but if I do not find one (idx == -1), I will proceed with (possibly successful) adding the device, while the error was already reported by virDomainNetFindIdx.
Ah, right :-/. Another option: introduce virDomainHasNet() to detect if the domain def already contains the net device. Regards, Jim

Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 01:58:02PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 11:43:15AM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
It will not be possible to detach such device later. Also improve logging in such cases.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- src/libxl/libxl_driver.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-)
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index ce3a99b..005cc96 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2787,6 +2787,7 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, int actualType; libxl_device_nic nic; int ret = -1; + char mac[VIR_MAC_STRING_BUFLEN];
/* preallocate new slot for device */ if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0) @@ -2801,6 +2802,14 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver,
actualType = virDomainNetGetActualType(net);
+ /* -2 means "multiple matches" so then fail also */
No longer true after commit 2fbae1b2. I think you just want to check if virDomainNetFindIdx() >= 0, meaning the def already contains a net device with the same mac address.
But here the error is when the device *is* found, so the opposite case than already reported as an error by virDomainNetFindIdx.
If you find an idx >= 0, then the domain def already contains a net device with the same mac address, right? In that case, you report an error and return failure from libxlDomainAttachNetDevice().
Right, but if I do not find one (idx == -1), I will proceed with (possibly successful) adding the device, while the error was already reported by virDomainNetFindIdx.
Ah, right :-/.
Another option: introduce virDomainHasNet() to detect if the domain def already contains the net device.
A better option would be to fix this in libxl, for the benefit of other libxl apps. Regards, Jim

On Thu, Feb 19, 2015 at 03:10:13PM -0700, Jim Fehlig wrote:
Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 01:58:02PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 11:43:15AM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
> It will not be possible to detach such device later. Also improve > logging in such cases. > > Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> > --- > src/libxl/libxl_driver.c | 41 +++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 39 insertions(+), 2 deletions(-) > > diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c > index ce3a99b..005cc96 100644 > --- a/src/libxl/libxl_driver.c > +++ b/src/libxl/libxl_driver.c > @@ -2787,6 +2787,7 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, > int actualType; > libxl_device_nic nic; > int ret = -1; > + char mac[VIR_MAC_STRING_BUFLEN]; > > /* preallocate new slot for device */ > if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0) > @@ -2801,6 +2802,14 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, > > actualType = virDomainNetGetActualType(net); > > + /* -2 means "multiple matches" so then fail also */ > > > > No longer true after commit 2fbae1b2. I think you just want to check if virDomainNetFindIdx() >= 0, meaning the def already contains a net device with the same mac address.
But here the error is when the device *is* found, so the opposite case than already reported as an error by virDomainNetFindIdx.
If you find an idx >= 0, then the domain def already contains a net device with the same mac address, right? In that case, you report an error and return failure from libxlDomainAttachNetDevice().
Right, but if I do not find one (idx == -1), I will proceed with (possibly successful) adding the device, while the error was already reported by virDomainNetFindIdx.
Ah, right :-/.
Another option: introduce virDomainHasNet() to detect if the domain def already contains the net device.
A better option would be to fix this in libxl, for the benefit of other libxl apps.
Actually libxl has no problem with duplicated mac addresses, its libvirt that makes problem. Such device cannot be removed, because net devices are identified by mac address, so can be unambitiously specified in case of duplicates. -- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing?

Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 03:10:13PM -0700, Jim Fehlig wrote:
Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 01:58:02PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 11:43:15AM -0700, Jim Fehlig wrote:
> Marek Marczykowski-Górecki wrote: > > > > >> It will not be possible to detach such device later. Also improve >> logging in such cases. >> >> Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> >> --- >> src/libxl/libxl_driver.c | 41 +++++++++++++++++++++++++++++++++++++++-- >> 1 file changed, 39 insertions(+), 2 deletions(-) >> >> diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c >> index ce3a99b..005cc96 100644 >> --- a/src/libxl/libxl_driver.c >> +++ b/src/libxl/libxl_driver.c >> @@ -2787,6 +2787,7 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, >> int actualType; >> libxl_device_nic nic; >> int ret = -1; >> + char mac[VIR_MAC_STRING_BUFLEN]; >> >> /* preallocate new slot for device */ >> if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0) >> @@ -2801,6 +2802,14 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, >> >> actualType = virDomainNetGetActualType(net); >> >> + /* -2 means "multiple matches" so then fail also */ >> >> >> >> >> > No longer true after commit 2fbae1b2. I think you just want to check if > virDomainNetFindIdx() >= 0, meaning the def already contains a net > device with the same mac address. > > > > But here the error is when the device *is* found, so the opposite case than already reported as an error by virDomainNetFindIdx.
If you find an idx >= 0, then the domain def already contains a net device with the same mac address, right? In that case, you report an error and return failure from libxlDomainAttachNetDevice().
Right, but if I do not find one (idx == -1), I will proceed with (possibly successful) adding the device, while the error was already reported by virDomainNetFindIdx.
Ah, right :-/.
Another option: introduce virDomainHasNet() to detect if the domain def already contains the net device.
A better option would be to fix this in libxl, for the benefit of other libxl apps.
Actually libxl has no problem with duplicated mac addresses, its libvirt that makes problem.
Yeah, it appears duplicate mac addresses are only valid if on different PCI devices. Back to virDomainHasNet? :-) Or checking for the duplicate directly in libxlDomainAttachNetDevice()? Regards, Jim

On Thu, Feb 19, 2015 at 03:58:30PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 03:10:13PM -0700, Jim Fehlig wrote:
Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 01:58:02PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote: > On Thu, Feb 19, 2015 at 11:43:15AM -0700, Jim Fehlig wrote: >> Marek Marczykowski-Górecki wrote: >>> It will not be possible to detach such device later. Also improve >>> logging in such cases. >>> >>> Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> >>> --- >>> src/libxl/libxl_driver.c | 41 +++++++++++++++++++++++++++++++++++++++-- >>> 1 file changed, 39 insertions(+), 2 deletions(-) >>> >>> diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c >>> index ce3a99b..005cc96 100644 >>> --- a/src/libxl/libxl_driver.c >>> +++ b/src/libxl/libxl_driver.c >>> @@ -2787,6 +2787,7 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, >>> int actualType; >>> libxl_device_nic nic; >>> int ret = -1; >>> + char mac[VIR_MAC_STRING_BUFLEN]; >>> >>> /* preallocate new slot for device */ >>> if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0) >>> @@ -2801,6 +2802,14 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, >>> >>> actualType = virDomainNetGetActualType(net); >>> >>> + /* -2 means "multiple matches" so then fail also */ >>> >>> >>> >>> >>> >> No longer true after commit 2fbae1b2. I think you just want to check if >> virDomainNetFindIdx() >= 0, meaning the def already contains a net >> device with the same mac address. >> >> >> >> > But here the error is when the device *is* found, so the opposite case > than already reported as an error by virDomainNetFindIdx. > > > If you find an idx >= 0, then the domain def already contains a net device with the same mac address, right? In that case, you report an error and return failure from libxlDomainAttachNetDevice().
Right, but if I do not find one (idx == -1), I will proceed with (possibly successful) adding the device, while the error was already reported by virDomainNetFindIdx.
Ah, right :-/.
Another option: introduce virDomainHasNet() to detect if the domain def already contains the net device.
A better option would be to fix this in libxl, for the benefit of other libxl apps.
Actually libxl has no problem with duplicated mac addresses, its libvirt that makes problem.
Yeah, it appears duplicate mac addresses are only valid if on different PCI devices.
Is that true for libvirt generally (all drivers)?
Back to virDomainHasNet? :-) Or checking for the duplicate directly in libxlDomainAttachNetDevice()?
What do you mean by "directly"? This is exactly what my patch did (until virDomainNetFindIdx stopped reporting duplicates). -- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing?

Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 03:58:30PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 03:10:13PM -0700, Jim Fehlig wrote:
Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 01:58:02PM -0700, Jim Fehlig wrote:
> Marek Marczykowski-Górecki wrote: > >> On Thu, Feb 19, 2015 at 11:43:15AM -0700, Jim Fehlig wrote: >> >>> Marek Marczykowski-Górecki wrote: >>> >>>> It will not be possible to detach such device later. Also improve >>>> logging in such cases. >>>> >>>> Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> >>>> --- >>>> src/libxl/libxl_driver.c | 41 +++++++++++++++++++++++++++++++++++++++-- >>>> 1 file changed, 39 insertions(+), 2 deletions(-) >>>> >>>> diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c >>>> index ce3a99b..005cc96 100644 >>>> --- a/src/libxl/libxl_driver.c >>>> +++ b/src/libxl/libxl_driver.c >>>> @@ -2787,6 +2787,7 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, >>>> int actualType; >>>> libxl_device_nic nic; >>>> int ret = -1; >>>> + char mac[VIR_MAC_STRING_BUFLEN]; >>>> >>>> /* preallocate new slot for device */ >>>> if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0) >>>> @@ -2801,6 +2802,14 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, >>>> >>>> actualType = virDomainNetGetActualType(net); >>>> >>>> + /* -2 means "multiple matches" so then fail also */ >>>> >>>> >>>> >>>> >>>> >>>> >>> No longer true after commit 2fbae1b2. I think you just want to check if >>> virDomainNetFindIdx() >= 0, meaning the def already contains a net >>> device with the same mac address. >>> >>> >>> >>> >>> >> But here the error is when the device *is* found, so the opposite case >> than already reported as an error by virDomainNetFindIdx. >> >> >> >> > If you find an idx >= 0, then the domain def already contains a net > device with the same mac address, right? In that case, you report an > error and return failure from libxlDomainAttachNetDevice(). > > > > Right, but if I do not find one (idx == -1), I will proceed with (possibly successful) adding the device, while the error was already reported by virDomainNetFindIdx.
Ah, right :-/.
Another option: introduce virDomainHasNet() to detect if the domain def already contains the net device.
A better option would be to fix this in libxl, for the benefit of other libxl apps.
Actually libxl has no problem with duplicated mac addresses, its libvirt that makes problem.
Yeah, it appears duplicate mac addresses are only valid if on different PCI devices.
Is that true for libvirt generally (all drivers)?
Back to virDomainHasNet? :-) Or checking for the duplicate directly in libxlDomainAttachNetDevice()?
What do you mean by "directly"? This is exactly what my patch did (until virDomainNetFindIdx stopped reporting duplicates).
I mean coding up the search for an existing mac directly in libxlDomainAttachNetDevice(). E.g. static int libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, libxlDomainObjPrivatePtr priv, virDomainObjPtr vm, virDomainNetDefPtr net) { int actualType; libxl_device_nic nic; int ret = -1; size_t i; virDomainDefPtr def = vm->def; for (i = 0; i < def->nnets; i++) { if (virMacAddrCmp(&def->nets[i]->mac, &net->mac) == 0) error; } ... } Regards, Jim

On Thu, Feb 19, 2015 at 06:13:01PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 03:58:30PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 03:10:13PM -0700, Jim Fehlig wrote:
Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
> On Thu, Feb 19, 2015 at 01:58:02PM -0700, Jim Fehlig wrote: > >> Marek Marczykowski-Górecki wrote: >> >>> On Thu, Feb 19, 2015 at 11:43:15AM -0700, Jim Fehlig wrote: >>> >>>> Marek Marczykowski-Górecki wrote: >>>> >>>>> It will not be possible to detach such device later. Also improve >>>>> logging in such cases. >>>>> >>>>> Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> >>>>> --- >>>>> src/libxl/libxl_driver.c | 41 +++++++++++++++++++++++++++++++++++++++-- >>>>> 1 file changed, 39 insertions(+), 2 deletions(-) >>>>> >>>>> diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c >>>>> index ce3a99b..005cc96 100644 >>>>> --- a/src/libxl/libxl_driver.c >>>>> +++ b/src/libxl/libxl_driver.c >>>>> @@ -2787,6 +2787,7 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, >>>>> int actualType; >>>>> libxl_device_nic nic; >>>>> int ret = -1; >>>>> + char mac[VIR_MAC_STRING_BUFLEN]; >>>>> >>>>> /* preallocate new slot for device */ >>>>> if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0) >>>>> @@ -2801,6 +2802,14 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, >>>>> >>>>> actualType = virDomainNetGetActualType(net); >>>>> >>>>> + /* -2 means "multiple matches" so then fail also */ >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> >>>> No longer true after commit 2fbae1b2. I think you just want to check if >>>> virDomainNetFindIdx() >= 0, meaning the def already contains a net >>>> device with the same mac address. >>>> >>>> >>>> >>>> >>>> >>> But here the error is when the device *is* found, so the opposite case >>> than already reported as an error by virDomainNetFindIdx. >>> >>> >>> >>> >> If you find an idx >= 0, then the domain def already contains a net >> device with the same mac address, right? In that case, you report an >> error and return failure from libxlDomainAttachNetDevice(). >> >> >> >> > Right, but if I do not find one (idx == -1), I will proceed with > (possibly successful) adding the device, while the error was already > reported by virDomainNetFindIdx. > > > > Ah, right :-/.
Another option: introduce virDomainHasNet() to detect if the domain def already contains the net device.
A better option would be to fix this in libxl, for the benefit of other libxl apps.
Actually libxl has no problem with duplicated mac addresses, its libvirt that makes problem.
Yeah, it appears duplicate mac addresses are only valid if on different PCI devices.
Is that true for libvirt generally (all drivers)?
Back to virDomainHasNet? :-) Or checking for the duplicate directly in libxlDomainAttachNetDevice()?
What do you mean by "directly"? This is exactly what my patch did (until virDomainNetFindIdx stopped reporting duplicates).
I mean coding up the search for an existing mac directly in libxlDomainAttachNetDevice(). E.g.
I see, IMO its better with (reusable...) virDomainHasNet.
static int libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, libxlDomainObjPrivatePtr priv, virDomainObjPtr vm, virDomainNetDefPtr net) { int actualType; libxl_device_nic nic; int ret = -1; size_t i; virDomainDefPtr def = vm->def;
for (i = 0; i < def->nnets; i++) { if (virMacAddrCmp(&def->nets[i]->mac, &net->mac) == 0) error; } ... }
Regards, Jim
-- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing?

Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- There was a discussion about calling virDomainDefCheckABIStability. The use case I have for this is to start multiple domains from the same savefile. This require changing: - UUID - name - IP address Those are exactly type of changes blocked by virDomainDefCheckABIStability. Perhaps some "permissive" mode should be introduced to the virDomainDefCheckABIStability function? src/libxl/libxl_driver.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 005cc96..7539d33 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -1456,11 +1456,6 @@ libxlDomainRestoreFlags(virConnectPtr conn, const char *from, #endif virCheckFlags(VIR_DOMAIN_SAVE_PAUSED, -1); - if (dxml) { - virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", - _("xml modification unsupported")); - return -1; - } fd = libxlDomainSaveImageOpen(driver, cfg, from, &def, &hdr); if (fd < 0) @@ -1469,6 +1464,18 @@ libxlDomainRestoreFlags(virConnectPtr conn, const char *from, if (virDomainRestoreFlagsEnsureACL(conn, def) < 0) goto cleanup_unlock; + if (dxml) { + virDomainDefPtr def2 = NULL; + + if (!(def2 = virDomainDefParseString(dxml, cfg->caps, driver->xmlopt, + 1 << VIR_DOMAIN_VIRT_XEN, + VIR_DOMAIN_XML_INACTIVE))) { + goto cleanup; + } + virDomainDefFree(def); + def = def2; + } + if (!(vm = virDomainObjListAdd(driver->domains, def, driver->xmlopt, VIR_DOMAIN_OBJ_LIST_ADD_LIVE | -- 1.8.3.1

Marek Marczykowski-Górecki wrote:
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> ---
There was a discussion about calling virDomainDefCheckABIStability. The use case I have for this is to start multiple domains from the same savefile.
Interesting use case...
This require changing: - UUID - name - IP address
Did you mean mac address? I don't see where the virtDomain*CheckABIStability() functions check for changes to IP addresses.
Those are exactly type of changes blocked by virDomainDefCheckABIStability. Perhaps some "permissive" mode should be introduced to the virDomainDefCheckABIStability function?
I'd like to hear what others think about this proposal. Are UUID and name really part of a domain's ABI? Regards, Jim
src/libxl/libxl_driver.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 005cc96..7539d33 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -1456,11 +1456,6 @@ libxlDomainRestoreFlags(virConnectPtr conn, const char *from, #endif
virCheckFlags(VIR_DOMAIN_SAVE_PAUSED, -1); - if (dxml) { - virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", - _("xml modification unsupported")); - return -1; - }
fd = libxlDomainSaveImageOpen(driver, cfg, from, &def, &hdr); if (fd < 0) @@ -1469,6 +1464,18 @@ libxlDomainRestoreFlags(virConnectPtr conn, const char *from, if (virDomainRestoreFlagsEnsureACL(conn, def) < 0) goto cleanup_unlock;
+ if (dxml) { + virDomainDefPtr def2 = NULL; + + if (!(def2 = virDomainDefParseString(dxml, cfg->caps, driver->xmlopt, + 1 << VIR_DOMAIN_VIRT_XEN, + VIR_DOMAIN_XML_INACTIVE))) { + goto cleanup; + } + virDomainDefFree(def); + def = def2; + } + if (!(vm = virDomainObjListAdd(driver->domains, def, driver->xmlopt, VIR_DOMAIN_OBJ_LIST_ADD_LIVE |

On Thu, Feb 19, 2015 at 11:59:38AM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> ---
There was a discussion about calling virDomainDefCheckABIStability. The use case I have for this is to start multiple domains from the same savefile.
Interesting use case...
If you're curious about details, it is used for DisposableVMs in Qubes OS: http://theinvisiblethings.blogspot.com/2010/06/disposable-vms.html Basically to speedup domain startup (with some preloaded applications etc). Domain state is discarded after its termination (disk image is read-only).
This require changing: - UUID - name - IP address
Did you mean mac address? I don't see where the virtDomain*CheckABIStability() functions check for changes to IP addresses.
Of course, I mean MAC address (in addition to IP address).
Those are exactly type of changes blocked by virDomainDefCheckABIStability. Perhaps some "permissive" mode should be introduced to the virDomainDefCheckABIStability function?
I'd like to hear what others think about this proposal. Are UUID and name really part of a domain's ABI?
At least by the implementation of virDomainDefCheckABIStability... Comment says this is to not confuse domain during migration.
Regards, Jim
src/libxl/libxl_driver.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 005cc96..7539d33 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -1456,11 +1456,6 @@ libxlDomainRestoreFlags(virConnectPtr conn, const char *from, #endif
virCheckFlags(VIR_DOMAIN_SAVE_PAUSED, -1); - if (dxml) { - virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", - _("xml modification unsupported")); - return -1; - }
fd = libxlDomainSaveImageOpen(driver, cfg, from, &def, &hdr); if (fd < 0) @@ -1469,6 +1464,18 @@ libxlDomainRestoreFlags(virConnectPtr conn, const char *from, if (virDomainRestoreFlagsEnsureACL(conn, def) < 0) goto cleanup_unlock;
+ if (dxml) { + virDomainDefPtr def2 = NULL; + + if (!(def2 = virDomainDefParseString(dxml, cfg->caps, driver->xmlopt, + 1 << VIR_DOMAIN_VIRT_XEN, + VIR_DOMAIN_XML_INACTIVE))) { + goto cleanup; + } + virDomainDefFree(def); + def = def2; + } + if (!(vm = virDomainObjListAdd(driver->domains, def, driver->xmlopt, VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
-- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing?

Xen have feature of having device model in separate domain (called stub domain). Add a 'type' attribute to 'emulator' element to allow selecting such a configuration. Emulator path is still used for qemu running in dom0 (if any). Libxl currently do not allow to select stubdomain path. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- I think it would be good idea to introduce the same change to capabilities XML. The problem is I can't include domain_conf.h from capabilities.h, so probably that enum declaration needs to be moved to capabilities.h. Is it the right way? Or it should be done somehow different? docs/formatdomain.html.in | 14 ++++++++++++++ docs/schemas/domaincommon.rng | 23 ++++++++++++++++++++++- src/conf/domain_conf.c | 36 ++++++++++++++++++++++++++++++++++-- src/conf/domain_conf.h | 9 +++++++++ src/libxl/libxl_conf.c | 17 +++++++++++++++++ 5 files changed, 96 insertions(+), 3 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 38c42d5..4f539e2 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1652,6 +1652,20 @@ The <a href="formatcaps.html">capabilities XML</a> specifies the recommended default emulator to use for each particular domain type / architecture combination. + + <span class="since">Since 1.2.13</span>, the <code>emulator</code> + element may contain <code>type</code> attribute. Possible values are: + <dl> + <dt><code>type='default'</code></dt> + <dd>Equivalent to not setting <code>type</code> attribute at all. + </dd> + + <dt><code>type='stubdom'</code></dt> + <dd>Launch emulator in stub domain (Xen only). The emulator path + still indicate which binary is used in dom0 - there is no control + which binary is used as a stub domain. + </dd> + </dl> </dd> </dl> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index a4321f1..2a12073 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2519,7 +2519,28 @@ --> <define name="emulator"> <element name="emulator"> - <ref name="absFilePath"/> + <choice> + <group> + <optional> + <attribute name="type"> + <choice> + <value>qemu</value> + <value>stubdom</value> + </choice> + </attribute> + </optional> + <ref name="absFilePath"/> + </group> + <group> + <attribute name="type"> + <choice> + <value>qemu</value> + <value>stubdom</value> + </choice> + </attribute> + <empty/> + </group> + </choice> </element> </define> <!-- diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 17b699a..c268091 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -741,6 +741,10 @@ VIR_ENUM_IMPL(virDomainDiskTray, VIR_DOMAIN_DISK_TRAY_LAST, "closed", "open"); +VIR_ENUM_IMPL(virDomainEmulatorType, VIR_DOMAIN_EMULATOR_TYPE_LAST, + "qemu", + "stubdom"); + VIR_ENUM_IMPL(virDomainRNGModel, VIR_DOMAIN_RNG_MODEL_LAST, "virtio"); @@ -13712,6 +13716,14 @@ virDomainDefParseXML(xmlDocPtr xml, } def->emulator = virXPathString("string(./devices/emulator[1])", ctxt); + if ((tmp = virXPathString("string(./devices/emulator/@type)", ctxt))) { + def->emulator_type = virDomainEmulatorTypeTypeFromString(tmp); + VIR_FREE(tmp); + if (def->emulator_type < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unknown emulator type '%s'"), tmp); + } + } /* analysis of the disk devices */ if ((n = virXPathNodeSet("./devices/disk", ctxt, &nodes)) < 0) @@ -15690,6 +15702,14 @@ virDomainDefCheckABIStability(virDomainDefPtr src, goto error; } + if (src->emulator_type != dst->emulator_type) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target domain emulator type %s does not match source %s"), + virDomainEmulatorTypeTypeToString(dst->emulator_type), + virDomainEmulatorTypeTypeToString(src->emulator_type)); + goto error; + } + if (!virDomainDefFeaturesCheckABIStability(src, dst)) goto error; @@ -19893,8 +19913,20 @@ virDomainDefFormatInternal(virDomainDefPtr def, virBufferAddLit(buf, "<devices>\n"); virBufferAdjustIndent(buf, 2); - virBufferEscapeString(buf, "<emulator>%s</emulator>\n", - def->emulator); + if (def->emulator || + def->emulator_type != VIR_DOMAIN_EMULATOR_TYPE_DEFAULT) { + virBufferAddLit(buf, "<emulator"); + if (def->emulator_type != VIR_DOMAIN_EMULATOR_TYPE_DEFAULT) { + virBufferAsprintf(buf, " type='%s'", + virDomainEmulatorTypeTypeToString(def->emulator_type)); + } + if (!def->emulator) { + virBufferAddLit(buf, "/>\n"); + } else { + virBufferEscapeString(buf, ">%s</emulator>\n", + def->emulator); + } + } for (n = 0; n < def->ndisks; n++) if (virDomainDiskDefFormat(buf, def->disks[n], flags) < 0) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 28c6920..38b9037 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1918,6 +1918,13 @@ struct _virBlkioDevice { }; typedef enum { + VIR_DOMAIN_EMULATOR_TYPE_DEFAULT, + VIR_DOMAIN_EMULATOR_TYPE_STUBDOM, + + VIR_DOMAIN_EMULATOR_TYPE_LAST +} virDomainEmulatorType; + +typedef enum { VIR_DOMAIN_RNG_MODEL_VIRTIO, VIR_DOMAIN_RNG_MODEL_LAST @@ -2083,6 +2090,7 @@ struct _virDomainDef { virDomainOSDef os; char *emulator; + virDomainEmulatorType emulator_type; /* These three options are of type virTristateSwitch, * except VIR_DOMAIN_FEATURE_CAPABILITIES that is of type * virDomainCapabilitiesPolicy */ @@ -2841,6 +2849,7 @@ VIR_ENUM_DECL(virDomainGraphicsSpiceMouseMode) VIR_ENUM_DECL(virDomainGraphicsVNCSharePolicy) VIR_ENUM_DECL(virDomainHyperv) VIR_ENUM_DECL(virDomainKVM) +VIR_ENUM_DECL(virDomainEmulatorType) VIR_ENUM_DECL(virDomainRNGModel) VIR_ENUM_DECL(virDomainRNGBackend) VIR_ENUM_DECL(virDomainTPMModel) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index b1131ea..a84ce09 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -768,6 +768,23 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, b_info->device_model_version = libxlDomainGetEmulatorType(def); } + /* In case of stubdom there will be two qemu instances: + * - in stubdom (libxl uses hardcoded path for this one), + * - in dom0 as a backend for stubdom (if needed). + * Emulator path control only the second one. It makes a perfect sense + * to use <emulator type='stubdom'/> (yes, without emulator path). + */ + if (def->emulator_type == VIR_DOMAIN_EMULATOR_TYPE_STUBDOM) + libxl_defbool_set(&b_info->device_model_stubdomain, 1); + + if (def->os.cmdline && def->os.cmdline[0]) { + b_info->extra_hvm = virStringSplit(def->os.cmdline, " ", 0); + if (b_info->extra_hvm == NULL) { + virReportOOMError(); + return -1; + } + } + if (def->nserials) { if (def->nserials > 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, -- 1.8.3.1

Marek Marczykowski-Górecki wrote:
Xen have feature of having device model in separate domain (called stub domain). Add a 'type' attribute to 'emulator' element to allow selecting such a configuration.
Or maybe 'mode', describing the mode in which the emulator runs: as a process or as a VM.
Emulator path is still used for qemu running in dom0 (if any). Libxl currently do not allow to select stubdomain path.
That seems to overload a single <emulator>. Would it be better to have multiple <emulators>? E.g. <emulator>/usr/lib/xen/bin/qemu-system-i386</emulator> <emulator mode='stubdomain'>/usr/lib/xen/bin/stubdom-dm</emulator>
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> ---
I think it would be good idea to introduce the same change to capabilities XML. The problem is I can't include domain_conf.h from capabilities.h, so probably that enum declaration needs to be moved to capabilities.h. Is it the right way? Or it should be done somehow different?
docs/formatdomain.html.in | 14 ++++++++++++++ docs/schemas/domaincommon.rng | 23 ++++++++++++++++++++++- src/conf/domain_conf.c | 36 ++++++++++++++++++++++++++++++++++-- src/conf/domain_conf.h | 9 +++++++++ src/libxl/libxl_conf.c | 17 +++++++++++++++++ 5 files changed, 96 insertions(+), 3 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 38c42d5..4f539e2 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1652,6 +1652,20 @@ The <a href="formatcaps.html">capabilities XML</a> specifies the recommended default emulator to use for each particular domain type / architecture combination. + + <span class="since">Since 1.2.13</span>, the <code>emulator</code> + element may contain <code>type</code> attribute. Possible values are: + <dl> + <dt><code>type='default'</code></dt> + <dd>Equivalent to not setting <code>type</code> attribute at all. + </dd> + + <dt><code>type='stubdom'</code></dt> + <dd>Launch emulator in stub domain (Xen only). The emulator path + still indicate which binary is used in dom0 - there is no control + which binary is used as a stub domain. + </dd> + </dl> </dd> </dl>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index a4321f1..2a12073 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2519,7 +2519,28 @@ --> <define name="emulator"> <element name="emulator"> - <ref name="absFilePath"/> + <choice> + <group> + <optional> + <attribute name="type"> + <choice> + <value>qemu</value> + <value>stubdom</value> + </choice> + </attribute> + </optional> + <ref name="absFilePath"/> + </group> + <group> + <attribute name="type"> + <choice> + <value>qemu</value> + <value>stubdom</value> + </choice> + </attribute> + <empty/> + </group> + </choice> </element> </define> <!-- diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 17b699a..c268091 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -741,6 +741,10 @@ VIR_ENUM_IMPL(virDomainDiskTray, VIR_DOMAIN_DISK_TRAY_LAST, "closed", "open");
+VIR_ENUM_IMPL(virDomainEmulatorType, VIR_DOMAIN_EMULATOR_TYPE_LAST, + "qemu", + "stubdom"); + VIR_ENUM_IMPL(virDomainRNGModel, VIR_DOMAIN_RNG_MODEL_LAST, "virtio"); @@ -13712,6 +13716,14 @@ virDomainDefParseXML(xmlDocPtr xml, }
def->emulator = virXPathString("string(./devices/emulator[1])", ctxt); + if ((tmp = virXPathString("string(./devices/emulator/@type)", ctxt))) { + def->emulator_type = virDomainEmulatorTypeTypeFromString(tmp); + VIR_FREE(tmp); + if (def->emulator_type < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unknown emulator type '%s'"), tmp); + } + }
/* analysis of the disk devices */ if ((n = virXPathNodeSet("./devices/disk", ctxt, &nodes)) < 0) @@ -15690,6 +15702,14 @@ virDomainDefCheckABIStability(virDomainDefPtr src, goto error; }
+ if (src->emulator_type != dst->emulator_type) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target domain emulator type %s does not match source %s"), + virDomainEmulatorTypeTypeToString(dst->emulator_type), + virDomainEmulatorTypeTypeToString(src->emulator_type)); + goto error; + } + if (!virDomainDefFeaturesCheckABIStability(src, dst)) goto error;
@@ -19893,8 +19913,20 @@ virDomainDefFormatInternal(virDomainDefPtr def, virBufferAddLit(buf, "<devices>\n"); virBufferAdjustIndent(buf, 2);
- virBufferEscapeString(buf, "<emulator>%s</emulator>\n", - def->emulator); + if (def->emulator || + def->emulator_type != VIR_DOMAIN_EMULATOR_TYPE_DEFAULT) { + virBufferAddLit(buf, "<emulator"); + if (def->emulator_type != VIR_DOMAIN_EMULATOR_TYPE_DEFAULT) { + virBufferAsprintf(buf, " type='%s'", + virDomainEmulatorTypeTypeToString(def->emulator_type)); + } + if (!def->emulator) { + virBufferAddLit(buf, "/>\n"); + } else { + virBufferEscapeString(buf, ">%s</emulator>\n", + def->emulator); + } + }
for (n = 0; n < def->ndisks; n++) if (virDomainDiskDefFormat(buf, def->disks[n], flags) < 0) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 28c6920..38b9037 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1918,6 +1918,13 @@ struct _virBlkioDevice { };
typedef enum { + VIR_DOMAIN_EMULATOR_TYPE_DEFAULT, + VIR_DOMAIN_EMULATOR_TYPE_STUBDOM, + + VIR_DOMAIN_EMULATOR_TYPE_LAST +} virDomainEmulatorType; + +typedef enum { VIR_DOMAIN_RNG_MODEL_VIRTIO,
VIR_DOMAIN_RNG_MODEL_LAST @@ -2083,6 +2090,7 @@ struct _virDomainDef {
virDomainOSDef os; char *emulator; + virDomainEmulatorType emulator_type; /* These three options are of type virTristateSwitch, * except VIR_DOMAIN_FEATURE_CAPABILITIES that is of type * virDomainCapabilitiesPolicy */ @@ -2841,6 +2849,7 @@ VIR_ENUM_DECL(virDomainGraphicsSpiceMouseMode) VIR_ENUM_DECL(virDomainGraphicsVNCSharePolicy) VIR_ENUM_DECL(virDomainHyperv) VIR_ENUM_DECL(virDomainKVM) +VIR_ENUM_DECL(virDomainEmulatorType) VIR_ENUM_DECL(virDomainRNGModel) VIR_ENUM_DECL(virDomainRNGBackend) VIR_ENUM_DECL(virDomainTPMModel) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index b1131ea..a84ce09 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -768,6 +768,23 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, b_info->device_model_version = libxlDomainGetEmulatorType(def); }
+ /* In case of stubdom there will be two qemu instances: + * - in stubdom (libxl uses hardcoded path for this one), + * - in dom0 as a backend for stubdom (if needed).
Your comment here provoked my thinking above about supporting multiple <emulator>s. ISTM there should be an <emulator> device for each of these qemu instances.
+ * Emulator path control only the second one. It makes a perfect sense + * to use <emulator type='stubdom'/> (yes, without emulator path).
I'm not so sure. Maybe we should first add support in libxl for specifying a stubdomain emulator path. Regards, Jim
+ */ + if (def->emulator_type == VIR_DOMAIN_EMULATOR_TYPE_STUBDOM) + libxl_defbool_set(&b_info->device_model_stubdomain, 1); + + if (def->os.cmdline && def->os.cmdline[0]) { + b_info->extra_hvm = virStringSplit(def->os.cmdline, " ", 0); + if (b_info->extra_hvm == NULL) { + virReportOOMError(); + return -1; + } + } + if (def->nserials) { if (def->nserials > 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED,

On Thu, Feb 19, 2015 at 01:45:52PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
Xen have feature of having device model in separate domain (called stub domain). Add a 'type' attribute to 'emulator' element to allow selecting such a configuration.
Or maybe 'mode', describing the mode in which the emulator runs: as a process or as a VM.
Emulator path is still used for qemu running in dom0 (if any). Libxl currently do not allow to select stubdomain path.
That seems to overload a single <emulator>. Would it be better to have multiple <emulators>? E.g.
<emulator>/usr/lib/xen/bin/qemu-system-i386</emulator> <emulator mode='stubdomain'>/usr/lib/xen/bin/stubdom-dm</emulator>
So the existence of <emulator mode='stubdomain'/> would enable this feature? What if someday the default will be to run stubdomain emulator - how the user can disable it in such case?
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> ---
I think it would be good idea to introduce the same change to capabilities XML. The problem is I can't include domain_conf.h from capabilities.h, so probably that enum declaration needs to be moved to capabilities.h. Is it the right way? Or it should be done somehow different?
Any hints here? IMHO it would be hardly useful without mentioning possible values in capabilities XML... In case of multiple <emulator>s, should them be just listed (possible values), or the whole possible combinations (which 'process' emulator with which 'stubdomain' one if applicable)? I think the later option is better.
docs/formatdomain.html.in | 14 ++++++++++++++ docs/schemas/domaincommon.rng | 23 ++++++++++++++++++++++- src/conf/domain_conf.c | 36 ++++++++++++++++++++++++++++++++++-- src/conf/domain_conf.h | 9 +++++++++ src/libxl/libxl_conf.c | 17 +++++++++++++++++ 5 files changed, 96 insertions(+), 3 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 38c42d5..4f539e2 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1652,6 +1652,20 @@ The <a href="formatcaps.html">capabilities XML</a> specifies the recommended default emulator to use for each particular domain type / architecture combination. + + <span class="since">Since 1.2.13</span>, the <code>emulator</code> + element may contain <code>type</code> attribute. Possible values are: + <dl> + <dt><code>type='default'</code></dt> + <dd>Equivalent to not setting <code>type</code> attribute at all. + </dd> + + <dt><code>type='stubdom'</code></dt> + <dd>Launch emulator in stub domain (Xen only). The emulator path + still indicate which binary is used in dom0 - there is no control + which binary is used as a stub domain. + </dd> + </dl> </dd> </dl>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index a4321f1..2a12073 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2519,7 +2519,28 @@ --> <define name="emulator"> <element name="emulator"> - <ref name="absFilePath"/> + <choice> + <group> + <optional> + <attribute name="type"> + <choice> + <value>qemu</value> + <value>stubdom</value> + </choice> + </attribute> + </optional> + <ref name="absFilePath"/> + </group> + <group> + <attribute name="type"> + <choice> + <value>qemu</value> + <value>stubdom</value> + </choice> + </attribute> + <empty/> + </group> + </choice> </element> </define> <!-- diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 17b699a..c268091 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -741,6 +741,10 @@ VIR_ENUM_IMPL(virDomainDiskTray, VIR_DOMAIN_DISK_TRAY_LAST, "closed", "open");
+VIR_ENUM_IMPL(virDomainEmulatorType, VIR_DOMAIN_EMULATOR_TYPE_LAST, + "qemu", + "stubdom"); + VIR_ENUM_IMPL(virDomainRNGModel, VIR_DOMAIN_RNG_MODEL_LAST, "virtio"); @@ -13712,6 +13716,14 @@ virDomainDefParseXML(xmlDocPtr xml, }
def->emulator = virXPathString("string(./devices/emulator[1])", ctxt); + if ((tmp = virXPathString("string(./devices/emulator/@type)", ctxt))) { + def->emulator_type = virDomainEmulatorTypeTypeFromString(tmp); + VIR_FREE(tmp); + if (def->emulator_type < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unknown emulator type '%s'"), tmp); + } + }
/* analysis of the disk devices */ if ((n = virXPathNodeSet("./devices/disk", ctxt, &nodes)) < 0) @@ -15690,6 +15702,14 @@ virDomainDefCheckABIStability(virDomainDefPtr src, goto error; }
+ if (src->emulator_type != dst->emulator_type) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target domain emulator type %s does not match source %s"), + virDomainEmulatorTypeTypeToString(dst->emulator_type), + virDomainEmulatorTypeTypeToString(src->emulator_type)); + goto error; + } + if (!virDomainDefFeaturesCheckABIStability(src, dst)) goto error;
@@ -19893,8 +19913,20 @@ virDomainDefFormatInternal(virDomainDefPtr def, virBufferAddLit(buf, "<devices>\n"); virBufferAdjustIndent(buf, 2);
- virBufferEscapeString(buf, "<emulator>%s</emulator>\n", - def->emulator); + if (def->emulator || + def->emulator_type != VIR_DOMAIN_EMULATOR_TYPE_DEFAULT) { + virBufferAddLit(buf, "<emulator"); + if (def->emulator_type != VIR_DOMAIN_EMULATOR_TYPE_DEFAULT) { + virBufferAsprintf(buf, " type='%s'", + virDomainEmulatorTypeTypeToString(def->emulator_type)); + } + if (!def->emulator) { + virBufferAddLit(buf, "/>\n"); + } else { + virBufferEscapeString(buf, ">%s</emulator>\n", + def->emulator); + } + }
for (n = 0; n < def->ndisks; n++) if (virDomainDiskDefFormat(buf, def->disks[n], flags) < 0) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 28c6920..38b9037 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1918,6 +1918,13 @@ struct _virBlkioDevice { };
typedef enum { + VIR_DOMAIN_EMULATOR_TYPE_DEFAULT, + VIR_DOMAIN_EMULATOR_TYPE_STUBDOM, + + VIR_DOMAIN_EMULATOR_TYPE_LAST +} virDomainEmulatorType; + +typedef enum { VIR_DOMAIN_RNG_MODEL_VIRTIO,
VIR_DOMAIN_RNG_MODEL_LAST @@ -2083,6 +2090,7 @@ struct _virDomainDef {
virDomainOSDef os; char *emulator; + virDomainEmulatorType emulator_type; /* These three options are of type virTristateSwitch, * except VIR_DOMAIN_FEATURE_CAPABILITIES that is of type * virDomainCapabilitiesPolicy */ @@ -2841,6 +2849,7 @@ VIR_ENUM_DECL(virDomainGraphicsSpiceMouseMode) VIR_ENUM_DECL(virDomainGraphicsVNCSharePolicy) VIR_ENUM_DECL(virDomainHyperv) VIR_ENUM_DECL(virDomainKVM) +VIR_ENUM_DECL(virDomainEmulatorType) VIR_ENUM_DECL(virDomainRNGModel) VIR_ENUM_DECL(virDomainRNGBackend) VIR_ENUM_DECL(virDomainTPMModel) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index b1131ea..a84ce09 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -768,6 +768,23 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, b_info->device_model_version = libxlDomainGetEmulatorType(def); }
+ /* In case of stubdom there will be two qemu instances: + * - in stubdom (libxl uses hardcoded path for this one), + * - in dom0 as a backend for stubdom (if needed).
Your comment here provoked my thinking above about supporting multiple <emulator>s. ISTM there should be an <emulator> device for each of these qemu instances.
+ * Emulator path control only the second one. It makes a perfect sense + * to use <emulator type='stubdom'/> (yes, without emulator path).
I'm not so sure. Maybe we should first add support in libxl for specifying a stubdomain emulator path.
Yes, this would be a good idea (especially when someone implements alternative stubdomain emulator). But Xen <=4.5 still should be somehow handled - I think it can be plain <emulator mode='stubdomain'/> (without a path). Possibly rejecting a path if not supported by underlying libxl. -- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing?

On Thu, Feb 19, 2015 at 10:19:22PM +0100, Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 01:45:52PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
Xen have feature of having device model in separate domain (called stub domain). Add a 'type' attribute to 'emulator' element to allow selecting such a configuration.
Or maybe 'mode', describing the mode in which the emulator runs: as a process or as a VM.
Emulator path is still used for qemu running in dom0 (if any). Libxl currently do not allow to select stubdomain path.
That seems to overload a single <emulator>. Would it be better to have multiple <emulators>? E.g.
<emulator>/usr/lib/xen/bin/qemu-system-i386</emulator> <emulator mode='stubdomain'>/usr/lib/xen/bin/stubdom-dm</emulator>
So the existence of <emulator mode='stubdomain'/> would enable this feature? What if someday the default will be to run stubdomain emulator - how the user can disable it in such case?
Any thoughts here? I can simply implement your proposition and not worry about disabling stubdom emulator (as in no case it is enabled by default, *for now*). Or another idea - you can not use the same binary as either process or stubdomain, so maybe it would be better to introduce separate element, instead or reusing <emulator>? Plain <stubdomain>? Or <emustubdomain>? In this case also capabilities XML would be easier to understand. I want to sent next iteration of this patch series (I've already handled other issues). Or maybe should I split stubdomain out of this series and send what I have ready for now?
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> ---
I think it would be good idea to introduce the same change to capabilities XML. The problem is I can't include domain_conf.h from capabilities.h, so probably that enum declaration needs to be moved to capabilities.h. Is it the right way? Or it should be done somehow different?
Any hints here? IMHO it would be hardly useful without mentioning possible values in capabilities XML...
In case of multiple <emulator>s, should them be just listed (possible values), or the whole possible combinations (which 'process' emulator with which 'stubdomain' one if applicable)? I think the later option is better.
In case of new element instead of reused <emulator>, this problem would be much easier to solve. (...)
+ /* In case of stubdom there will be two qemu instances: + * - in stubdom (libxl uses hardcoded path for this one), + * - in dom0 as a backend for stubdom (if needed).
Your comment here provoked my thinking above about supporting multiple <emulator>s. ISTM there should be an <emulator> device for each of these qemu instances.
+ * Emulator path control only the second one. It makes a perfect sense + * to use <emulator type='stubdom'/> (yes, without emulator path).
I'm not so sure. Maybe we should first add support in libxl for specifying a stubdomain emulator path.
Yes, this would be a good idea (especially when someone implements alternative stubdomain emulator). But Xen <=4.5 still should be somehow handled - I think it can be plain <emulator mode='stubdomain'/> (without a path). Possibly rejecting a path if not supported by underlying libxl.
-- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing?

On Thu, Feb 19, 2015 at 10:19:22PM +0100, Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 01:45:52PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
Xen have feature of having device model in separate domain (called stub domain). Add a 'type' attribute to 'emulator' element to allow selecting such a configuration.
Or maybe 'mode', describing the mode in which the emulator runs: as a process or as a VM.
Emulator path is still used for qemu running in dom0 (if any). Libxl currently do not allow to select stubdomain path.
That seems to overload a single <emulator>. Would it be better to have multiple <emulators>? E.g.
<emulator>/usr/lib/xen/bin/qemu-system-i386</emulator> <emulator mode='stubdomain'>/usr/lib/xen/bin/stubdom-dm</emulator>
So the existence of <emulator mode='stubdomain'/> would enable this feature? What if someday the default will be to run stubdomain emulator - how the user can disable it in such case?
This suggests to me we need to have two separate controls. First an attribute / element somewhere saying what device mode is used, and the second (optionally) saying what the path to the stubdom emulator is. eg no stubdomain: <devices> <emulator>/usr/lib/xen/bin/qemu-system-i386</emulator> ... </devices> Stubdomain with default path <devices> <emulator>/usr/lib/xen/bin/qemu-system-i386</emulator> <stubdomain enabled="yes|no"/> </devices> Stubdomain with custom path <devices> <emulator>/usr/lib/xen/bin/qemu-system-i386</emulator> <stubdomain enabled="yes|no"> <emulator>/usr/lib/xen/bin/stubdom-dm</emulator> </stubdomain> </devices> We can of course not worry about this 3rd option until libxl actually supports this. So, just implement <stubdomain enabled="yes|no"/> for now. If <stubdomain> is not listed in the XML from the application, the XML post-parse callback can be used by the hypervisor to fill in the default either <stubdomain enabled="yes"/> or <stubdomain enabled="no"/> as appropriate. So that copes with xen changing its default in the future Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On Wed, Mar 04, 2015 at 08:34:26PM +0000, Daniel P. Berrange wrote:
On Thu, Feb 19, 2015 at 10:19:22PM +0100, Marek Marczykowski-Górecki wrote:
On Thu, Feb 19, 2015 at 01:45:52PM -0700, Jim Fehlig wrote:
Marek Marczykowski-Górecki wrote:
Xen have feature of having device model in separate domain (called stub domain). Add a 'type' attribute to 'emulator' element to allow selecting such a configuration.
Or maybe 'mode', describing the mode in which the emulator runs: as a process or as a VM.
Emulator path is still used for qemu running in dom0 (if any). Libxl currently do not allow to select stubdomain path.
That seems to overload a single <emulator>. Would it be better to have multiple <emulators>? E.g.
<emulator>/usr/lib/xen/bin/qemu-system-i386</emulator> <emulator mode='stubdomain'>/usr/lib/xen/bin/stubdom-dm</emulator>
So the existence of <emulator mode='stubdomain'/> would enable this feature? What if someday the default will be to run stubdomain emulator - how the user can disable it in such case?
This suggests to me we need to have two separate controls. First an attribute / element somewhere saying what device mode is used, and the second (optionally) saying what the path to the stubdom emulator is.
eg no stubdomain:
<devices> <emulator>/usr/lib/xen/bin/qemu-system-i386</emulator> ... </devices>
Stubdomain with default path
<devices> <emulator>/usr/lib/xen/bin/qemu-system-i386</emulator> <stubdomain enabled="yes|no"/> </devices>
Stubdomain with custom path
<devices> <emulator>/usr/lib/xen/bin/qemu-system-i386</emulator> <stubdomain enabled="yes|no"> <emulator>/usr/lib/xen/bin/stubdom-dm</emulator> </stubdomain> </devices>
I like this approach :)
We can of course not worry about this 3rd option until libxl actually supports this. So, just implement <stubdomain enabled="yes|no"/> for now. If <stubdomain> is not listed in the XML from the application, the XML post-parse callback can be used by the hypervisor to fill in the default either <stubdomain enabled="yes"/> or <stubdomain enabled="no"/> as appropriate. So that copes with xen changing its default in the future
I see libvirt has cool virTristateBool type, which I will use here. So the lack of <stubdomain> element will mean "use hypervisor default". As in many other places I think. -- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing?

Handle features supported only on xen: driver domains, qemu in stubdomain. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- tests/Makefile.am | 9 +- tests/domainschematest | 2 +- tests/xlxml2xmldata/xlxml2xml-hvm-stubdom.xml | 41 +++++ tests/xlxml2xmldata/xlxml2xml-hvm.xml | 40 +++++ tests/xlxml2xmldata/xlxml2xml-network-bridged.xml | 38 +++++ .../xlxml2xml-network-driver-domain.xml | 38 +++++ tests/xlxml2xmldata/xlxml2xml-network-routed.xml | 39 +++++ tests/xlxml2xmldata/xlxml2xml-pv.xml | 38 +++++ tests/xlxml2xmltest.c | 189 +++++++++++++++++++++ 9 files changed, 431 insertions(+), 3 deletions(-) create mode 100644 tests/xlxml2xmldata/xlxml2xml-hvm-stubdom.xml create mode 100644 tests/xlxml2xmldata/xlxml2xml-hvm.xml create mode 100644 tests/xlxml2xmldata/xlxml2xml-network-bridged.xml create mode 100644 tests/xlxml2xmldata/xlxml2xml-network-driver-domain.xml create mode 100644 tests/xlxml2xmldata/xlxml2xml-network-routed.xml create mode 100644 tests/xlxml2xmldata/xlxml2xml-pv.xml create mode 100644 tests/xlxml2xmltest.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 938270c..48648b9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -85,6 +85,7 @@ EXTRA_DIST = \ domainsnapshotxml2xmlout \ fchostdata \ interfaceschemadata \ + xlxml2xmldata \ lxcconf2xmldata \ lxcxml2xmldata \ lxcxml2xmloutdata \ @@ -230,7 +231,7 @@ test_programs += xml2sexprtest sexpr2xmltest \ endif WITH_XEN if WITH_LIBXL -test_programs += xlconfigtest +test_programs += xlconfigtest xlxml2xmltest endif WITH_LIBXL if WITH_QEMU @@ -515,8 +516,12 @@ xlconfigtest_SOURCES = \ xlconfigtest.c testutilsxen.c testutilsxen.h \ testutils.c testutils.h xlconfigtest_LDADD =$(libxl_LDADDS) +xlxml2xmltest_SOURCES = \ + xlxml2xmltest.c testutilsxen.c testutilsxen.h \ + testutils.c testutils.h +xlxml2xmltest_LDADD =$(libxl_LDADDS) else ! WITH_LIBXL -EXTRA_DIST += xlconfigtest.c +EXTRA_DIST += xlconfigtest.c xlxml2xmltest.c endif ! WITH_LIBXL QEMUMONITORTESTUTILS_SOURCES = \ diff --git a/tests/domainschematest b/tests/domainschematest index ba90180..18b442b 100755 --- a/tests/domainschematest +++ b/tests/domainschematest @@ -8,7 +8,7 @@ DIRS="" DIRS="$DIRS domainschemadata qemuxml2argvdata sexpr2xmldata" DIRS="$DIRS xmconfigdata xml2sexprdata qemuxml2xmloutdata" DIRS="$DIRS lxcxml2xmldata lxcxml2xmloutdata" -DIRS="$DIRS bhyvexml2argvdata" +DIRS="$DIRS bhyvexml2argvdata xlxml2xmldata" SCHEMA="domain.rng" check_schema "$DIRS" "$SCHEMA" diff --git a/tests/xlxml2xmldata/xlxml2xml-hvm-stubdom.xml b/tests/xlxml2xmldata/xlxml2xml-hvm-stubdom.xml new file mode 100644 index 0000000..ed6440c --- /dev/null +++ b/tests/xlxml2xmldata/xlxml2xml-hvm-stubdom.xml @@ -0,0 +1,41 @@ +<domain type='xen'> + <name>testhvm</name> + <uuid>a3d3fa04-dc23-4136-9eab-b579d2930817</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>2</vcpu> + <os> + <type arch='x86_64' machine='xenfv'>hvm</type> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> + <boot dev='cdrom'/> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + <viridian/> + </features> + <clock offset='variable' adjustment='0' basis='localtime'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>destroy</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator type='stubdom'>/usr/lib/xen/bin/qemu-dm</emulator> + <disk type='file' device='disk'> + <driver name='file'/> + <source file='/var/lib/libvirt/images/testhvm/root.img'/> + <target dev='xvda' bus='xen'/> + </disk> + <disk type='file' device='disk'> + <driver name='file'/> + <source file='/var/lib/libvirt/images/testhvm/private.img'/> + <target dev='xvdb' bus='xen'/> + </disk> + <interface type='network'> + <mac address='00:16:3e:5e:6c:09'/> + <source network='default'/> + </interface> + <input type='tablet' bus='usb'/> + </devices> +</domain> diff --git a/tests/xlxml2xmldata/xlxml2xml-hvm.xml b/tests/xlxml2xmldata/xlxml2xml-hvm.xml new file mode 100644 index 0000000..95d9b84 --- /dev/null +++ b/tests/xlxml2xmldata/xlxml2xml-hvm.xml @@ -0,0 +1,40 @@ +<domain type='xen'> + <name>testhvm</name> + <uuid>a3d3fa04-dc23-4136-9eab-b579d2930817</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>2</vcpu> + <os> + <type arch='x86_64' machine='xenfv'>hvm</type> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> + <boot dev='cdrom'/> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + <viridian/> + </features> + <clock offset='variable' adjustment='0' basis='localtime'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>destroy</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <disk type='file' device='disk'> + <driver name='file'/> + <source file='/var/lib/libvirt/images/testhvm/root.img'/> + <target dev='xvda' bus='xen'/> + </disk> + <disk type='file' device='disk'> + <driver name='file'/> + <source file='/var/lib/libvirt/images/testhvm/private.img'/> + <target dev='xvdb' bus='xen'/> + </disk> + <interface type='network'> + <mac address='00:16:3e:5e:6c:09'/> + <source network='default'/> + </interface> + <input type='tablet' bus='usb'/> + </devices> +</domain> diff --git a/tests/xlxml2xmldata/xlxml2xml-network-bridged.xml b/tests/xlxml2xmldata/xlxml2xml-network-bridged.xml new file mode 100644 index 0000000..a6b8f59 --- /dev/null +++ b/tests/xlxml2xmldata/xlxml2xml-network-bridged.xml @@ -0,0 +1,38 @@ +<domain type='xen'> + <name>testvm</name> + <uuid>900e3685-4998-41ad-a2c9-e496a5ed40a4</uuid> + <memory unit='KiB'>4096000</memory> + <currentMemory unit='KiB'>409600</currentMemory> + <vcpu placement='static'>2</vcpu> + <os> + <type arch='x86_64' machine='xenpv'>linux</type> + <kernel>/boot/vmlinuz-3.12.37-1</kernel> + <initrd>/boot/initramfs-3.12.37-1.img</initrd> + <cmdline>root=/dev/xvda ro nomodeset console=hvc0 rd_NO_PLYMOUTH 3</cmdline> + </os> + <clock offset='utc' adjustment='reset'> + <timer name='tsc' mode='native'/> + </clock> + <on_poweroff>destroy</on_poweroff> + <on_reboot>destroy</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <disk type='file' device='disk'> + <driver name='file'/> + <source file='/var/lib/libvirt/images/testvm/root.img'/> + <target dev='xvda' bus='xen'/> + </disk> + <disk type='block' device='disk'> + <driver name='file'/> + <source dev='/var/lib/libvirt/images/testvm/home.img'/> + <target dev='xvdb' bus='xen'/> + </disk> + <interface type='bridge'> + <mac address='00:16:3e:5e:6c:09'/> + <source bridge='xenbr0'/> + </interface> + <console type='pty'> + <target type='xen' port='0'/> + </console> + </devices> +</domain> diff --git a/tests/xlxml2xmldata/xlxml2xml-network-driver-domain.xml b/tests/xlxml2xmldata/xlxml2xml-network-driver-domain.xml new file mode 100644 index 0000000..31c0437 --- /dev/null +++ b/tests/xlxml2xmldata/xlxml2xml-network-driver-domain.xml @@ -0,0 +1,38 @@ +<domain type='xen'> + <name>testvm</name> + <uuid>900e3685-4998-41ad-a2c9-e496a5ed40a4</uuid> + <memory unit='KiB'>4096000</memory> + <currentMemory unit='KiB'>409600</currentMemory> + <vcpu placement='static'>2</vcpu> + <os> + <type arch='x86_64' machine='xenpv'>linux</type> + <kernel>/boot/vmlinuz-3.12.37-1</kernel> + <initrd>/boot/initramfs-3.12.37-1.img</initrd> + <cmdline>root=/dev/xvda ro nomodeset console=hvc0 rd_NO_PLYMOUTH 3</cmdline> + </os> + <clock offset='utc' adjustment='reset'> + <timer name='tsc' mode='native'/> + </clock> + <on_poweroff>destroy</on_poweroff> + <on_reboot>destroy</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <disk type='file' device='disk'> + <driver name='file'/> + <source file='/var/lib/libvirt/images/testvm/root.img'/> + <target dev='xvda' bus='xen'/> + </disk> + <disk type='block' device='disk'> + <driver name='file'/> + <source dev='/var/lib/libvirt/images/testvm/home.img'/> + <target dev='xvdb' bus='xen'/> + </disk> + <interface type='bridge'> + <mac address='00:16:3e:5e:6c:09'/> + <source bridge='xenbr0' domain='netvm'/> + </interface> + <console type='pty'> + <target type='xen' port='0'/> + </console> + </devices> +</domain> diff --git a/tests/xlxml2xmldata/xlxml2xml-network-routed.xml b/tests/xlxml2xmldata/xlxml2xml-network-routed.xml new file mode 100644 index 0000000..fac9d8d --- /dev/null +++ b/tests/xlxml2xmldata/xlxml2xml-network-routed.xml @@ -0,0 +1,39 @@ +<domain type='xen'> + <name>testvm</name> + <uuid>900e3685-4998-41ad-a2c9-e496a5ed40a4</uuid> + <memory unit='KiB'>4096000</memory> + <currentMemory unit='KiB'>409600</currentMemory> + <vcpu placement='static'>2</vcpu> + <os> + <type arch='x86_64' machine='xenpv'>linux</type> + <kernel>/boot/vmlinuz-3.12.37-1</kernel> + <initrd>/boot/initramfs-3.12.37-1.img</initrd> + <cmdline>root=/dev/xvda ro nomodeset console=hvc0 rd_NO_PLYMOUTH 3</cmdline> + </os> + <clock offset='utc' adjustment='reset'> + <timer name='tsc' mode='native'/> + </clock> + <on_poweroff>destroy</on_poweroff> + <on_reboot>destroy</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <disk type='file' device='disk'> + <driver name='file'/> + <source file='/var/lib/libvirt/images/testvm/root.img'/> + <target dev='xvda' bus='xen'/> + </disk> + <disk type='block' device='disk'> + <driver name='file'/> + <source dev='/var/lib/libvirt/images/testvm/home.img'/> + <target dev='xvdb' bus='xen'/> + </disk> + <interface type='ethernet'> + <mac address='00:16:3e:5e:6c:09'/> + <ip address='192.168.0.1' family='ipv4'/> + <script path='vif-route'/> + </interface> + <console type='pty'> + <target type='xen' port='0'/> + </console> + </devices> +</domain> diff --git a/tests/xlxml2xmldata/xlxml2xml-pv.xml b/tests/xlxml2xmldata/xlxml2xml-pv.xml new file mode 100644 index 0000000..b937b8b --- /dev/null +++ b/tests/xlxml2xmldata/xlxml2xml-pv.xml @@ -0,0 +1,38 @@ +<domain type='xen'> + <name>testvm</name> + <uuid>900e3685-4998-41ad-a2c9-e496a5ed40a4</uuid> + <memory unit='KiB'>4096000</memory> + <currentMemory unit='KiB'>409600</currentMemory> + <vcpu placement='static'>2</vcpu> + <os> + <type arch='x86_64' machine='xenpv'>linux</type> + <kernel>/boot/vmlinuz-3.12.37-1</kernel> + <initrd>/boot/initramfs-3.12.37-1.img</initrd> + <cmdline>root=/dev/xvda ro nomodeset console=hvc0 rd_NO_PLYMOUTH 3</cmdline> + </os> + <clock offset='utc' adjustment='reset'> + <timer name='tsc' mode='native'/> + </clock> + <on_poweroff>destroy</on_poweroff> + <on_reboot>destroy</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <disk type='file' device='disk'> + <driver name='file'/> + <source file='/var/lib/libvirt/images/testvm/root.img'/> + <target dev='xvda' bus='xen'/> + </disk> + <disk type='block' device='disk'> + <driver name='file'/> + <source dev='/var/lib/libvirt/images/testvm/home.img'/> + <target dev='xvdb' bus='xen'/> + </disk> + <interface type='network'> + <mac address='00:16:3e:5e:6c:09'/> + <source network='default'/> + </interface> + <console type='pty'> + <target type='xen' port='0'/> + </console> + </devices> +</domain> diff --git a/tests/xlxml2xmltest.c b/tests/xlxml2xmltest.c new file mode 100644 index 0000000..131e43b --- /dev/null +++ b/tests/xlxml2xmltest.c @@ -0,0 +1,189 @@ +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include <sys/types.h> +#include <fcntl.h> + +#include "testutils.h" + +#ifdef WITH_LIBXL + +# include "internal.h" +# include "libxl/libxl_conf.h" +# include "libxl/libxl_domain.h" +# include "testutilsxen.h" +# include "virstring.h" + +# define VIR_FROM_THIS VIR_FROM_NONE + +static virCapsPtr caps; +static virDomainXMLOptionPtr xmlopt; + +static int +testCompareXMLToXMLFiles(const char *inxml, const char *outxml, bool live) +{ + char *inXmlData = NULL; + char *outXmlData = NULL; + char *actual = NULL; + int ret = -1; + virDomainDefPtr def = NULL; + unsigned int parse_flags = live ? 0 : VIR_DOMAIN_DEF_PARSE_INACTIVE; + unsigned int format_flags = VIR_DOMAIN_DEF_FORMAT_SECURE; + if (!live) + format_flags |= VIR_DOMAIN_DEF_FORMAT_INACTIVE; + + if (virtTestLoadFile(inxml, &inXmlData) < 0) + goto fail; + if (virtTestLoadFile(outxml, &outXmlData) < 0) + goto fail; + + if (!(def = virDomainDefParseString(inXmlData, caps, xmlopt, + 1 << VIR_DOMAIN_VIRT_XEN, parse_flags))) + goto fail; + + if (!virDomainDefCheckABIStability(def, def)) { + fprintf(stderr, "ABI stability check failed on %s", inxml); + goto fail; + } + + if (!(actual = virDomainDefFormat(def, format_flags))) + goto fail; + + if (STRNEQ(outXmlData, actual)) { + virtTestDifferenceFull(stderr, outXmlData, outxml, actual, inxml); + goto fail; + } + + ret = 0; + fail: + VIR_FREE(inXmlData); + VIR_FREE(outXmlData); + VIR_FREE(actual); + virDomainDefFree(def); + return ret; +} + +enum { + WHEN_INACTIVE = 1, + WHEN_ACTIVE = 2, + WHEN_EITHER = 3, +}; + +struct testInfo { + const char *name; + bool different; + int when; +}; + +static int +testCompareXMLToXMLHelper(const void *data) +{ + const struct testInfo *info = data; + char *xml_in = NULL; + char *xml_out = NULL; + char *xml_out_active = NULL; + char *xml_out_inactive = NULL; + int ret = -1; + + if (virAsprintf(&xml_in, "%s/xlxml2xmldata/xlxml2xml-%s.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&xml_out, "%s/xlxml2xmldata/xlxml2xml-%s-out.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&xml_out_active, + "%s/xlxml2xmldata/xlxml2xml-%s-active.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&xml_out_inactive, + "%s/xlxml2xmldata/xlxml2xml-%s-inactive.xml", + abs_srcdir, info->name) < 0) + goto cleanup; + + if ((info->when & WHEN_INACTIVE)) { + char *out; + if (!info->different) + out = xml_in; + else if (virFileExists(xml_out_inactive)) + out = xml_out_inactive; + else + out = xml_out; + + if (testCompareXMLToXMLFiles(xml_in, out, false) < 0) + goto cleanup; + } + + if ((info->when & WHEN_ACTIVE)) { + char *out; + if (!info->different) + out = xml_in; + else if (virFileExists(xml_out_active)) + out = xml_out_active; + else + out = xml_out; + + if (testCompareXMLToXMLFiles(xml_in, out, true) < 0) + goto cleanup; + } + + ret = 0; + + cleanup: + VIR_FREE(xml_in); + VIR_FREE(xml_out); + VIR_FREE(xml_out_active); + VIR_FREE(xml_out_inactive); + return ret; +} + + +static int +mymain(void) +{ + int ret = 0; + + if ((caps = testXLInitCaps()) == NULL) + return EXIT_FAILURE; + + if (!(xmlopt = libxlCreateXMLConf())) + return EXIT_FAILURE; + +# define DO_TEST_FULL(name, is_different, when) \ + do { \ + const struct testInfo info = {name, is_different, when}; \ + if (virtTestRun("LibXL XML-2-XML " name, \ + testCompareXMLToXMLHelper, &info) < 0) \ + ret = -1; \ + } while (0) + +# define DO_TEST(name) \ + DO_TEST_FULL(name, false, WHEN_EITHER) + +# define DO_TEST_DIFFERENT(name) \ + DO_TEST_FULL(name, true, WHEN_EITHER) + + DO_TEST("hvm"); + DO_TEST("pv"); + DO_TEST("hvm-stubdom"); + DO_TEST("network-bridged"); + DO_TEST("network-routed"); + DO_TEST("network-driver-domain"); + + virObjectUnref(caps); + virObjectUnref(xmlopt); + + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +VIRT_TEST_MAIN(mymain) + +#else + +int +main(void) +{ + return EXIT_AM_SKIP; +} + +#endif /* WITH_LIBXL */ -- 1.8.3.1
participants (4)
-
Daniel P. Berrange
-
Eric Blake
-
Jim Fehlig
-
Marek Marczykowski-Górecki