2013-09-04 05:43:00 +00:00
|
|
|
/*
|
|
|
|
* libxl_conf.c: libxl configuration management
|
|
|
|
*
|
2016-06-07 15:39:34 +00:00
|
|
|
* Copyright (C) 2012-2014, 2016 Red Hat, Inc.
|
2013-09-04 05:43:00 +00:00
|
|
|
* Copyright (c) 2011-2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
2012-02-02 22:47:04 +00:00
|
|
|
* Copyright (C) 2011 Univention GmbH.
|
2011-02-10 22:42:34 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2011-03-29 12:24:05 +00:00
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Jim Fehlig <jfehlig@novell.com>
|
2011-05-26 15:09:01 +00:00
|
|
|
* Markus Groß <gross@univention.de>
|
2011-02-10 22:42:34 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <regex.h>
|
|
|
|
#include <libxl.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
|
|
|
#include "internal.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2017-02-01 00:10:34 +00:00
|
|
|
#include "c-ctype.h"
|
2011-02-10 22:42:34 +00:00
|
|
|
#include "datatypes.h"
|
2013-09-09 15:15:15 +00:00
|
|
|
#include "virconf.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
#include "virfile.h"
|
2012-11-26 16:28:56 +00:00
|
|
|
#include "virstring.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-13 18:01:25 +00:00
|
|
|
#include "viruuid.h"
|
2014-09-19 16:32:43 +00:00
|
|
|
#include "vircommand.h"
|
2017-07-05 10:19:43 +00:00
|
|
|
#include "virsocketaddr.h"
|
2013-08-30 17:18:31 +00:00
|
|
|
#include "libxl_domain.h"
|
2011-02-10 22:42:34 +00:00
|
|
|
#include "libxl_conf.h"
|
2012-11-26 16:28:56 +00:00
|
|
|
#include "libxl_utils.h"
|
2012-12-13 15:25:48 +00:00
|
|
|
#include "virstoragefile.h"
|
2016-04-04 17:31:29 +00:00
|
|
|
#include "secret_util.h"
|
2017-04-24 13:06:59 +00:00
|
|
|
#include "cpu/cpu.h"
|
2017-12-07 02:27:45 +00:00
|
|
|
#include "xen_common.h"
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_LIBXL
|
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("libxl.libxl_conf");
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2013-08-30 20:52:14 +00:00
|
|
|
static virClassPtr libxlDriverConfigClass;
|
|
|
|
static void libxlDriverConfigDispose(void *obj);
|
|
|
|
|
|
|
|
static int libxlConfigOnceInit(void)
|
|
|
|
{
|
|
|
|
if (!(libxlDriverConfigClass = virClassNew(virClassForObject(),
|
|
|
|
"libxlDriverConfig",
|
|
|
|
sizeof(libxlDriverConfig),
|
|
|
|
libxlDriverConfigDispose)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_ONCE_GLOBAL_INIT(libxlConfig)
|
|
|
|
|
|
|
|
static void
|
|
|
|
libxlDriverConfigDispose(void *obj)
|
|
|
|
{
|
|
|
|
libxlDriverConfigPtr cfg = obj;
|
|
|
|
|
|
|
|
virObjectUnref(cfg->caps);
|
|
|
|
libxl_ctx_free(cfg->ctx);
|
2017-01-09 15:20:50 +00:00
|
|
|
libxlLoggerFree(cfg->logger);
|
2013-08-30 20:52:14 +00:00
|
|
|
|
|
|
|
VIR_FREE(cfg->configDir);
|
|
|
|
VIR_FREE(cfg->autostartDir);
|
|
|
|
VIR_FREE(cfg->logDir);
|
|
|
|
VIR_FREE(cfg->stateDir);
|
|
|
|
VIR_FREE(cfg->libDir);
|
|
|
|
VIR_FREE(cfg->saveDir);
|
2014-02-19 23:09:36 +00:00
|
|
|
VIR_FREE(cfg->autoDumpDir);
|
2015-04-14 20:38:46 +00:00
|
|
|
VIR_FREE(cfg->lockManagerName);
|
libxl: channels support
And allow libxl to handle channel element which creates a Xen
console visible to the guest as a low-bandwitdh communication
channel. If type is PTY we also fetch the tty after boot using
libxl_channel_getinfo to fetch the tty path. On socket case,
we autogenerate a path if not specified in the XML. Path autogenerated
is slightly different from qemu driver: qemu stores also on
"channels/target" but it creates then a directory per domain with
each channel target name. libxl doesn't appear to have a clear
definition of private files associated with each domain, so for
simplicity we do it slightly different. On qemu each autogenerated
channel goes like:
channels/target/<domain-name>/<target name>
Whereas for libxl:
channels/target/<domain-name>-<target name>
Should note that if path is not specified it won't persist,
existing only on live XML, unless user had initially specified it.
Since support for libxl channels only came on Xen >= 4.5 we therefore
need to conditionally compile it with LIBXL_HAVE_DEVICE_CHANNEL.
After this patch and having a qemu guest agent:
$ cat domain.xml | grep -a1 channel | head -n 5 | tail -n 4
<channel type='unix'>
<source mode='bind' path='/tmp/channel'/>
<target type='xen' name='org.qemu.guest_agent.0'/>
</channel>
$ virsh create domain.xml
$ echo '{"execute":"guest-network-get-interfaces"}' | socat
stdio,ignoreeof unix-connect:/tmp/channel
{"execute":"guest-network-get-interfaces"}
{"return": [{"name": "lo", "ip-addresses": [{"ip-address-type": "ipv4",
"ip-address": "127.0.0.1", "prefix": 8}, {"ip-address-type": "ipv6",
"ip-address": "::1", "prefix": 128}], "hardware-address":
"00:00:00:00:00:00"}, {"name": "eth0", "ip-addresses":
[{"ip-address-type": "ipv4", "ip-address": "10.100.0.6", "prefix": 24},
{"ip-address-type": "ipv6", "ip-address": "fe80::216:3eff:fe40:88eb",
"prefix": 64}], "hardware-address": "00:16:3e:40:88:eb"}, {"name":
"sit0"}]}
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2016-09-26 17:33:16 +00:00
|
|
|
VIR_FREE(cfg->channelDir);
|
2016-05-18 14:24:37 +00:00
|
|
|
virFirmwareFreeList(cfg->firmwares, cfg->nfirmwares);
|
2013-08-30 20:52:14 +00:00
|
|
|
}
|
|
|
|
|
2014-09-03 20:14:50 +00:00
|
|
|
|
|
|
|
static libxl_action_on_shutdown
|
|
|
|
libxlActionFromVirLifecycle(virDomainLifecycleAction action)
|
|
|
|
{
|
|
|
|
switch (action) {
|
2017-10-10 12:32:11 +00:00
|
|
|
case VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY:
|
2014-09-03 20:14:50 +00:00
|
|
|
return LIBXL_ACTION_ON_SHUTDOWN_DESTROY;
|
|
|
|
|
2017-10-10 12:32:11 +00:00
|
|
|
case VIR_DOMAIN_LIFECYCLE_ACTION_RESTART:
|
|
|
|
return LIBXL_ACTION_ON_SHUTDOWN_RESTART;
|
2014-09-03 20:14:50 +00:00
|
|
|
|
2017-10-10 12:32:11 +00:00
|
|
|
case VIR_DOMAIN_LIFECYCLE_ACTION_RESTART_RENAME:
|
2014-09-03 20:14:50 +00:00
|
|
|
return LIBXL_ACTION_ON_SHUTDOWN_RESTART_RENAME;
|
|
|
|
|
2017-10-10 12:32:11 +00:00
|
|
|
case VIR_DOMAIN_LIFECYCLE_ACTION_PRESERVE:
|
2014-09-03 20:14:50 +00:00
|
|
|
return LIBXL_ACTION_ON_SHUTDOWN_PRESERVE;
|
|
|
|
|
2017-10-10 12:51:38 +00:00
|
|
|
case VIR_DOMAIN_LIFECYCLE_ACTION_COREDUMP_DESTROY:
|
2014-09-03 20:14:50 +00:00
|
|
|
return LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY;
|
|
|
|
|
2017-10-10 12:51:38 +00:00
|
|
|
case VIR_DOMAIN_LIFECYCLE_ACTION_COREDUMP_RESTART:
|
2014-09-03 20:14:50 +00:00
|
|
|
return LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_RESTART;
|
|
|
|
|
2017-10-10 12:51:38 +00:00
|
|
|
case VIR_DOMAIN_LIFECYCLE_ACTION_LAST:
|
2014-09-03 20:14:50 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
static int
|
2013-08-30 20:34:10 +00:00
|
|
|
libxlMakeDomCreateInfo(libxl_ctx *ctx,
|
2012-11-26 16:28:56 +00:00
|
|
|
virDomainDefPtr def,
|
|
|
|
libxl_domain_create_info *c_info)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_domain_create_info_init(c_info);
|
|
|
|
|
2016-02-23 03:06:57 +00:00
|
|
|
if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
|
2012-11-26 16:28:56 +00:00
|
|
|
c_info->type = LIBXL_DOMAIN_TYPE_HVM;
|
2016-02-23 03:06:57 +00:00
|
|
|
switch ((virTristateSwitch) def->features[VIR_DOMAIN_FEATURE_HAP]) {
|
|
|
|
case VIR_TRISTATE_SWITCH_OFF:
|
|
|
|
libxl_defbool_set(&c_info->hap, false);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_TRISTATE_SWITCH_ON:
|
|
|
|
libxl_defbool_set(&c_info->hap, true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_TRISTATE_SWITCH_ABSENT:
|
|
|
|
case VIR_TRISTATE_SWITCH_LAST:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
2012-11-26 16:28:56 +00:00
|
|
|
c_info->type = LIBXL_DOMAIN_TYPE_PV;
|
2016-02-23 03:06:57 +00:00
|
|
|
}
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(c_info->name, def->name) < 0)
|
2011-02-10 22:42:34 +00:00
|
|
|
goto error;
|
|
|
|
|
2012-11-26 16:28:56 +00:00
|
|
|
if (def->nseclabels &&
|
|
|
|
def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_STATIC) {
|
2013-08-30 20:34:10 +00:00
|
|
|
if (libxl_flask_context_to_sid(ctx,
|
2012-11-26 16:28:56 +00:00
|
|
|
def->seclabels[0]->label,
|
|
|
|
strlen(def->seclabels[0]->label),
|
|
|
|
&c_info->ssidref)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to resolve security label '%s'"),
|
|
|
|
def->seclabels[0]->label);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
virUUIDFormat(def->uuid, uuidstr);
|
2012-10-17 09:23:12 +00:00
|
|
|
if (libxl_uuid_from_string(&c_info->uuid, uuidstr)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to parse UUID '%s'"), uuidstr);
|
2011-02-10 22:42:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:51:17 +00:00
|
|
|
error:
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_domain_create_info_dispose(c_info);
|
2011-02-10 22:42:34 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-07-26 03:30:50 +00:00
|
|
|
static int
|
|
|
|
libxlMakeChrdevStr(virDomainChrDefPtr def, char **buf)
|
|
|
|
{
|
2016-10-21 11:45:54 +00:00
|
|
|
virDomainChrSourceDefPtr srcdef = def->source;
|
|
|
|
const char *type = virDomainChrTypeToString(srcdef->type);
|
2013-07-26 03:30:50 +00:00
|
|
|
|
|
|
|
if (!type) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
"%s", _("unknown chrdev type"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-10-21 11:45:54 +00:00
|
|
|
switch (srcdef->type) {
|
2013-07-26 03:30:50 +00:00
|
|
|
case VIR_DOMAIN_CHR_TYPE_NULL:
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_STDIO:
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_VC:
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_PTY:
|
|
|
|
if (VIR_STRDUP(*buf, type) < 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_FILE:
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_PIPE:
|
2016-10-21 11:45:54 +00:00
|
|
|
if (virAsprintf(buf, "%s:%s", type, srcdef->data.file.path) < 0)
|
2013-07-26 03:30:50 +00:00
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_DEV:
|
2016-10-21 11:45:54 +00:00
|
|
|
if (VIR_STRDUP(*buf, srcdef->data.file.path) < 0)
|
2013-07-26 03:30:50 +00:00
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_UDP: {
|
2016-10-21 11:45:54 +00:00
|
|
|
const char *connectHost = srcdef->data.udp.connectHost;
|
|
|
|
const char *bindHost = srcdef->data.udp.bindHost;
|
|
|
|
const char *bindService = srcdef->data.udp.bindService;
|
2013-07-26 03:30:50 +00:00
|
|
|
|
|
|
|
if (connectHost == NULL)
|
|
|
|
connectHost = "";
|
|
|
|
if (bindHost == NULL)
|
|
|
|
bindHost = "";
|
|
|
|
if (bindService == NULL)
|
|
|
|
bindService = "0";
|
|
|
|
|
|
|
|
if (virAsprintf(buf, "udp:%s:%s@%s:%s",
|
|
|
|
connectHost,
|
2016-10-21 11:45:54 +00:00
|
|
|
srcdef->data.udp.connectService,
|
2013-07-26 03:30:50 +00:00
|
|
|
bindHost,
|
|
|
|
bindService) < 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_TCP: {
|
|
|
|
const char *prefix;
|
|
|
|
|
2016-10-21 11:45:54 +00:00
|
|
|
if (srcdef->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET)
|
2013-07-26 03:30:50 +00:00
|
|
|
prefix = "telnet";
|
|
|
|
else
|
|
|
|
prefix = "tcp";
|
|
|
|
|
|
|
|
if (virAsprintf(buf, "%s:%s:%s%s",
|
|
|
|
prefix,
|
2016-10-21 11:45:54 +00:00
|
|
|
srcdef->data.tcp.host,
|
|
|
|
srcdef->data.tcp.service,
|
|
|
|
srcdef->data.tcp.listen ? ",server,nowait" : "") < 0)
|
2013-07-26 03:30:50 +00:00
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_UNIX:
|
|
|
|
if (virAsprintf(buf, "unix:%s%s",
|
2016-10-21 11:45:54 +00:00
|
|
|
srcdef->data.nix.path,
|
|
|
|
srcdef->data.nix.listen ? ",server,nowait" : "") < 0)
|
2013-07-26 03:30:50 +00:00
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("unsupported chardev '%s'"), type);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
static int
|
2014-05-30 13:46:35 +00:00
|
|
|
libxlMakeDomBuildInfo(virDomainDefPtr def,
|
|
|
|
libxl_ctx *ctx,
|
2017-04-24 13:06:59 +00:00
|
|
|
virCapsPtr caps,
|
2014-05-30 13:46:35 +00:00
|
|
|
libxl_domain_config *d_config)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
2018-02-20 23:51:27 +00:00
|
|
|
virDomainClockDef clock = def->clock;
|
2011-02-10 22:42:34 +00:00
|
|
|
libxl_domain_build_info *b_info = &d_config->b_info;
|
2015-04-17 00:11:06 +00:00
|
|
|
int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM;
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2016-09-23 12:11:50 +00:00
|
|
|
size_t nusbdevice = 0;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_domain_build_info_init(b_info);
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2012-11-26 16:28:56 +00:00
|
|
|
if (hvm)
|
|
|
|
libxl_domain_build_info_init_type(b_info, LIBXL_DOMAIN_TYPE_HVM);
|
2011-05-23 22:06:00 +00:00
|
|
|
else
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_domain_build_info_init_type(b_info, LIBXL_DOMAIN_TYPE_PV);
|
2013-07-24 11:43:43 +00:00
|
|
|
|
2015-10-19 17:21:24 +00:00
|
|
|
b_info->max_vcpus = virDomainDefGetVcpusMax(def);
|
|
|
|
if (libxl_cpu_bitmap_alloc(ctx, &b_info->avail_vcpus, b_info->max_vcpus))
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2013-07-24 11:43:43 +00:00
|
|
|
libxl_bitmap_set_none(&b_info->avail_vcpus);
|
2015-10-22 12:59:03 +00:00
|
|
|
for (i = 0; i < virDomainDefGetVcpus(def); i++)
|
2013-07-24 11:43:43 +00:00
|
|
|
libxl_bitmap_set((&b_info->avail_vcpus), i);
|
|
|
|
|
2018-02-20 23:51:27 +00:00
|
|
|
switch ((virDomainClockOffsetType) clock.offset) {
|
|
|
|
case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE:
|
|
|
|
if (clock.data.variable.basis == VIR_DOMAIN_CLOCK_BASIS_LOCALTIME)
|
|
|
|
libxl_defbool_set(&b_info->localtime, true);
|
|
|
|
b_info->rtc_timeoffset = clock.data.variable.adjustment;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
|
|
|
|
libxl_defbool_set(&b_info->localtime, true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Nothing to do since UTC is the default in libxl */
|
|
|
|
case VIR_DOMAIN_CLOCK_OFFSET_UTC:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("unsupported clock offset '%s'"),
|
|
|
|
virDomainClockOffsetTypeToString(clock.offset));
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CLOCK_OFFSET_LAST:
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("unexpected clock offset '%d'"), clock.offset);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < clock.ntimers; i++) {
|
|
|
|
switch ((virDomainTimerNameType) clock.timers[i]->name) {
|
2017-01-16 22:37:40 +00:00
|
|
|
case VIR_DOMAIN_TIMER_NAME_TSC:
|
2018-02-20 23:51:27 +00:00
|
|
|
switch (clock.timers[i]->mode) {
|
2011-02-10 22:42:34 +00:00
|
|
|
case VIR_DOMAIN_TIMER_MODE_NATIVE:
|
2017-01-19 23:21:34 +00:00
|
|
|
b_info->tsc_mode = LIBXL_TSC_MODE_NATIVE;
|
2011-02-10 22:42:34 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_TIMER_MODE_PARAVIRT:
|
2017-01-19 23:21:34 +00:00
|
|
|
b_info->tsc_mode = LIBXL_TSC_MODE_NATIVE_PARAVIRT;
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_TIMER_MODE_EMULATE:
|
|
|
|
b_info->tsc_mode = LIBXL_TSC_MODE_ALWAYS_EMULATE;
|
2011-02-10 22:42:34 +00:00
|
|
|
break;
|
|
|
|
default:
|
2017-01-19 23:21:34 +00:00
|
|
|
b_info->tsc_mode = LIBXL_TSC_MODE_DEFAULT;
|
2017-01-16 22:37:40 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_TIMER_NAME_HPET:
|
|
|
|
if (!hvm) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("unsupported timer type (name) '%s'"),
|
2018-02-20 23:51:27 +00:00
|
|
|
virDomainTimerNameTypeToString(clock.timers[i]->name));
|
2017-01-16 22:37:40 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2018-02-20 23:51:27 +00:00
|
|
|
if (clock.timers[i]->present == 1)
|
2017-01-16 22:37:40 +00:00
|
|
|
libxl_defbool_set(&b_info->u.hvm.hpet, 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_TIMER_NAME_PLATFORM:
|
|
|
|
case VIR_DOMAIN_TIMER_NAME_KVMCLOCK:
|
|
|
|
case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK:
|
|
|
|
case VIR_DOMAIN_TIMER_NAME_RTC:
|
|
|
|
case VIR_DOMAIN_TIMER_NAME_PIT:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("unsupported timer type (name) '%s'"),
|
2018-02-20 23:51:27 +00:00
|
|
|
virDomainTimerNameTypeToString(clock.timers[i]->name));
|
2017-01-16 22:37:40 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_TIMER_NAME_LAST:
|
|
|
|
break;
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
}
|
2017-01-16 22:37:40 +00:00
|
|
|
|
2012-11-26 16:28:56 +00:00
|
|
|
b_info->sched_params.weight = 1000;
|
2015-02-17 17:01:09 +00:00
|
|
|
b_info->max_memkb = virDomainDefGetMemoryInitial(def);
|
2011-02-10 22:42:34 +00:00
|
|
|
b_info->target_memkb = def->mem.cur_balloon;
|
|
|
|
if (hvm) {
|
2012-12-12 21:28:24 +00:00
|
|
|
char bootorder[VIR_DOMAIN_BOOT_LAST + 1];
|
|
|
|
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_defbool_set(&b_info->u.hvm.pae,
|
2013-09-23 13:02:38 +00:00
|
|
|
def->features[VIR_DOMAIN_FEATURE_PAE] ==
|
2014-06-27 15:18:53 +00:00
|
|
|
VIR_TRISTATE_SWITCH_ON);
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_defbool_set(&b_info->u.hvm.apic,
|
2013-09-23 13:02:38 +00:00
|
|
|
def->features[VIR_DOMAIN_FEATURE_APIC] ==
|
2014-06-27 15:18:53 +00:00
|
|
|
VIR_TRISTATE_SWITCH_ON);
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_defbool_set(&b_info->u.hvm.acpi,
|
2013-09-23 13:02:38 +00:00
|
|
|
def->features[VIR_DOMAIN_FEATURE_ACPI] ==
|
2014-06-27 15:18:53 +00:00
|
|
|
VIR_TRISTATE_SWITCH_ON);
|
2015-05-04 19:50:10 +00:00
|
|
|
|
2017-04-24 13:06:59 +00:00
|
|
|
if (caps &&
|
|
|
|
def->cpu && def->cpu->mode == (VIR_CPU_MODE_HOST_PASSTHROUGH)) {
|
|
|
|
bool hasHwVirt = false;
|
|
|
|
bool svm = false, vmx = false;
|
|
|
|
|
|
|
|
if (ARCH_IS_X86(def->os.arch)) {
|
|
|
|
vmx = virCPUCheckFeature(caps->host.arch, caps->host.cpu, "vmx");
|
|
|
|
svm = virCPUCheckFeature(caps->host.arch, caps->host.cpu, "svm");
|
|
|
|
hasHwVirt = vmx | svm;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->cpu->nfeatures) {
|
|
|
|
for (i = 0; i < def->cpu->nfeatures; i++) {
|
|
|
|
|
|
|
|
switch (def->cpu->features[i].policy) {
|
|
|
|
|
|
|
|
case VIR_CPU_FEATURE_DISABLE:
|
|
|
|
case VIR_CPU_FEATURE_FORBID:
|
|
|
|
if ((vmx && STREQ(def->cpu->features[i].name, "vmx")) ||
|
|
|
|
(svm && STREQ(def->cpu->features[i].name, "svm")))
|
|
|
|
hasHwVirt = false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_CPU_FEATURE_FORCE:
|
|
|
|
case VIR_CPU_FEATURE_REQUIRE:
|
|
|
|
case VIR_CPU_FEATURE_OPTIONAL:
|
|
|
|
case VIR_CPU_FEATURE_LAST:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.nested_hvm, hasHwVirt);
|
|
|
|
}
|
|
|
|
|
2015-05-04 19:50:10 +00:00
|
|
|
if (def->nsounds > 0) {
|
|
|
|
/*
|
|
|
|
* Use first sound device. man xl.cfg(5) describes soundhw as
|
|
|
|
* a single device. From the man page: soundhw=DEVICE
|
|
|
|
*/
|
|
|
|
virDomainSoundDefPtr snd = def->sounds[0];
|
|
|
|
|
|
|
|
if (VIR_STRDUP(b_info->u.hvm.soundhw,
|
|
|
|
virDomainSoundModelTypeToString(snd->model)) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-05-21 07:21:16 +00:00
|
|
|
for (i = 0; i < def->os.nBootDevs; i++) {
|
2012-12-12 21:28:24 +00:00
|
|
|
switch (def->os.bootDevs[i]) {
|
|
|
|
case VIR_DOMAIN_BOOT_FLOPPY:
|
|
|
|
bootorder[i] = 'a';
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
case VIR_DOMAIN_BOOT_DISK:
|
|
|
|
bootorder[i] = 'c';
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_BOOT_CDROM:
|
|
|
|
bootorder[i] = 'd';
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_BOOT_NET:
|
|
|
|
bootorder[i] = 'n';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (def->os.nBootDevs == 0) {
|
|
|
|
bootorder[0] = 'c';
|
|
|
|
bootorder[1] = '\0';
|
2014-09-03 19:04:59 +00:00
|
|
|
} else {
|
2012-12-12 21:28:24 +00:00
|
|
|
bootorder[def->os.nBootDevs] = '\0';
|
|
|
|
}
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(b_info->u.hvm.boot, bootorder) < 0)
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2011-05-10 11:24:15 +00:00
|
|
|
|
2015-03-20 04:16:11 +00:00
|
|
|
#ifdef LIBXL_HAVE_BUILDINFO_KERNEL
|
|
|
|
if (VIR_STRDUP(b_info->cmdline, def->os.cmdline) < 0)
|
|
|
|
return -1;
|
|
|
|
if (VIR_STRDUP(b_info->kernel, def->os.kernel) < 0)
|
|
|
|
return -1;
|
|
|
|
if (VIR_STRDUP(b_info->ramdisk, def->os.initrd) < 0)
|
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
|
2016-04-20 21:14:35 +00:00
|
|
|
/*
|
|
|
|
* Currently libxl only allows specifying the type of BIOS.
|
|
|
|
* If the type is PFLASH, we assume OVMF and set libxl_bios_type
|
|
|
|
* to LIBXL_BIOS_TYPE_OVMF. The path to the OVMF firmware is
|
|
|
|
* configured when building Xen using '--with-system-ovmf='. If
|
|
|
|
* not specified, LIBXL_FIRMWARE_DIR/ovmf.bin is used. In the
|
|
|
|
* future, Xen will support a user-specified firmware path. See
|
|
|
|
* http://lists.xenproject.org/archives/html/xen-devel/2016-03/msg01628.html
|
|
|
|
*/
|
|
|
|
if (def->os.loader &&
|
|
|
|
def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH)
|
|
|
|
b_info->u.hvm.bios = LIBXL_BIOS_TYPE_OVMF;
|
|
|
|
|
2014-09-19 19:03:18 +00:00
|
|
|
if (def->emulator) {
|
|
|
|
if (!virFileExists(def->emulator)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("emulator '%s' not found"),
|
|
|
|
def->emulator);
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2014-09-19 19:03:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!virFileIsExecutable(def->emulator)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("emulator '%s' is not executable"),
|
|
|
|
def->emulator);
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2014-09-19 19:03:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(b_info->device_model);
|
|
|
|
if (VIR_STRDUP(b_info->device_model, def->emulator) < 0)
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2014-09-19 19:03:18 +00:00
|
|
|
|
|
|
|
b_info->device_model_version = libxlDomainGetEmulatorType(def);
|
|
|
|
}
|
|
|
|
|
2013-07-26 03:30:50 +00:00
|
|
|
if (def->nserials) {
|
2016-08-18 02:20:48 +00:00
|
|
|
if (def->nserials == 1) {
|
|
|
|
if (libxlMakeChrdevStr(def->serials[0], &b_info->u.hvm.serial) <
|
|
|
|
0)
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
#ifdef LIBXL_HAVE_BUILDINFO_SERIAL_LIST
|
|
|
|
if (VIR_ALLOC_N(b_info->u.hvm.serial_list, def->nserials + 1) <
|
|
|
|
0)
|
|
|
|
return -1;
|
|
|
|
for (i = 0; i < def->nserials; i++) {
|
|
|
|
if (libxlMakeChrdevStr(def->serials[i],
|
|
|
|
&b_info->u.hvm.serial_list[i]) < 0)
|
|
|
|
{
|
|
|
|
libxl_string_list_dispose(&b_info->u.hvm.serial_list);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
b_info->u.hvm.serial_list[i] = NULL;
|
|
|
|
#else
|
2013-07-26 03:30:50 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
"%s",
|
|
|
|
_("Only one serial device is supported by libxl"));
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2016-08-18 02:20:48 +00:00
|
|
|
#endif
|
2013-07-26 03:30:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->nparallels) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
"%s",
|
|
|
|
_("Parallel devices are not supported by libxl"));
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2013-07-26 03:30:50 +00:00
|
|
|
}
|
|
|
|
|
2015-02-10 02:36:47 +00:00
|
|
|
/* 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);
|
|
|
|
|
2016-09-23 12:11:50 +00:00
|
|
|
for (i = 0; i < def->ninputs; i++) {
|
|
|
|
char **usbdevice;
|
|
|
|
|
|
|
|
if (def->inputs[i]->bus != VIR_DOMAIN_INPUT_BUS_USB)
|
|
|
|
continue;
|
|
|
|
|
2015-03-06 14:36:12 +00:00
|
|
|
#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST
|
2016-09-23 12:11:50 +00:00
|
|
|
if (VIR_EXPAND_N(b_info->u.hvm.usbdevice_list, nusbdevice, 1) < 0)
|
2015-03-06 14:36:12 +00:00
|
|
|
return -1;
|
|
|
|
#else
|
2017-01-10 16:09:03 +00:00
|
|
|
nusbdevice++;
|
|
|
|
if (nusbdevice > 1) {
|
2015-03-06 14:36:12 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("libxenlight supports only one input device"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
2015-03-14 00:36:04 +00:00
|
|
|
|
2015-03-06 14:36:12 +00:00
|
|
|
#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST
|
2017-01-10 16:09:03 +00:00
|
|
|
usbdevice = &b_info->u.hvm.usbdevice_list[nusbdevice - 1];
|
2015-03-06 14:36:12 +00:00
|
|
|
#else
|
2016-09-23 12:11:50 +00:00
|
|
|
usbdevice = &b_info->u.hvm.usbdevice;
|
2015-03-06 14:36:12 +00:00
|
|
|
#endif
|
2016-09-23 12:11:50 +00:00
|
|
|
switch (def->inputs[i]->type) {
|
|
|
|
case VIR_DOMAIN_INPUT_TYPE_MOUSE:
|
|
|
|
VIR_FREE(*usbdevice);
|
|
|
|
if (VIR_STRDUP(*usbdevice, "mouse") < 0)
|
2015-03-06 14:36:12 +00:00
|
|
|
return -1;
|
2016-09-23 12:11:50 +00:00
|
|
|
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;
|
2015-03-06 14:36:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-23 12:11:50 +00:00
|
|
|
#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST
|
|
|
|
/* NULL-terminate usbdevice_list */
|
|
|
|
if (nusbdevice > 0 &&
|
|
|
|
VIR_EXPAND_N(b_info->u.hvm.usbdevice_list, nusbdevice, 1) < 0) {
|
|
|
|
VIR_DISPOSE_N(b_info->u.hvm.usbdevice_list, nusbdevice);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-08-02 23:36:34 +00:00
|
|
|
/* Allow libxl to calculate shadow memory requirements */
|
|
|
|
b_info->shadow_memkb =
|
|
|
|
libxl_get_required_shadow_memory(b_info->max_memkb,
|
|
|
|
b_info->max_vcpus);
|
2011-02-10 22:42:34 +00:00
|
|
|
} else {
|
2013-05-17 15:30:08 +00:00
|
|
|
/*
|
|
|
|
* For compatibility with the legacy xen toolstack, default to pygrub
|
|
|
|
* if bootloader is not specified AND direct kernel boot is not specified.
|
|
|
|
*/
|
|
|
|
if (def->os.bootloader) {
|
|
|
|
if (VIR_STRDUP(b_info->u.pv.bootloader, def->os.bootloader) < 0)
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2013-05-17 15:30:08 +00:00
|
|
|
} else if (def->os.kernel == NULL) {
|
|
|
|
if (VIR_STRDUP(b_info->u.pv.bootloader, LIBXL_BOOTLOADER_PATH) < 0)
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2013-05-17 15:30:08 +00:00
|
|
|
}
|
2011-02-10 22:42:34 +00:00
|
|
|
if (def->os.bootloaderArgs) {
|
2012-11-26 16:28:56 +00:00
|
|
|
if (!(b_info->u.pv.bootloader_args =
|
|
|
|
virStringSplit(def->os.bootloaderArgs, " \t\n", 0)))
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(b_info->u.pv.cmdline, def->os.cmdline) < 0)
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
if (def->os.kernel) {
|
2013-05-03 12:42:47 +00:00
|
|
|
/* libxl_init_build_info() sets VIR_STRDUP(kernel.path, "hvmloader") */
|
2012-11-26 16:28:56 +00:00
|
|
|
VIR_FREE(b_info->u.pv.kernel);
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(b_info->u.pv.kernel, def->os.kernel) < 0)
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(b_info->u.pv.ramdisk, def->os.initrd) < 0)
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-11-02 15:47:22 +00:00
|
|
|
#ifdef LIBXL_HAVE_VNUMA
|
|
|
|
static int
|
|
|
|
libxlMakeVnumaList(virDomainDefPtr def,
|
|
|
|
libxl_ctx *ctx,
|
|
|
|
libxl_domain_config *d_config)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
size_t i, j;
|
|
|
|
size_t nr_nodes;
|
|
|
|
size_t num_vnuma;
|
|
|
|
bool simulate = false;
|
|
|
|
virBitmapPtr bitmap = NULL;
|
|
|
|
virDomainNumaPtr numa = def->numa;
|
|
|
|
libxl_domain_build_info *b_info = &d_config->b_info;
|
|
|
|
libxl_physinfo physinfo;
|
|
|
|
libxl_vnode_info *vnuma_nodes = NULL;
|
|
|
|
|
|
|
|
if (!numa)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
num_vnuma = virDomainNumaGetNodeCount(numa);
|
|
|
|
if (!num_vnuma)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
libxl_physinfo_init(&physinfo);
|
|
|
|
if (libxl_get_physinfo(ctx, &physinfo) < 0) {
|
|
|
|
libxl_physinfo_dispose(&physinfo);
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxl_get_physinfo_info failed"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
nr_nodes = physinfo.nr_nodes;
|
|
|
|
libxl_physinfo_dispose(&physinfo);
|
|
|
|
|
|
|
|
if (num_vnuma > nr_nodes) {
|
|
|
|
VIR_WARN("Number of configured numa cells %zu exceeds available physical nodes %zu. All cells will use physical node 0",
|
|
|
|
num_vnuma, nr_nodes);
|
|
|
|
simulate = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* allocate the vnuma_nodes for assignment under b_info.
|
|
|
|
*/
|
|
|
|
if (VIR_ALLOC_N(vnuma_nodes, num_vnuma) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* parse the vnuma vnodes data.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < num_vnuma; i++) {
|
|
|
|
int cpu;
|
|
|
|
libxl_bitmap vcpu_bitmap;
|
|
|
|
libxl_vnode_info *p = &vnuma_nodes[i];
|
|
|
|
|
|
|
|
libxl_vnode_info_init(p);
|
|
|
|
|
|
|
|
/* pnode */
|
|
|
|
p->pnode = simulate ? 0 : i;
|
|
|
|
|
|
|
|
/* memory size */
|
|
|
|
p->memkb = virDomainNumaGetNodeMemorySize(numa, i);
|
|
|
|
|
|
|
|
/* vcpus */
|
|
|
|
bitmap = virDomainNumaGetNodeCpumask(numa, i);
|
|
|
|
if (bitmap == NULL) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("vnuma sibling %zu missing vcpus set"), i);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((cpu = virBitmapNextSetBit(bitmap, -1)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
libxl_bitmap_init(&vcpu_bitmap);
|
|
|
|
if (libxl_cpu_bitmap_alloc(ctx, &vcpu_bitmap, b_info->max_vcpus)) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
libxl_bitmap_set(&vcpu_bitmap, cpu);
|
|
|
|
} while ((cpu = virBitmapNextSetBit(bitmap, cpu)) >= 0);
|
|
|
|
|
|
|
|
libxl_bitmap_copy_alloc(ctx, &p->vcpus, &vcpu_bitmap);
|
|
|
|
libxl_bitmap_dispose(&vcpu_bitmap);
|
|
|
|
|
|
|
|
/* vdistances */
|
|
|
|
if (VIR_ALLOC_N(p->distances, num_vnuma) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
p->num_distances = num_vnuma;
|
|
|
|
|
|
|
|
for (j = 0; j < num_vnuma; j++)
|
|
|
|
p->distances[j] = virDomainNumaGetNodeDistance(numa, i, j);
|
|
|
|
}
|
|
|
|
|
|
|
|
b_info->vnuma_nodes = vnuma_nodes;
|
|
|
|
b_info->num_vnuma_nodes = num_vnuma;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (ret) {
|
|
|
|
for (i = 0; i < num_vnuma; i++) {
|
|
|
|
libxl_vnode_info *p = &vnuma_nodes[i];
|
|
|
|
|
|
|
|
VIR_FREE(p->distances);
|
|
|
|
}
|
|
|
|
VIR_FREE(vnuma_nodes);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-07-07 15:05:17 +00:00
|
|
|
static int
|
|
|
|
libxlDiskSetDiscard(libxl_device_disk *x_disk, int discard)
|
|
|
|
{
|
|
|
|
if (!x_disk->readwrite)
|
|
|
|
return 0;
|
|
|
|
#if defined(LIBXL_HAVE_LIBXL_DEVICE_DISK_DISCARD_ENABLE)
|
2014-07-11 13:43:47 +00:00
|
|
|
switch ((virDomainDiskDiscard)discard) {
|
2014-07-07 15:05:17 +00:00
|
|
|
case VIR_DOMAIN_DISK_DISCARD_DEFAULT:
|
|
|
|
case VIR_DOMAIN_DISK_DISCARD_LAST:
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DISK_DISCARD_UNMAP:
|
|
|
|
libxl_defbool_set(&x_disk->discard_enable, true);
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DISK_DISCARD_IGNORE:
|
|
|
|
libxl_defbool_set(&x_disk->discard_enable, false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
#else
|
|
|
|
if (discard == VIR_DOMAIN_DISK_DISCARD_DEFAULT)
|
|
|
|
return 0;
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("This version of libxenlight does not support "
|
|
|
|
"disk 'discard' option passing"));
|
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-02-11 03:53:36 +00:00
|
|
|
static char *
|
|
|
|
libxlMakeNetworkDiskSrcStr(virStorageSourcePtr src,
|
|
|
|
const char *username,
|
|
|
|
const char *secret)
|
|
|
|
{
|
|
|
|
char *ret = NULL;
|
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
switch ((virStorageNetProtocol) src->protocol) {
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_NBD:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_HTTP:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_HTTPS:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_FTP:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_FTPS:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_TFTP:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_ISCSI:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
|
2014-09-09 15:56:04 +00:00
|
|
|
case VIR_STORAGE_NET_PROTOCOL_SSH:
|
2017-08-29 11:21:51 +00:00
|
|
|
case VIR_STORAGE_NET_PROTOCOL_VXHS:
|
2016-02-11 03:53:36 +00:00
|
|
|
case VIR_STORAGE_NET_PROTOCOL_LAST:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_NONE:
|
|
|
|
virReportError(VIR_ERR_NO_SUPPORT,
|
|
|
|
_("Unsupported network block protocol '%s'"),
|
|
|
|
virStorageNetProtocolTypeToString(src->protocol));
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_RBD:
|
|
|
|
if (strchr(src->path, ':')) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("':' not allowed in RBD source volume name '%s'"),
|
|
|
|
src->path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-10-23 14:23:45 +00:00
|
|
|
virBufferStrcat(&buf, "rbd:", src->volume, "/", src->path, NULL);
|
2016-02-11 03:53:36 +00:00
|
|
|
|
|
|
|
if (username) {
|
|
|
|
virBufferEscape(&buf, '\\', ":", ":id=%s", username);
|
|
|
|
virBufferEscape(&buf, '\\', ":",
|
|
|
|
":key=%s:auth_supported=cephx\\;none",
|
|
|
|
secret);
|
|
|
|
} else {
|
|
|
|
virBufferAddLit(&buf, ":auth_supported=none");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src->nhosts > 0) {
|
|
|
|
virBufferAddLit(&buf, ":mon_host=");
|
|
|
|
for (i = 0; i < src->nhosts; i++) {
|
|
|
|
if (i)
|
|
|
|
virBufferAddLit(&buf, "\\;");
|
|
|
|
|
|
|
|
/* assume host containing : is ipv6 */
|
|
|
|
if (strchr(src->hosts[i].name, ':'))
|
|
|
|
virBufferEscape(&buf, '\\', ":", "[%s]",
|
|
|
|
src->hosts[i].name);
|
|
|
|
else
|
|
|
|
virBufferAsprintf(&buf, "%s", src->hosts[i].name);
|
|
|
|
|
|
|
|
if (src->hosts[i].port)
|
2017-07-20 10:45:42 +00:00
|
|
|
virBufferAsprintf(&buf, "\\:%u", src->hosts[i].port);
|
2016-02-11 03:53:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src->configFile)
|
|
|
|
virBufferEscape(&buf, '\\', ":", ":conf=%s", src->configFile);
|
|
|
|
|
|
|
|
if (virBufferCheckError(&buf) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = virBufferContentAndReset(&buf);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virBufferFreeAndReset(&buf);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlMakeNetworkDiskSrc(virStorageSourcePtr src, char **srcstr)
|
|
|
|
{
|
|
|
|
virConnectPtr conn = NULL;
|
2016-05-12 15:43:39 +00:00
|
|
|
uint8_t *secret = NULL;
|
|
|
|
char *base64secret = NULL;
|
|
|
|
size_t secretlen = 0;
|
2016-02-11 03:53:36 +00:00
|
|
|
char *username = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
*srcstr = NULL;
|
|
|
|
if (src->auth && src->protocol == VIR_STORAGE_NET_PROTOCOL_RBD) {
|
|
|
|
username = src->auth->username;
|
|
|
|
if (!(conn = virConnectOpen("xen:///system")))
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-05-28 12:43:23 +00:00
|
|
|
if (virSecretGetSecretString(conn, &src->auth->seclookupdef,
|
2016-05-12 15:43:39 +00:00
|
|
|
VIR_SECRET_USAGE_TYPE_CEPH,
|
|
|
|
&secret, &secretlen) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* RBD expects an encoded secret */
|
|
|
|
if (!(base64secret = virStringEncodeBase64(secret, secretlen)))
|
2016-02-11 03:53:36 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-05-12 15:43:39 +00:00
|
|
|
if (!(*srcstr = libxlMakeNetworkDiskSrcStr(src, username, base64secret)))
|
2016-02-23 22:28:04 +00:00
|
|
|
goto cleanup;
|
2016-02-11 03:53:36 +00:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2016-05-12 15:43:39 +00:00
|
|
|
VIR_DISPOSE_N(secret, secretlen);
|
|
|
|
VIR_DISPOSE_STRING(base64secret);
|
2016-02-11 03:53:36 +00:00
|
|
|
virObjectUnref(conn);
|
|
|
|
return ret;
|
|
|
|
}
|
2014-09-19 16:32:43 +00:00
|
|
|
|
2011-05-26 15:09:01 +00:00
|
|
|
int
|
2012-11-26 16:28:56 +00:00
|
|
|
libxlMakeDisk(virDomainDiskDefPtr l_disk, libxl_device_disk *x_disk)
|
2011-05-26 15:09:01 +00:00
|
|
|
{
|
2016-05-23 21:56:01 +00:00
|
|
|
const char *driver = virDomainDiskGetDriver(l_disk);
|
|
|
|
int format = virDomainDiskGetFormat(l_disk);
|
2016-02-11 03:53:36 +00:00
|
|
|
int actual_type = virStorageSourceGetActualType(l_disk->src);
|
2014-03-17 20:14:11 +00:00
|
|
|
|
2013-06-13 01:54:10 +00:00
|
|
|
libxl_device_disk_init(x_disk);
|
|
|
|
|
2016-02-11 03:53:36 +00:00
|
|
|
if (actual_type == VIR_STORAGE_TYPE_NETWORK) {
|
2016-05-23 21:56:01 +00:00
|
|
|
if (STRNEQ_NULLABLE(driver, "qemu")) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("only the 'qemu' driver can be used with network disks"));
|
|
|
|
return -1;
|
|
|
|
}
|
2016-02-11 03:53:36 +00:00
|
|
|
if (libxlMakeNetworkDiskSrc(l_disk->src, &x_disk->pdev_path) < 0)
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
if (VIR_STRDUP(x_disk->pdev_path, virDomainDiskGetSource(l_disk)) < 0)
|
2011-05-26 15:09:01 +00:00
|
|
|
return -1;
|
2016-02-11 03:53:36 +00:00
|
|
|
}
|
2011-05-26 15:09:01 +00:00
|
|
|
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(x_disk->vdev, l_disk->dst) < 0)
|
2011-05-26 15:09:01 +00:00
|
|
|
return -1;
|
|
|
|
|
2014-03-17 20:14:11 +00:00
|
|
|
if (driver) {
|
|
|
|
if (STREQ(driver, "tap") || STREQ(driver, "tap2")) {
|
|
|
|
switch (format) {
|
2012-10-15 21:47:42 +00:00
|
|
|
case VIR_STORAGE_FILE_QCOW:
|
2012-11-26 16:28:56 +00:00
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_QCOW;
|
|
|
|
x_disk->backend = LIBXL_DISK_BACKEND_QDISK;
|
2012-10-15 21:47:42 +00:00
|
|
|
break;
|
|
|
|
case VIR_STORAGE_FILE_QCOW2:
|
2012-11-26 16:28:56 +00:00
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_QCOW2;
|
|
|
|
x_disk->backend = LIBXL_DISK_BACKEND_QDISK;
|
2012-10-15 21:47:42 +00:00
|
|
|
break;
|
|
|
|
case VIR_STORAGE_FILE_VHD:
|
2012-11-26 16:28:56 +00:00
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_VHD;
|
|
|
|
x_disk->backend = LIBXL_DISK_BACKEND_TAP;
|
2012-10-15 21:47:42 +00:00
|
|
|
break;
|
|
|
|
case VIR_STORAGE_FILE_RAW:
|
2012-11-26 16:28:56 +00:00
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_RAW;
|
|
|
|
x_disk->backend = LIBXL_DISK_BACKEND_TAP;
|
2012-10-15 21:47:42 +00:00
|
|
|
break;
|
2016-11-14 15:00:02 +00:00
|
|
|
#ifdef LIBXL_HAVE_QED
|
|
|
|
case VIR_STORAGE_FILE_QED:
|
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_QED;
|
|
|
|
x_disk->backend = LIBXL_DISK_BACKEND_QDISK;
|
|
|
|
break;
|
|
|
|
#endif
|
2012-10-15 21:47:42 +00:00
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2013-05-13 18:14:20 +00:00
|
|
|
_("libxenlight does not support disk format %s "
|
|
|
|
"with disk driver %s"),
|
2014-03-17 20:14:11 +00:00
|
|
|
virStorageFileFormatTypeToString(format),
|
|
|
|
driver);
|
2012-10-15 21:47:42 +00:00
|
|
|
return -1;
|
2011-05-26 15:09:01 +00:00
|
|
|
}
|
2014-03-17 20:14:11 +00:00
|
|
|
} else if (STREQ(driver, "qemu")) {
|
2013-05-13 18:14:21 +00:00
|
|
|
x_disk->backend = LIBXL_DISK_BACKEND_QDISK;
|
2014-03-17 20:14:11 +00:00
|
|
|
switch (format) {
|
2013-05-13 18:14:21 +00:00
|
|
|
case VIR_STORAGE_FILE_QCOW:
|
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_QCOW;
|
|
|
|
break;
|
|
|
|
case VIR_STORAGE_FILE_QCOW2:
|
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_QCOW2;
|
|
|
|
break;
|
2016-11-14 15:00:02 +00:00
|
|
|
#ifdef LIBXL_HAVE_QED
|
|
|
|
case VIR_STORAGE_FILE_QED:
|
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_QED;
|
|
|
|
break;
|
|
|
|
#endif
|
2013-05-13 18:14:21 +00:00
|
|
|
case VIR_STORAGE_FILE_VHD:
|
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_VHD;
|
|
|
|
break;
|
|
|
|
case VIR_STORAGE_FILE_RAW:
|
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_RAW;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight does not support disk format %s "
|
|
|
|
"with disk driver %s"),
|
2014-03-17 20:14:11 +00:00
|
|
|
virStorageFileFormatTypeToString(format),
|
|
|
|
driver);
|
2013-05-13 18:14:21 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2014-03-17 20:14:11 +00:00
|
|
|
} else if (STREQ(driver, "file")) {
|
2017-02-07 18:00:33 +00:00
|
|
|
if (format != VIR_STORAGE_FILE_RAW) {
|
2013-05-13 18:14:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight does not support disk format %s "
|
|
|
|
"with disk driver %s"),
|
2014-03-17 20:14:11 +00:00
|
|
|
virStorageFileFormatTypeToString(format),
|
|
|
|
driver);
|
2013-05-13 18:14:20 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2012-11-26 16:28:56 +00:00
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_RAW;
|
2014-06-20 05:36:25 +00:00
|
|
|
x_disk->backend = LIBXL_DISK_BACKEND_QDISK;
|
2014-03-17 20:14:11 +00:00
|
|
|
} else if (STREQ(driver, "phy")) {
|
2017-02-07 18:00:33 +00:00
|
|
|
if (format != VIR_STORAGE_FILE_RAW) {
|
2013-05-13 18:14:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight does not support disk format %s "
|
|
|
|
"with disk driver %s"),
|
2014-03-17 20:14:11 +00:00
|
|
|
virStorageFileFormatTypeToString(format),
|
|
|
|
driver);
|
2013-05-13 18:14:20 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2012-11-26 16:28:56 +00:00
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_RAW;
|
|
|
|
x_disk->backend = LIBXL_DISK_BACKEND_PHY;
|
2011-05-26 15:09:01 +00:00
|
|
|
} else {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight does not support disk driver %s"),
|
2014-03-17 20:14:11 +00:00
|
|
|
driver);
|
2011-05-26 15:09:01 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
2013-02-20 20:02:28 +00:00
|
|
|
/*
|
|
|
|
* If driverName is not specified, default to raw as per
|
|
|
|
* xl-disk-configuration.txt in the xen documentation and let
|
|
|
|
* libxl pick a suitable backend.
|
|
|
|
*/
|
2012-11-26 16:28:56 +00:00
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_RAW;
|
2013-02-20 20:02:28 +00:00
|
|
|
x_disk->backend = LIBXL_DISK_BACKEND_UNKNOWN;
|
2011-05-26 15:09:01 +00:00
|
|
|
}
|
|
|
|
|
2012-11-26 16:28:56 +00:00
|
|
|
/* XXX is this right? */
|
|
|
|
x_disk->removable = 1;
|
2014-06-24 13:15:55 +00:00
|
|
|
x_disk->readwrite = !l_disk->src->readonly;
|
2011-05-26 15:09:01 +00:00
|
|
|
x_disk->is_cdrom = l_disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ? 1 : 0;
|
2014-07-07 15:05:17 +00:00
|
|
|
if (libxlDiskSetDiscard(x_disk, l_disk->discard) < 0)
|
|
|
|
return -1;
|
2014-03-27 16:55:03 +00:00
|
|
|
/* An empty CDROM must have the empty format, otherwise libxl fails. */
|
|
|
|
if (x_disk->is_cdrom && !x_disk->pdev_path)
|
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_EMPTY;
|
2011-08-13 21:42:48 +00:00
|
|
|
if (l_disk->transient) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxenlight does not support transient disks"));
|
2011-08-13 21:42:48 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2011-05-26 15:09:01 +00:00
|
|
|
|
2015-02-20 03:22:06 +00:00
|
|
|
if (l_disk->domain_name) {
|
|
|
|
#ifdef LIBXL_HAVE_DEVICE_BACKEND_DOMNAME
|
|
|
|
if (VIR_STRDUP(x_disk->backend_domname, l_disk->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
|
|
|
|
}
|
|
|
|
|
2011-05-26 15:09:01 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
static int
|
|
|
|
libxlMakeDiskList(virDomainDefPtr def, libxl_domain_config *d_config)
|
|
|
|
{
|
|
|
|
virDomainDiskDefPtr *l_disks = def->disks;
|
|
|
|
int ndisks = def->ndisks;
|
|
|
|
libxl_device_disk *x_disks;
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2013-07-04 10:10:38 +00:00
|
|
|
if (VIR_ALLOC_N(x_disks, ndisks) < 0)
|
2011-02-10 22:42:34 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0; i < ndisks; i++) {
|
2012-11-26 16:28:56 +00:00
|
|
|
if (libxlMakeDisk(l_disks[i], &x_disks[i]) < 0)
|
2011-02-10 22:42:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
d_config->disks = x_disks;
|
|
|
|
d_config->num_disks = ndisks;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:51:17 +00:00
|
|
|
error:
|
2011-02-10 22:42:34 +00:00
|
|
|
for (i = 0; i < ndisks; i++)
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_device_disk_dispose(&x_disks[i]);
|
2011-02-10 22:42:34 +00:00
|
|
|
VIR_FREE(x_disks);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2017-02-07 19:05:15 +00:00
|
|
|
/*
|
|
|
|
* Update libvirt disk config with libxl disk config.
|
|
|
|
*
|
|
|
|
* This function can be used to update the libvirt disk config with default
|
|
|
|
* values selected by libxl. Currently only the backend type is selected by
|
|
|
|
* libxl when not explicitly specified by the user.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
libxlUpdateDiskDef(virDomainDiskDefPtr l_disk, libxl_device_disk *x_disk)
|
|
|
|
{
|
|
|
|
const char *driver = NULL;
|
|
|
|
|
|
|
|
if (virDomainDiskGetDriver(l_disk))
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (x_disk->backend) {
|
|
|
|
case LIBXL_DISK_BACKEND_QDISK:
|
|
|
|
driver = "qemu";
|
|
|
|
break;
|
|
|
|
case LIBXL_DISK_BACKEND_TAP:
|
|
|
|
driver = "tap";
|
|
|
|
break;
|
|
|
|
case LIBXL_DISK_BACKEND_PHY:
|
|
|
|
driver = "phy";
|
|
|
|
break;
|
|
|
|
case LIBXL_DISK_BACKEND_UNKNOWN:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (driver)
|
|
|
|
ignore_value(virDomainDiskSetDriver(l_disk, driver));
|
|
|
|
}
|
|
|
|
|
2011-05-26 15:09:01 +00:00
|
|
|
int
|
2014-01-06 18:37:20 +00:00
|
|
|
libxlMakeNic(virDomainDefPtr def,
|
|
|
|
virDomainNetDefPtr l_nic,
|
2016-12-14 10:53:32 +00:00
|
|
|
libxl_device_nic *x_nic,
|
|
|
|
bool attach)
|
2011-05-26 15:09:01 +00:00
|
|
|
{
|
2014-06-10 20:28:07 +00:00
|
|
|
virDomainNetType actual_type = virDomainNetGetActualType(l_nic);
|
2016-02-24 22:40:00 +00:00
|
|
|
virNetworkPtr network = NULL;
|
|
|
|
virConnectPtr conn = NULL;
|
2015-12-29 00:26:58 +00:00
|
|
|
virNetDevBandwidthPtr actual_bw;
|
2016-02-24 22:40:00 +00:00
|
|
|
int ret = -1;
|
2014-01-06 18:37:20 +00:00
|
|
|
|
2012-11-26 16:28:56 +00:00
|
|
|
/* TODO: Where is mtu stored?
|
|
|
|
*
|
|
|
|
* x_nics[i].mtu = 1492;
|
|
|
|
*/
|
2011-05-26 15:09:01 +00:00
|
|
|
|
2014-06-10 20:53:55 +00:00
|
|
|
if (l_nic->script && !(actual_type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
|
|
|
|
actual_type == VIR_DOMAIN_NET_TYPE_ETHERNET)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("specifying a script is only supported with "
|
|
|
|
"interface types bridge and ethernet"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-06-13 01:54:10 +00:00
|
|
|
libxl_device_nic_init(x_nic);
|
|
|
|
|
2012-07-17 12:07:59 +00:00
|
|
|
virMacAddrGetRaw(&l_nic->mac, x_nic->mac);
|
2011-05-26 15:09:01 +00:00
|
|
|
|
2016-12-14 10:53:32 +00:00
|
|
|
/*
|
|
|
|
* The nictype field of libxl_device_nic structure tells Xen which type of
|
|
|
|
* NIC device to create for the domain. LIBXL_NIC_TYPE_VIF specifies a
|
|
|
|
* PV NIC. LIBXL_NIC_TYPE_VIF_IOEMU specifies a PV and emulated NIC,
|
|
|
|
* allowing the domain to choose which NIC to use and unplug the unused
|
|
|
|
* one. LIBXL_NIC_TYPE_VIF_IOEMU is only valid for HVM domains. Further,
|
|
|
|
* if hotplugging the NIC, emulated NICs are currently not supported.
|
|
|
|
* Alternatively one could set LIBXL_NIC_TYPE_UNKNOWN and let libxl decide,
|
|
|
|
* but its behaviour might not be consistent across all libvirt supported
|
|
|
|
* versions. The other nictype values are well established already, hence
|
|
|
|
* we manually select our own default and mimic xl/libxl behaviour starting
|
|
|
|
* xen commit 32e9d0f ("libxl: nic type defaults to vif in hotplug for
|
|
|
|
* hvm guest").
|
|
|
|
*/
|
2014-01-06 18:37:20 +00:00
|
|
|
if (l_nic->model) {
|
2016-12-14 10:53:32 +00:00
|
|
|
if (def->os.type == VIR_DOMAIN_OSTYPE_XEN &&
|
|
|
|
STRNEQ(l_nic->model, "netfront")) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("only model 'netfront' is supported for "
|
|
|
|
"Xen PV domains"));
|
|
|
|
return -1;
|
|
|
|
}
|
2014-01-06 18:37:20 +00:00
|
|
|
if (VIR_STRDUP(x_nic->model, l_nic->model) < 0)
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2014-01-06 18:37:20 +00:00
|
|
|
if (STREQ(l_nic->model, "netfront"))
|
|
|
|
x_nic->nictype = LIBXL_NIC_TYPE_VIF;
|
2016-12-14 10:53:32 +00:00
|
|
|
else
|
|
|
|
x_nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU;
|
|
|
|
} else {
|
|
|
|
if (def->os.type == VIR_DOMAIN_OSTYPE_HVM && !attach)
|
|
|
|
x_nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU;
|
|
|
|
else
|
|
|
|
x_nic->nictype = LIBXL_NIC_TYPE_VIF;
|
2011-05-26 15:09:01 +00:00
|
|
|
}
|
|
|
|
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(x_nic->ifname, l_nic->ifname) < 0)
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2011-05-26 15:09:01 +00:00
|
|
|
|
2014-06-10 20:28:07 +00:00
|
|
|
switch (actual_type) {
|
2013-06-13 01:54:03 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_BRIDGE:
|
2014-06-10 20:28:07 +00:00
|
|
|
if (VIR_STRDUP(x_nic->bridge,
|
|
|
|
virDomainNetGetActualBridgeName(l_nic)) < 0)
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2017-06-07 08:46:41 +00:00
|
|
|
ATTRIBUTE_FALLTHROUGH;
|
2013-06-13 01:54:03 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_ETHERNET:
|
|
|
|
if (VIR_STRDUP(x_nic->script, l_nic->script) < 0)
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2016-06-07 15:39:34 +00:00
|
|
|
if (l_nic->guestIP.nips > 0) {
|
2017-12-07 02:27:45 +00:00
|
|
|
x_nic->ip = xenMakeIPList(&l_nic->guestIP);
|
2015-02-10 02:17:23 +00:00
|
|
|
if (!x_nic->ip)
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2015-02-10 02:17:23 +00:00
|
|
|
}
|
2013-06-13 01:54:03 +00:00
|
|
|
break;
|
2014-06-10 20:28:07 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_NETWORK:
|
|
|
|
{
|
|
|
|
if (!(conn = virConnectOpen("xen:///system")))
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2014-06-10 20:28:07 +00:00
|
|
|
|
|
|
|
if (!(network =
|
|
|
|
virNetworkLookupByName(conn, l_nic->data.network.name))) {
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2014-06-10 20:28:07 +00:00
|
|
|
}
|
|
|
|
|
2016-06-07 15:39:34 +00:00
|
|
|
if (l_nic->guestIP.nips > 0) {
|
2017-12-07 02:27:45 +00:00
|
|
|
x_nic->ip = xenMakeIPList(&l_nic->guestIP);
|
2015-02-10 02:17:23 +00:00
|
|
|
if (!x_nic->ip)
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2014-06-10 20:28:07 +00:00
|
|
|
}
|
|
|
|
|
2016-02-24 22:40:00 +00:00
|
|
|
if (!(x_nic->bridge = virNetworkGetBridgeName(network)))
|
|
|
|
goto cleanup;
|
2014-06-10 20:28:07 +00:00
|
|
|
break;
|
|
|
|
}
|
2014-07-11 17:47:31 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
|
2014-06-10 20:28:07 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_USER:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_SERVER:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_CLIENT:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_MCAST:
|
2015-08-29 20:19:10 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_UDP:
|
2014-06-10 20:28:07 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_INTERNAL:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_DIRECT:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_LAST:
|
2014-06-10 20:53:55 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("unsupported interface type %s"),
|
2013-06-13 01:54:03 +00:00
|
|
|
virDomainNetTypeToString(l_nic->type));
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2011-05-26 15:09:01 +00:00
|
|
|
}
|
|
|
|
|
2015-02-20 03:22:06 +00:00
|
|
|
if (l_nic->domain_name) {
|
|
|
|
#ifdef LIBXL_HAVE_DEVICE_BACKEND_DOMNAME
|
|
|
|
if (VIR_STRDUP(x_nic->backend_domname, l_nic->domain_name) < 0)
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2015-02-20 03:22:06 +00:00
|
|
|
#else
|
|
|
|
virReportError(VIR_ERR_XML_DETAIL, "%s",
|
|
|
|
_("this version of libxenlight does not "
|
|
|
|
"support backend domain name"));
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2015-02-20 03:22:06 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-12-29 00:26:58 +00:00
|
|
|
/*
|
|
|
|
* Set bandwidth.
|
|
|
|
* From $xen-sources/docs/misc/xl-network-configuration.markdown:
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Specifies the rate at which the outgoing traffic will be limited to.
|
|
|
|
* The default if this keyword is not specified is unlimited.
|
|
|
|
*
|
|
|
|
* The rate may be specified as "<RATE>/s" or optionally "<RATE>/s@<INTERVAL>".
|
|
|
|
*
|
|
|
|
* `RATE` is in bytes and can accept suffixes:
|
|
|
|
* GB, MB, KB, B for bytes.
|
|
|
|
* Gb, Mb, Kb, b for bits.
|
|
|
|
* `INTERVAL` is in microseconds and can accept suffixes: ms, us, s.
|
|
|
|
* It determines the frequency at which the vif transmission credit
|
|
|
|
* is replenished. The default is 50ms.
|
|
|
|
|
|
|
|
* Vif rate limiting is credit-based. It means that for "1MB/s@20ms",
|
|
|
|
* the available credit will be equivalent of the traffic you would have
|
|
|
|
* done at "1MB/s" during 20ms. This will results in a credit of 20,000
|
|
|
|
* bytes replenished every 20,000 us.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* libvirt doesn't support the notion of rate limiting over an interval.
|
|
|
|
* Similar to xl's behavior when interval is not specified, set a default
|
|
|
|
* interval of 50ms and calculate the number of bytes per interval based
|
|
|
|
* on the specified average bandwidth.
|
|
|
|
*/
|
|
|
|
actual_bw = virDomainNetGetActualBandwidth(l_nic);
|
|
|
|
if (actual_bw && actual_bw->out && actual_bw->out->average) {
|
|
|
|
uint64_t bytes_per_sec = actual_bw->out->average * 1024;
|
|
|
|
uint64_t bytes_per_interval =
|
|
|
|
(((uint64_t) bytes_per_sec * 50000UL) / 1000000UL);
|
|
|
|
|
|
|
|
x_nic->rate_bytes_per_interval = bytes_per_interval;
|
|
|
|
x_nic->rate_interval_usecs = 50000UL;
|
|
|
|
}
|
|
|
|
|
2016-02-24 22:40:00 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virObjectUnref(network);
|
|
|
|
virObjectUnref(conn);
|
|
|
|
|
|
|
|
return ret;
|
2011-05-26 15:09:01 +00:00
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
static int
|
|
|
|
libxlMakeNicList(virDomainDefPtr def, libxl_domain_config *d_config)
|
|
|
|
{
|
|
|
|
virDomainNetDefPtr *l_nics = def->nets;
|
2014-05-08 06:44:04 +00:00
|
|
|
size_t nnics = def->nnets;
|
2011-02-10 22:42:34 +00:00
|
|
|
libxl_device_nic *x_nics;
|
2014-05-08 06:44:04 +00:00
|
|
|
size_t i, nvnics = 0;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2013-07-04 10:10:38 +00:00
|
|
|
if (VIR_ALLOC_N(x_nics, nnics) < 0)
|
2011-02-10 22:42:34 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0; i < nnics; i++) {
|
2016-03-10 02:50:41 +00:00
|
|
|
if (virDomainNetGetActualType(l_nics[i]) == VIR_DOMAIN_NET_TYPE_HOSTDEV)
|
2014-05-08 06:44:04 +00:00
|
|
|
continue;
|
|
|
|
|
2016-12-14 10:53:32 +00:00
|
|
|
if (libxlMakeNic(def, l_nics[i], &x_nics[nvnics], false))
|
2011-02-10 22:42:34 +00:00
|
|
|
goto error;
|
2014-01-08 10:39:19 +00:00
|
|
|
/*
|
|
|
|
* The devid (at least right now) will not get initialized by
|
|
|
|
* libxl in the setup case but is required for starting the
|
|
|
|
* device-model.
|
|
|
|
*/
|
2014-05-08 06:44:04 +00:00
|
|
|
if (x_nics[nvnics].devid < 0)
|
|
|
|
x_nics[nvnics].devid = nvnics;
|
|
|
|
|
|
|
|
nvnics++;
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
|
2014-05-08 06:44:04 +00:00
|
|
|
VIR_SHRINK_N(x_nics, nnics, nnics - nvnics);
|
2012-11-26 16:28:56 +00:00
|
|
|
d_config->nics = x_nics;
|
2016-02-23 08:07:58 +00:00
|
|
|
d_config->num_nics = nvnics;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:51:17 +00:00
|
|
|
error:
|
2011-02-10 22:42:34 +00:00
|
|
|
for (i = 0; i < nnics; i++)
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_device_nic_dispose(&x_nics[i]);
|
2011-02-10 22:42:34 +00:00
|
|
|
VIR_FREE(x_nics);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-05-26 15:09:01 +00:00
|
|
|
int
|
2018-02-06 09:09:06 +00:00
|
|
|
libxlMakeVfb(virPortAllocatorRangePtr graphicsports,
|
2012-11-26 16:28:56 +00:00
|
|
|
virDomainGraphicsDefPtr l_vfb,
|
|
|
|
libxl_device_vfb *x_vfb)
|
2011-05-26 15:09:01 +00:00
|
|
|
{
|
2013-01-11 12:09:53 +00:00
|
|
|
unsigned short port;
|
2016-05-17 12:55:55 +00:00
|
|
|
virDomainGraphicsListenDefPtr glisten = NULL;
|
2011-05-26 15:09:01 +00:00
|
|
|
|
2013-06-13 01:54:10 +00:00
|
|
|
libxl_device_vfb_init(x_vfb);
|
|
|
|
|
2011-05-26 15:09:01 +00:00
|
|
|
switch (l_vfb->type) {
|
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_defbool_set(&x_vfb->sdl.enable, 1);
|
2015-04-17 17:19:31 +00:00
|
|
|
libxl_defbool_set(&x_vfb->vnc.enable, 0);
|
2015-04-24 20:11:26 +00:00
|
|
|
libxl_defbool_set(&x_vfb->sdl.opengl, 0);
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(x_vfb->sdl.display, l_vfb->data.sdl.display) < 0)
|
2011-05-26 15:09:01 +00:00
|
|
|
return -1;
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(x_vfb->sdl.xauthority, l_vfb->data.sdl.xauth) < 0)
|
2011-05-26 15:09:01 +00:00
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_defbool_set(&x_vfb->vnc.enable, 1);
|
2015-04-17 17:19:31 +00:00
|
|
|
libxl_defbool_set(&x_vfb->sdl.enable, 0);
|
2011-05-26 15:09:01 +00:00
|
|
|
/* driver handles selection of free port */
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_defbool_set(&x_vfb->vnc.findunused, 0);
|
2011-05-26 15:09:01 +00:00
|
|
|
if (l_vfb->data.vnc.autoport) {
|
2013-01-11 12:09:53 +00:00
|
|
|
|
2014-05-30 13:48:56 +00:00
|
|
|
if (virPortAllocatorAcquire(graphicsports, &port) < 0)
|
2013-01-11 12:09:53 +00:00
|
|
|
return -1;
|
2011-05-26 15:09:01 +00:00
|
|
|
l_vfb->data.vnc.port = port;
|
|
|
|
}
|
2012-11-26 16:28:56 +00:00
|
|
|
x_vfb->vnc.display = l_vfb->data.vnc.port - LIBXL_VNC_PORT_MIN;
|
2011-05-26 15:09:01 +00:00
|
|
|
|
2017-05-19 21:52:04 +00:00
|
|
|
if ((glisten = virDomainGraphicsGetListen(l_vfb, 0))) {
|
|
|
|
if (glisten->address) {
|
|
|
|
/* libxl_device_vfb_init() does VIR_STRDUP("127.0.0.1") */
|
|
|
|
VIR_FREE(x_vfb->vnc.listen);
|
|
|
|
if (VIR_STRDUP(x_vfb->vnc.listen, glisten->address) < 0)
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
if (VIR_STRDUP(glisten->address, VIR_LOOPBACK_IPV4_ADDR) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
2011-05-26 15:09:01 +00:00
|
|
|
}
|
2017-05-19 21:52:04 +00:00
|
|
|
|
2015-04-28 00:20:30 +00:00
|
|
|
if (VIR_STRDUP(x_vfb->vnc.passwd, l_vfb->data.vnc.auth.passwd) < 0)
|
|
|
|
return -1;
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(x_vfb->keymap, l_vfb->data.vnc.keymap) < 0)
|
2011-05-26 15:09:01 +00:00
|
|
|
return -1;
|
|
|
|
break;
|
2016-05-02 15:45:23 +00:00
|
|
|
|
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
|
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
|
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
|
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
|
|
|
|
break;
|
2011-05-26 15:09:01 +00:00
|
|
|
}
|
2012-11-26 16:28:56 +00:00
|
|
|
|
2011-05-26 15:09:01 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
static int
|
2018-02-06 09:09:06 +00:00
|
|
|
libxlMakeVfbList(virPortAllocatorRangePtr graphicsports,
|
2012-11-26 16:28:56 +00:00
|
|
|
virDomainDefPtr def,
|
|
|
|
libxl_domain_config *d_config)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
|
|
|
virDomainGraphicsDefPtr *l_vfbs = def->graphics;
|
|
|
|
int nvfbs = def->ngraphics;
|
|
|
|
libxl_device_vfb *x_vfbs;
|
|
|
|
libxl_device_vkb *x_vkbs;
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
if (nvfbs == 0)
|
|
|
|
return 0;
|
|
|
|
|
2013-07-04 10:10:38 +00:00
|
|
|
if (VIR_ALLOC_N(x_vfbs, nvfbs) < 0)
|
2011-02-10 22:42:34 +00:00
|
|
|
return -1;
|
|
|
|
if (VIR_ALLOC_N(x_vkbs, nvfbs) < 0) {
|
|
|
|
VIR_FREE(x_vfbs);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < nvfbs; i++) {
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_device_vkb_init(&x_vkbs[i]);
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2014-05-30 13:48:56 +00:00
|
|
|
if (libxlMakeVfb(graphicsports, l_vfbs[i], &x_vfbs[i]) < 0)
|
2011-05-26 15:09:01 +00:00
|
|
|
goto error;
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
d_config->vfbs = x_vfbs;
|
|
|
|
d_config->vkbs = x_vkbs;
|
|
|
|
d_config->num_vfbs = d_config->num_vkbs = nvfbs;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:51:17 +00:00
|
|
|
error:
|
2011-02-10 22:42:34 +00:00
|
|
|
for (i = 0; i < nvfbs; i++) {
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_device_vfb_dispose(&x_vfbs[i]);
|
|
|
|
libxl_device_vkb_dispose(&x_vkbs[i]);
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
VIR_FREE(x_vfbs);
|
|
|
|
VIR_FREE(x_vkbs);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-04-27 18:32:55 +00:00
|
|
|
/*
|
|
|
|
* Populate vfb info in libxl_domain_build_info struct for HVM domains.
|
|
|
|
* Prior to calling this function, libxlMakeVfbList must be called to
|
|
|
|
* populate libxl_domain_config->vfbs.
|
|
|
|
*/
|
|
|
|
static int
|
2018-02-06 09:09:06 +00:00
|
|
|
libxlMakeBuildInfoVfb(virPortAllocatorRangePtr graphicsports,
|
2015-04-27 22:27:52 +00:00
|
|
|
virDomainDefPtr def,
|
|
|
|
libxl_domain_config *d_config)
|
2015-04-27 18:32:55 +00:00
|
|
|
{
|
|
|
|
libxl_domain_build_info *b_info = &d_config->b_info;
|
|
|
|
libxl_device_vfb x_vfb;
|
2015-04-27 22:27:52 +00:00
|
|
|
size_t i;
|
2015-04-27 18:32:55 +00:00
|
|
|
|
|
|
|
if (def->os.type != VIR_DOMAIN_OSTYPE_HVM)
|
|
|
|
return 0;
|
|
|
|
|
2015-04-27 22:27:52 +00:00
|
|
|
if (def->ngraphics == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Prefer SPICE, otherwise use first libxl_device_vfb device in
|
|
|
|
* libxl_domain_config->vfbs. Prior to calling this function,
|
|
|
|
*/
|
|
|
|
for (i = 0; i < def->ngraphics; i++) {
|
|
|
|
virDomainGraphicsDefPtr l_vfb = def->graphics[i];
|
|
|
|
unsigned short port;
|
2016-05-17 12:55:55 +00:00
|
|
|
virDomainGraphicsListenDefPtr glisten = NULL;
|
2015-04-27 22:27:52 +00:00
|
|
|
|
|
|
|
if (l_vfb->type != VIR_DOMAIN_GRAPHICS_TYPE_SPICE)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.spice.enable, true);
|
|
|
|
|
|
|
|
if (l_vfb->data.spice.autoport) {
|
|
|
|
if (virPortAllocatorAcquire(graphicsports, &port) < 0)
|
|
|
|
return -1;
|
|
|
|
l_vfb->data.spice.port = port;
|
|
|
|
}
|
|
|
|
b_info->u.hvm.spice.port = l_vfb->data.spice.port;
|
|
|
|
|
2017-05-19 21:52:04 +00:00
|
|
|
if ((glisten = virDomainGraphicsGetListen(l_vfb, 0))) {
|
|
|
|
if (glisten->address) {
|
|
|
|
if (VIR_STRDUP(b_info->u.hvm.spice.host, glisten->address) < 0)
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
if (VIR_STRDUP(b_info->u.hvm.spice.host, VIR_LOOPBACK_IPV4_ADDR) < 0 ||
|
|
|
|
VIR_STRDUP(glisten->address, VIR_LOOPBACK_IPV4_ADDR) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2015-04-27 22:27:52 +00:00
|
|
|
|
|
|
|
if (VIR_STRDUP(b_info->u.hvm.keymap, l_vfb->data.spice.keymap) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (l_vfb->data.spice.auth.passwd) {
|
|
|
|
if (VIR_STRDUP(b_info->u.hvm.spice.passwd,
|
|
|
|
l_vfb->data.spice.auth.passwd) < 0)
|
|
|
|
return -1;
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.spice.disable_ticketing, false);
|
|
|
|
} else {
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.spice.disable_ticketing, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (l_vfb->data.spice.mousemode) {
|
|
|
|
/* client mouse mode is default in xl.cfg */
|
|
|
|
case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_DEFAULT:
|
|
|
|
case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT:
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.spice.agent_mouse, true);
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER:
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.spice.agent_mouse, false);
|
|
|
|
break;
|
2016-05-02 15:45:23 +00:00
|
|
|
case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_LAST:
|
|
|
|
break;
|
2015-04-27 22:27:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef LIBXL_HAVE_SPICE_VDAGENT
|
|
|
|
if (l_vfb->data.spice.copypaste == VIR_TRISTATE_BOOL_YES) {
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.spice.vdagent, true);
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.spice.clipboard_sharing, true);
|
|
|
|
} else {
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.spice.vdagent, false);
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.spice.clipboard_sharing, false);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-04-27 18:32:55 +00:00
|
|
|
return 0;
|
2015-04-27 22:27:52 +00:00
|
|
|
}
|
2015-04-27 18:32:55 +00:00
|
|
|
|
|
|
|
x_vfb = d_config->vfbs[0];
|
|
|
|
|
|
|
|
if (libxl_defbool_val(x_vfb.vnc.enable)) {
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.vnc.enable, true);
|
|
|
|
if (VIR_STRDUP(b_info->u.hvm.vnc.listen, x_vfb.vnc.listen) < 0)
|
|
|
|
return -1;
|
|
|
|
if (VIR_STRDUP(b_info->u.hvm.vnc.passwd, x_vfb.vnc.passwd) < 0)
|
|
|
|
return -1;
|
|
|
|
b_info->u.hvm.vnc.display = x_vfb.vnc.display;
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.vnc.findunused,
|
|
|
|
libxl_defbool_val(x_vfb.vnc.findunused));
|
|
|
|
} else if (libxl_defbool_val(x_vfb.sdl.enable)) {
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.sdl.enable, true);
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.sdl.opengl,
|
|
|
|
libxl_defbool_val(x_vfb.sdl.opengl));
|
|
|
|
if (VIR_STRDUP(b_info->u.hvm.sdl.display, x_vfb.sdl.display) < 0)
|
|
|
|
return -1;
|
|
|
|
if (VIR_STRDUP(b_info->u.hvm.sdl.xauthority, x_vfb.sdl.xauthority) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_STRDUP(b_info->u.hvm.keymap, x_vfb.keymap) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-09-09 15:15:15 +00:00
|
|
|
/*
|
|
|
|
* Get domain0 autoballoon configuration. Honor user-specified
|
|
|
|
* setting in libxl.conf first. If not specified, autoballooning
|
|
|
|
* is disabled when domain0's memory is set with 'dom0_mem'.
|
|
|
|
* Otherwise autoballooning is enabled.
|
|
|
|
*/
|
2013-09-04 06:21:42 +00:00
|
|
|
static int
|
2013-09-09 15:15:15 +00:00
|
|
|
libxlGetAutoballoonConf(libxlDriverConfigPtr cfg,
|
|
|
|
virConfPtr conf)
|
2013-08-30 17:11:08 +00:00
|
|
|
{
|
|
|
|
regex_t regex;
|
2013-09-04 06:21:42 +00:00
|
|
|
int res;
|
|
|
|
|
2017-01-30 18:43:15 +00:00
|
|
|
res = virConfGetValueBool(conf, "autoballoon", &cfg->autoballoon);
|
|
|
|
if (res < 0)
|
2016-07-08 12:52:04 +00:00
|
|
|
return -1;
|
2017-01-30 18:43:15 +00:00
|
|
|
else if (res == 1)
|
|
|
|
return 0;
|
2013-09-09 15:15:15 +00:00
|
|
|
|
2013-09-04 06:21:42 +00:00
|
|
|
if ((res = regcomp(®ex,
|
|
|
|
"(^| )dom0_mem=((|min:|max:)[0-9]+[bBkKmMgG]?,?)+($| )",
|
|
|
|
REG_NOSUB | REG_EXTENDED)) != 0) {
|
|
|
|
char error[100];
|
|
|
|
regerror(res, ®ex, error, sizeof(error));
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to compile regex %s"),
|
|
|
|
error);
|
2013-08-30 17:11:08 +00:00
|
|
|
|
2013-09-04 06:21:42 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2013-08-30 17:11:08 +00:00
|
|
|
|
2013-09-04 06:21:42 +00:00
|
|
|
res = regexec(®ex, cfg->verInfo->commandline, 0, NULL, 0);
|
2013-08-30 17:11:08 +00:00
|
|
|
regfree(®ex);
|
2013-09-09 15:15:15 +00:00
|
|
|
cfg->autoballoon = res == REG_NOMATCH;
|
2013-09-04 06:21:42 +00:00
|
|
|
return 0;
|
2013-08-30 17:11:08 +00:00
|
|
|
}
|
|
|
|
|
2013-08-30 20:52:14 +00:00
|
|
|
libxlDriverConfigPtr
|
|
|
|
libxlDriverConfigNew(void)
|
|
|
|
{
|
|
|
|
libxlDriverConfigPtr cfg;
|
|
|
|
char ebuf[1024];
|
|
|
|
unsigned int free_mem;
|
|
|
|
|
|
|
|
if (libxlConfigInitialize() < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(cfg = virObjectNew(libxlDriverConfigClass)))
|
|
|
|
return NULL;
|
|
|
|
|
2013-09-09 15:15:15 +00:00
|
|
|
if (VIR_STRDUP(cfg->configBaseDir, LIBXL_CONFIG_BASE_DIR) < 0)
|
|
|
|
goto error;
|
2013-08-30 20:52:14 +00:00
|
|
|
if (VIR_STRDUP(cfg->configDir, LIBXL_CONFIG_DIR) < 0)
|
|
|
|
goto error;
|
|
|
|
if (VIR_STRDUP(cfg->autostartDir, LIBXL_AUTOSTART_DIR) < 0)
|
|
|
|
goto error;
|
|
|
|
if (VIR_STRDUP(cfg->logDir, LIBXL_LOG_DIR) < 0)
|
|
|
|
goto error;
|
|
|
|
if (VIR_STRDUP(cfg->stateDir, LIBXL_STATE_DIR) < 0)
|
|
|
|
goto error;
|
|
|
|
if (VIR_STRDUP(cfg->libDir, LIBXL_LIB_DIR) < 0)
|
|
|
|
goto error;
|
|
|
|
if (VIR_STRDUP(cfg->saveDir, LIBXL_SAVE_DIR) < 0)
|
|
|
|
goto error;
|
2014-02-19 23:09:36 +00:00
|
|
|
if (VIR_STRDUP(cfg->autoDumpDir, LIBXL_DUMP_DIR) < 0)
|
|
|
|
goto error;
|
libxl: channels support
And allow libxl to handle channel element which creates a Xen
console visible to the guest as a low-bandwitdh communication
channel. If type is PTY we also fetch the tty after boot using
libxl_channel_getinfo to fetch the tty path. On socket case,
we autogenerate a path if not specified in the XML. Path autogenerated
is slightly different from qemu driver: qemu stores also on
"channels/target" but it creates then a directory per domain with
each channel target name. libxl doesn't appear to have a clear
definition of private files associated with each domain, so for
simplicity we do it slightly different. On qemu each autogenerated
channel goes like:
channels/target/<domain-name>/<target name>
Whereas for libxl:
channels/target/<domain-name>-<target name>
Should note that if path is not specified it won't persist,
existing only on live XML, unless user had initially specified it.
Since support for libxl channels only came on Xen >= 4.5 we therefore
need to conditionally compile it with LIBXL_HAVE_DEVICE_CHANNEL.
After this patch and having a qemu guest agent:
$ cat domain.xml | grep -a1 channel | head -n 5 | tail -n 4
<channel type='unix'>
<source mode='bind' path='/tmp/channel'/>
<target type='xen' name='org.qemu.guest_agent.0'/>
</channel>
$ virsh create domain.xml
$ echo '{"execute":"guest-network-get-interfaces"}' | socat
stdio,ignoreeof unix-connect:/tmp/channel
{"execute":"guest-network-get-interfaces"}
{"return": [{"name": "lo", "ip-addresses": [{"ip-address-type": "ipv4",
"ip-address": "127.0.0.1", "prefix": 8}, {"ip-address-type": "ipv6",
"ip-address": "::1", "prefix": 128}], "hardware-address":
"00:00:00:00:00:00"}, {"name": "eth0", "ip-addresses":
[{"ip-address-type": "ipv4", "ip-address": "10.100.0.6", "prefix": 24},
{"ip-address-type": "ipv6", "ip-address": "fe80::216:3eff:fe40:88eb",
"prefix": 64}], "hardware-address": "00:16:3e:40:88:eb"}, {"name":
"sit0"}]}
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2016-09-26 17:33:16 +00:00
|
|
|
if (VIR_STRDUP(cfg->channelDir, LIBXL_CHANNEL_DIR) < 0)
|
|
|
|
goto error;
|
2013-08-30 20:52:14 +00:00
|
|
|
|
2014-03-25 15:28:36 +00:00
|
|
|
if (virFileMakePath(cfg->logDir) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("failed to create log dir '%s': %s"),
|
|
|
|
cfg->logDir,
|
|
|
|
virStrerror(errno, ebuf, sizeof(ebuf)));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2017-01-09 15:20:50 +00:00
|
|
|
cfg->logger = libxlLoggerNew(cfg->logDir, virLogGetDefaultPriority());
|
2013-08-30 20:52:14 +00:00
|
|
|
if (!cfg->logger) {
|
|
|
|
VIR_ERROR(_("cannot create logger for libxenlight, disabling driver"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2017-01-09 15:20:50 +00:00
|
|
|
if (libxl_ctx_alloc(&cfg->ctx, LIBXL_VERSION, 0, (xentoollog_logger *)cfg->logger)) {
|
2013-08-30 20:52:14 +00:00
|
|
|
VIR_ERROR(_("cannot initialize libxenlight context, probably not "
|
|
|
|
"running in a Xen Dom0, disabling driver"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((cfg->verInfo = libxl_get_version_info(cfg->ctx)) == NULL) {
|
|
|
|
VIR_ERROR(_("cannot version information from libxenlight, "
|
|
|
|
"disabling driver"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
cfg->version = (cfg->verInfo->xen_version_major * 1000000) +
|
|
|
|
(cfg->verInfo->xen_version_minor * 1000);
|
|
|
|
|
|
|
|
/* This will fill xenstore info about free and dom0 memory if missing,
|
|
|
|
* should be called before starting first domain */
|
|
|
|
if (libxl_get_free_memory(cfg->ctx, &free_mem)) {
|
|
|
|
VIR_ERROR(_("Unable to configure libxl's memory management parameters"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2016-05-18 14:24:37 +00:00
|
|
|
#ifdef DEFAULT_LOADER_NVRAM
|
|
|
|
if (virFirmwareParseList(DEFAULT_LOADER_NVRAM,
|
|
|
|
&cfg->firmwares,
|
|
|
|
&cfg->nfirmwares) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
#else
|
|
|
|
if (VIR_ALLOC_N(cfg->firmwares, 1) < 0)
|
|
|
|
goto error;
|
|
|
|
cfg->nfirmwares = 1;
|
|
|
|
if (VIR_ALLOC(cfg->firmwares[0]) < 0)
|
|
|
|
goto error;
|
|
|
|
if (VIR_STRDUP(cfg->firmwares[0]->name,
|
|
|
|
LIBXL_FIRMWARE_DIR "/ovmf.bin") < 0)
|
|
|
|
goto error;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Always add hvmloader to firmwares */
|
|
|
|
if (VIR_REALLOC_N(cfg->firmwares, cfg->nfirmwares + 1) < 0)
|
|
|
|
goto error;
|
|
|
|
cfg->nfirmwares++;
|
|
|
|
if (VIR_ALLOC(cfg->firmwares[cfg->nfirmwares - 1]) < 0)
|
|
|
|
goto error;
|
|
|
|
if (VIR_STRDUP(cfg->firmwares[cfg->nfirmwares - 1]->name,
|
|
|
|
LIBXL_FIRMWARE_DIR "/hvmloader") < 0)
|
|
|
|
goto error;
|
|
|
|
|
2013-08-30 20:52:14 +00:00
|
|
|
return cfg;
|
|
|
|
|
2014-03-25 06:51:17 +00:00
|
|
|
error:
|
2013-08-30 20:52:14 +00:00
|
|
|
virObjectUnref(cfg);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
libxlDriverConfigPtr
|
|
|
|
libxlDriverConfigGet(libxlDriverPrivatePtr driver)
|
|
|
|
{
|
2013-08-30 20:57:42 +00:00
|
|
|
libxlDriverConfigPtr cfg;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
cfg = virObjectRef(driver->config);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
return cfg;
|
2013-08-30 20:52:14 +00:00
|
|
|
}
|
|
|
|
|
2013-09-09 15:15:15 +00:00
|
|
|
int libxlDriverConfigLoadFile(libxlDriverConfigPtr cfg,
|
|
|
|
const char *filename)
|
|
|
|
{
|
|
|
|
virConfPtr conf = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
2016-02-05 20:45:03 +00:00
|
|
|
/* defaults for keepalive messages */
|
|
|
|
cfg->keepAliveInterval = 5;
|
|
|
|
cfg->keepAliveCount = 5;
|
|
|
|
|
2013-09-09 15:15:15 +00:00
|
|
|
/* Check the file is readable before opening it, otherwise
|
|
|
|
* libvirt emits an error.
|
|
|
|
*/
|
|
|
|
if (access(filename, R_OK) == -1) {
|
|
|
|
VIR_INFO("Could not read libxl config file %s", filename);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(conf = virConfReadFile(filename, 0)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* setup autoballoon */
|
|
|
|
if (libxlGetAutoballoonConf(cfg, conf) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-07-08 12:52:04 +00:00
|
|
|
if (virConfGetValueString(conf, "lock_manager", &cfg->lockManagerName) < 0)
|
|
|
|
goto cleanup;
|
2016-02-05 20:45:03 +00:00
|
|
|
|
2016-07-08 12:52:04 +00:00
|
|
|
if (virConfGetValueInt(conf, "keepalive_interval", &cfg->keepAliveInterval) < 0)
|
|
|
|
goto cleanup;
|
2016-02-05 20:45:03 +00:00
|
|
|
|
2016-07-08 12:52:04 +00:00
|
|
|
if (virConfGetValueUInt(conf, "keepalive_count", &cfg->keepAliveCount) < 0)
|
|
|
|
goto cleanup;
|
2016-02-05 20:45:03 +00:00
|
|
|
|
2013-09-09 15:15:15 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virConfFree(conf);
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-02-01 00:10:34 +00:00
|
|
|
/*
|
|
|
|
* dom0's maximum memory can be controled by the user with the 'dom0_mem' Xen
|
|
|
|
* command line parameter. E.g. to set dom0's initial memory to 4G and max
|
|
|
|
* memory to 8G: dom0_mem=4G,max:8G
|
|
|
|
* Supported unit suffixes are [bBkKmMgGtT]. If not specified the default
|
|
|
|
* unit is kilobytes.
|
|
|
|
*
|
|
|
|
* If not constrained by the user, dom0 can effectively use all host memory.
|
|
|
|
* This function returns the configured maximum memory for dom0 in kilobytes,
|
|
|
|
* either the user-specified value or total physical memory as a default.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
libxlDriverGetDom0MaxmemConf(libxlDriverConfigPtr cfg,
|
|
|
|
unsigned long long *maxmem)
|
|
|
|
{
|
|
|
|
char **cmd_tokens = NULL;
|
|
|
|
char **mem_tokens = NULL;
|
|
|
|
size_t i;
|
|
|
|
size_t j;
|
|
|
|
libxl_physinfo physinfo;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (cfg->verInfo->commandline == NULL ||
|
|
|
|
!(cmd_tokens = virStringSplit(cfg->verInfo->commandline, " ", 0)))
|
|
|
|
goto physmem;
|
|
|
|
|
|
|
|
for (i = 0; cmd_tokens[i] != NULL; i++) {
|
|
|
|
if (!STRPREFIX(cmd_tokens[i], "dom0_mem="))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!(mem_tokens = virStringSplit(cmd_tokens[i], ",", 0)))
|
|
|
|
break;
|
|
|
|
for (j = 0; mem_tokens[j] != NULL; j++) {
|
|
|
|
if (STRPREFIX(mem_tokens[j], "max:")) {
|
|
|
|
char *p = mem_tokens[j] + 4;
|
|
|
|
unsigned long long multiplier = 1;
|
|
|
|
|
|
|
|
while (c_isdigit(*p))
|
|
|
|
p++;
|
|
|
|
if (virStrToLong_ull(mem_tokens[j] + 4, &p, 10, maxmem) < 0)
|
|
|
|
break;
|
|
|
|
if (*p) {
|
|
|
|
switch (*p) {
|
|
|
|
case 'm':
|
|
|
|
case 'M':
|
|
|
|
multiplier = 1024;
|
|
|
|
break;
|
|
|
|
case 'g':
|
|
|
|
case 'G':
|
|
|
|
multiplier = 1024 * 1024;
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
case 'T':
|
|
|
|
multiplier = 1024 * 1024 * 1024;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*maxmem = *maxmem * multiplier;
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
2017-02-10 11:54:56 +00:00
|
|
|
virStringListFree(mem_tokens);
|
2017-02-15 17:45:27 +00:00
|
|
|
mem_tokens = NULL;
|
2017-02-01 00:10:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
physmem:
|
|
|
|
/* No 'max' specified in dom0_mem, so dom0 can use all physical memory */
|
|
|
|
libxl_physinfo_init(&physinfo);
|
|
|
|
if (libxl_get_physinfo(cfg->ctx, &physinfo)) {
|
|
|
|
VIR_WARN("libxl_get_physinfo failed");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
*maxmem = (physinfo.total_pages * cfg->verInfo->pagesize) / 1024;
|
|
|
|
libxl_physinfo_dispose(&physinfo);
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virStringListFree(cmd_tokens);
|
|
|
|
virStringListFree(mem_tokens);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
libxl: channels support
And allow libxl to handle channel element which creates a Xen
console visible to the guest as a low-bandwitdh communication
channel. If type is PTY we also fetch the tty after boot using
libxl_channel_getinfo to fetch the tty path. On socket case,
we autogenerate a path if not specified in the XML. Path autogenerated
is slightly different from qemu driver: qemu stores also on
"channels/target" but it creates then a directory per domain with
each channel target name. libxl doesn't appear to have a clear
definition of private files associated with each domain, so for
simplicity we do it slightly different. On qemu each autogenerated
channel goes like:
channels/target/<domain-name>/<target name>
Whereas for libxl:
channels/target/<domain-name>-<target name>
Should note that if path is not specified it won't persist,
existing only on live XML, unless user had initially specified it.
Since support for libxl channels only came on Xen >= 4.5 we therefore
need to conditionally compile it with LIBXL_HAVE_DEVICE_CHANNEL.
After this patch and having a qemu guest agent:
$ cat domain.xml | grep -a1 channel | head -n 5 | tail -n 4
<channel type='unix'>
<source mode='bind' path='/tmp/channel'/>
<target type='xen' name='org.qemu.guest_agent.0'/>
</channel>
$ virsh create domain.xml
$ echo '{"execute":"guest-network-get-interfaces"}' | socat
stdio,ignoreeof unix-connect:/tmp/channel
{"execute":"guest-network-get-interfaces"}
{"return": [{"name": "lo", "ip-addresses": [{"ip-address-type": "ipv4",
"ip-address": "127.0.0.1", "prefix": 8}, {"ip-address-type": "ipv6",
"ip-address": "::1", "prefix": 128}], "hardware-address":
"00:00:00:00:00:00"}, {"name": "eth0", "ip-addresses":
[{"ip-address-type": "ipv4", "ip-address": "10.100.0.6", "prefix": 24},
{"ip-address-type": "ipv6", "ip-address": "fe80::216:3eff:fe40:88eb",
"prefix": 64}], "hardware-address": "00:16:3e:40:88:eb"}, {"name":
"sit0"}]}
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2016-09-26 17:33:16 +00:00
|
|
|
#ifdef LIBXL_HAVE_DEVICE_CHANNEL
|
|
|
|
static int
|
|
|
|
libxlPrepareChannel(virDomainChrDefPtr channel,
|
|
|
|
const char *channelDir,
|
|
|
|
const char *domainName)
|
|
|
|
{
|
|
|
|
if (channel->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN &&
|
2016-10-21 11:45:54 +00:00
|
|
|
channel->source->type == VIR_DOMAIN_CHR_TYPE_UNIX &&
|
|
|
|
!channel->source->data.nix.path) {
|
|
|
|
if (virAsprintf(&channel->source->data.nix.path,
|
libxl: channels support
And allow libxl to handle channel element which creates a Xen
console visible to the guest as a low-bandwitdh communication
channel. If type is PTY we also fetch the tty after boot using
libxl_channel_getinfo to fetch the tty path. On socket case,
we autogenerate a path if not specified in the XML. Path autogenerated
is slightly different from qemu driver: qemu stores also on
"channels/target" but it creates then a directory per domain with
each channel target name. libxl doesn't appear to have a clear
definition of private files associated with each domain, so for
simplicity we do it slightly different. On qemu each autogenerated
channel goes like:
channels/target/<domain-name>/<target name>
Whereas for libxl:
channels/target/<domain-name>-<target name>
Should note that if path is not specified it won't persist,
existing only on live XML, unless user had initially specified it.
Since support for libxl channels only came on Xen >= 4.5 we therefore
need to conditionally compile it with LIBXL_HAVE_DEVICE_CHANNEL.
After this patch and having a qemu guest agent:
$ cat domain.xml | grep -a1 channel | head -n 5 | tail -n 4
<channel type='unix'>
<source mode='bind' path='/tmp/channel'/>
<target type='xen' name='org.qemu.guest_agent.0'/>
</channel>
$ virsh create domain.xml
$ echo '{"execute":"guest-network-get-interfaces"}' | socat
stdio,ignoreeof unix-connect:/tmp/channel
{"execute":"guest-network-get-interfaces"}
{"return": [{"name": "lo", "ip-addresses": [{"ip-address-type": "ipv4",
"ip-address": "127.0.0.1", "prefix": 8}, {"ip-address-type": "ipv6",
"ip-address": "::1", "prefix": 128}], "hardware-address":
"00:00:00:00:00:00"}, {"name": "eth0", "ip-addresses":
[{"ip-address-type": "ipv4", "ip-address": "10.100.0.6", "prefix": 24},
{"ip-address-type": "ipv6", "ip-address": "fe80::216:3eff:fe40:88eb",
"prefix": 64}], "hardware-address": "00:16:3e:40:88:eb"}, {"name":
"sit0"}]}
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2016-09-26 17:33:16 +00:00
|
|
|
"%s/%s-%s", channelDir, domainName,
|
|
|
|
channel->target.name ? channel->target.name
|
|
|
|
: "unknown.sock") < 0)
|
|
|
|
return -1;
|
|
|
|
|
2016-10-21 11:45:54 +00:00
|
|
|
channel->source->data.nix.listen = true;
|
libxl: channels support
And allow libxl to handle channel element which creates a Xen
console visible to the guest as a low-bandwitdh communication
channel. If type is PTY we also fetch the tty after boot using
libxl_channel_getinfo to fetch the tty path. On socket case,
we autogenerate a path if not specified in the XML. Path autogenerated
is slightly different from qemu driver: qemu stores also on
"channels/target" but it creates then a directory per domain with
each channel target name. libxl doesn't appear to have a clear
definition of private files associated with each domain, so for
simplicity we do it slightly different. On qemu each autogenerated
channel goes like:
channels/target/<domain-name>/<target name>
Whereas for libxl:
channels/target/<domain-name>-<target name>
Should note that if path is not specified it won't persist,
existing only on live XML, unless user had initially specified it.
Since support for libxl channels only came on Xen >= 4.5 we therefore
need to conditionally compile it with LIBXL_HAVE_DEVICE_CHANNEL.
After this patch and having a qemu guest agent:
$ cat domain.xml | grep -a1 channel | head -n 5 | tail -n 4
<channel type='unix'>
<source mode='bind' path='/tmp/channel'/>
<target type='xen' name='org.qemu.guest_agent.0'/>
</channel>
$ virsh create domain.xml
$ echo '{"execute":"guest-network-get-interfaces"}' | socat
stdio,ignoreeof unix-connect:/tmp/channel
{"execute":"guest-network-get-interfaces"}
{"return": [{"name": "lo", "ip-addresses": [{"ip-address-type": "ipv4",
"ip-address": "127.0.0.1", "prefix": 8}, {"ip-address-type": "ipv6",
"ip-address": "::1", "prefix": 128}], "hardware-address":
"00:00:00:00:00:00"}, {"name": "eth0", "ip-addresses":
[{"ip-address-type": "ipv4", "ip-address": "10.100.0.6", "prefix": 24},
{"ip-address-type": "ipv6", "ip-address": "fe80::216:3eff:fe40:88eb",
"prefix": 64}], "hardware-address": "00:16:3e:40:88:eb"}, {"name":
"sit0"}]}
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2016-09-26 17:33:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlMakeChannel(virDomainChrDefPtr l_channel,
|
|
|
|
libxl_device_channel *x_channel)
|
|
|
|
{
|
|
|
|
libxl_device_channel_init(x_channel);
|
|
|
|
|
|
|
|
if (l_channel->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("channel target type not supported"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-10-21 11:45:54 +00:00
|
|
|
switch (l_channel->source->type) {
|
libxl: channels support
And allow libxl to handle channel element which creates a Xen
console visible to the guest as a low-bandwitdh communication
channel. If type is PTY we also fetch the tty after boot using
libxl_channel_getinfo to fetch the tty path. On socket case,
we autogenerate a path if not specified in the XML. Path autogenerated
is slightly different from qemu driver: qemu stores also on
"channels/target" but it creates then a directory per domain with
each channel target name. libxl doesn't appear to have a clear
definition of private files associated with each domain, so for
simplicity we do it slightly different. On qemu each autogenerated
channel goes like:
channels/target/<domain-name>/<target name>
Whereas for libxl:
channels/target/<domain-name>-<target name>
Should note that if path is not specified it won't persist,
existing only on live XML, unless user had initially specified it.
Since support for libxl channels only came on Xen >= 4.5 we therefore
need to conditionally compile it with LIBXL_HAVE_DEVICE_CHANNEL.
After this patch and having a qemu guest agent:
$ cat domain.xml | grep -a1 channel | head -n 5 | tail -n 4
<channel type='unix'>
<source mode='bind' path='/tmp/channel'/>
<target type='xen' name='org.qemu.guest_agent.0'/>
</channel>
$ virsh create domain.xml
$ echo '{"execute":"guest-network-get-interfaces"}' | socat
stdio,ignoreeof unix-connect:/tmp/channel
{"execute":"guest-network-get-interfaces"}
{"return": [{"name": "lo", "ip-addresses": [{"ip-address-type": "ipv4",
"ip-address": "127.0.0.1", "prefix": 8}, {"ip-address-type": "ipv6",
"ip-address": "::1", "prefix": 128}], "hardware-address":
"00:00:00:00:00:00"}, {"name": "eth0", "ip-addresses":
[{"ip-address-type": "ipv4", "ip-address": "10.100.0.6", "prefix": 24},
{"ip-address-type": "ipv6", "ip-address": "fe80::216:3eff:fe40:88eb",
"prefix": 64}], "hardware-address": "00:16:3e:40:88:eb"}, {"name":
"sit0"}]}
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2016-09-26 17:33:16 +00:00
|
|
|
case VIR_DOMAIN_CHR_TYPE_PTY:
|
|
|
|
x_channel->connection = LIBXL_CHANNEL_CONNECTION_PTY;
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_UNIX:
|
|
|
|
x_channel->connection = LIBXL_CHANNEL_CONNECTION_SOCKET;
|
|
|
|
if (VIR_STRDUP(x_channel->u.socket.path,
|
2016-10-21 11:45:54 +00:00
|
|
|
l_channel->source->data.nix.path) < 0)
|
libxl: channels support
And allow libxl to handle channel element which creates a Xen
console visible to the guest as a low-bandwitdh communication
channel. If type is PTY we also fetch the tty after boot using
libxl_channel_getinfo to fetch the tty path. On socket case,
we autogenerate a path if not specified in the XML. Path autogenerated
is slightly different from qemu driver: qemu stores also on
"channels/target" but it creates then a directory per domain with
each channel target name. libxl doesn't appear to have a clear
definition of private files associated with each domain, so for
simplicity we do it slightly different. On qemu each autogenerated
channel goes like:
channels/target/<domain-name>/<target name>
Whereas for libxl:
channels/target/<domain-name>-<target name>
Should note that if path is not specified it won't persist,
existing only on live XML, unless user had initially specified it.
Since support for libxl channels only came on Xen >= 4.5 we therefore
need to conditionally compile it with LIBXL_HAVE_DEVICE_CHANNEL.
After this patch and having a qemu guest agent:
$ cat domain.xml | grep -a1 channel | head -n 5 | tail -n 4
<channel type='unix'>
<source mode='bind' path='/tmp/channel'/>
<target type='xen' name='org.qemu.guest_agent.0'/>
</channel>
$ virsh create domain.xml
$ echo '{"execute":"guest-network-get-interfaces"}' | socat
stdio,ignoreeof unix-connect:/tmp/channel
{"execute":"guest-network-get-interfaces"}
{"return": [{"name": "lo", "ip-addresses": [{"ip-address-type": "ipv4",
"ip-address": "127.0.0.1", "prefix": 8}, {"ip-address-type": "ipv6",
"ip-address": "::1", "prefix": 128}], "hardware-address":
"00:00:00:00:00:00"}, {"name": "eth0", "ip-addresses":
[{"ip-address-type": "ipv4", "ip-address": "10.100.0.6", "prefix": 24},
{"ip-address-type": "ipv6", "ip-address": "fe80::216:3eff:fe40:88eb",
"prefix": 64}], "hardware-address": "00:16:3e:40:88:eb"}, {"name":
"sit0"}]}
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2016-09-26 17:33:16 +00:00
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("channel source type not supported"));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!l_channel->target.name) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("channel target name missing"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_STRDUP(x_channel->name, l_channel->target.name) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlMakeChannelList(const char *channelDir,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
libxl_domain_config *d_config)
|
|
|
|
{
|
|
|
|
virDomainChrDefPtr *l_channels = def->channels;
|
|
|
|
size_t nchannels = def->nchannels;
|
|
|
|
libxl_device_channel *x_channels;
|
|
|
|
size_t i, nvchannels = 0;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(x_channels, nchannels) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0; i < nchannels; i++) {
|
|
|
|
if (l_channels[i]->deviceType != VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (libxlPrepareChannel(l_channels[i], channelDir, def->name) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (libxlMakeChannel(l_channels[i], &x_channels[nvchannels]) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
nvchannels++;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_SHRINK_N(x_channels, nchannels, nchannels - nvchannels);
|
|
|
|
d_config->channels = x_channels;
|
|
|
|
d_config->num_channels = nvchannels;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
for (i = 0; i < nchannels; i++)
|
|
|
|
libxl_device_channel_dispose(&x_channels[i]);
|
|
|
|
VIR_FREE(x_channels);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-05-19 08:14:33 +00:00
|
|
|
#ifdef LIBXL_HAVE_PVUSB
|
2016-06-15 06:00:09 +00:00
|
|
|
int
|
|
|
|
libxlMakeUSBController(virDomainControllerDefPtr controller,
|
|
|
|
libxl_device_usbctrl *usbctrl)
|
|
|
|
{
|
|
|
|
usbctrl->devid = controller->idx;
|
|
|
|
|
|
|
|
if (controller->type != VIR_DOMAIN_CONTROLLER_TYPE_USB)
|
|
|
|
return -1;
|
|
|
|
|
2018-02-14 10:51:26 +00:00
|
|
|
if (controller->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_DEFAULT) {
|
2016-06-15 06:00:09 +00:00
|
|
|
usbctrl->version = 2;
|
|
|
|
usbctrl->type = LIBXL_USBCTRL_TYPE_QUSB;
|
|
|
|
} else {
|
|
|
|
switch (controller->model) {
|
|
|
|
case VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB1:
|
|
|
|
usbctrl->version = 1;
|
|
|
|
usbctrl->type = LIBXL_USBCTRL_TYPE_QUSB;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB2:
|
|
|
|
usbctrl->version = 2;
|
|
|
|
usbctrl->type = LIBXL_USBCTRL_TYPE_QUSB;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("unsupported usb model"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (controller->opts.usbopts.ports == -1)
|
|
|
|
usbctrl->ports = 8;
|
|
|
|
else
|
|
|
|
usbctrl->ports = controller->opts.usbopts.ports;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-03-28 23:34:16 +00:00
|
|
|
static int
|
|
|
|
libxlMakeDefaultUSBControllers(virDomainDefPtr def,
|
|
|
|
libxl_domain_config *d_config)
|
|
|
|
{
|
|
|
|
virDomainControllerDefPtr l_controller = NULL;
|
|
|
|
libxl_device_usbctrl *x_controllers = NULL;
|
|
|
|
size_t nusbdevs = 0;
|
|
|
|
size_t ncontrollers;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < def->nhostdevs; i++) {
|
|
|
|
if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
|
|
|
|
def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
|
|
|
|
nusbdevs++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No controllers needed if there are no USB devs */
|
|
|
|
if (nusbdevs == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Create USB controllers with 8 ports */
|
|
|
|
ncontrollers = VIR_DIV_UP(nusbdevs, 8);
|
|
|
|
if (VIR_ALLOC_N(x_controllers, ncontrollers) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0; i < ncontrollers; i++) {
|
|
|
|
if (!(l_controller = virDomainControllerDefNew(VIR_DOMAIN_CONTROLLER_TYPE_USB)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
l_controller->model = VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB2;
|
|
|
|
l_controller->idx = i;
|
|
|
|
l_controller->opts.usbopts.ports = 8;
|
|
|
|
|
|
|
|
libxl_device_usbctrl_init(&x_controllers[i]);
|
|
|
|
|
|
|
|
if (libxlMakeUSBController(l_controller, &x_controllers[i]) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (virDomainControllerInsert(def, l_controller) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
l_controller = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
d_config->usbctrls = x_controllers;
|
|
|
|
d_config->num_usbctrls = ncontrollers;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virDomainControllerDefFree(l_controller);
|
|
|
|
for (i = 0; i < ncontrollers; i++)
|
|
|
|
libxl_device_usbctrl_dispose(&x_controllers[i]);
|
|
|
|
VIR_FREE(x_controllers);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-06-15 06:00:09 +00:00
|
|
|
static int
|
|
|
|
libxlMakeUSBControllerList(virDomainDefPtr def, libxl_domain_config *d_config)
|
|
|
|
{
|
|
|
|
virDomainControllerDefPtr *l_controllers = def->controllers;
|
|
|
|
size_t ncontrollers = def->ncontrollers;
|
|
|
|
size_t nusbctrls = 0;
|
|
|
|
libxl_device_usbctrl *x_usbctrls;
|
2017-03-28 23:34:16 +00:00
|
|
|
size_t i, j;
|
2016-06-15 06:00:09 +00:00
|
|
|
|
2017-03-28 23:34:16 +00:00
|
|
|
for (i = 0; i < ncontrollers; i++) {
|
|
|
|
if (l_controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB)
|
|
|
|
nusbctrls++;
|
|
|
|
}
|
2016-06-15 06:00:09 +00:00
|
|
|
|
2017-03-28 23:34:16 +00:00
|
|
|
if (nusbctrls == 0)
|
|
|
|
return libxlMakeDefaultUSBControllers(def, d_config);
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(x_usbctrls, nusbctrls) < 0)
|
2016-06-15 06:00:09 +00:00
|
|
|
return -1;
|
|
|
|
|
2017-03-28 23:34:16 +00:00
|
|
|
for (i = 0, j = 0; i < ncontrollers && j < nusbctrls; i++) {
|
2016-06-15 06:00:09 +00:00
|
|
|
if (l_controllers[i]->type != VIR_DOMAIN_CONTROLLER_TYPE_USB)
|
|
|
|
continue;
|
|
|
|
|
2017-03-28 23:34:16 +00:00
|
|
|
libxl_device_usbctrl_init(&x_usbctrls[j]);
|
2016-06-15 06:00:09 +00:00
|
|
|
|
|
|
|
if (libxlMakeUSBController(l_controllers[i],
|
2017-03-28 23:34:16 +00:00
|
|
|
&x_usbctrls[j]) < 0)
|
2016-06-15 06:00:09 +00:00
|
|
|
goto error;
|
|
|
|
|
2017-03-28 23:34:16 +00:00
|
|
|
j++;
|
2016-06-15 06:00:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
d_config->usbctrls = x_usbctrls;
|
|
|
|
d_config->num_usbctrls = nusbctrls;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
for (i = 0; i < nusbctrls; i++)
|
|
|
|
libxl_device_usbctrl_dispose(&x_usbctrls[i]);
|
|
|
|
|
|
|
|
VIR_FREE(x_usbctrls);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-05-19 08:14:33 +00:00
|
|
|
int
|
|
|
|
libxlMakeUSB(virDomainHostdevDefPtr hostdev, libxl_device_usbdev *usbdev)
|
|
|
|
{
|
|
|
|
virDomainHostdevSubsysUSBPtr usbsrc = &hostdev->source.subsys.u.usb;
|
2016-08-11 00:39:12 +00:00
|
|
|
virUSBDevicePtr usb = NULL;
|
|
|
|
int ret = -1;
|
2016-05-19 08:14:33 +00:00
|
|
|
|
|
|
|
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
|
2016-08-11 00:39:12 +00:00
|
|
|
return ret;
|
2016-05-19 08:14:33 +00:00
|
|
|
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
|
2016-08-11 00:39:12 +00:00
|
|
|
return ret;
|
2016-05-19 08:14:33 +00:00
|
|
|
|
2016-08-11 00:39:12 +00:00
|
|
|
if (usbsrc->bus > 0 && usbsrc->device > 0) {
|
|
|
|
usbdev->u.hostdev.hostbus = usbsrc->bus;
|
|
|
|
usbdev->u.hostdev.hostaddr = usbsrc->device;
|
|
|
|
} else {
|
|
|
|
if (virHostdevFindUSBDevice(hostdev, true, &usb) < 0) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("failed to find USB device busnum:devnum "
|
|
|
|
"for %x:%x"),
|
|
|
|
usbsrc->vendor, usbsrc->product);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
usbdev->u.hostdev.hostbus = virUSBDeviceGetBus(usb);
|
|
|
|
usbdev->u.hostdev.hostaddr = virUSBDeviceGetDevno(usb);
|
2016-05-19 08:14:33 +00:00
|
|
|
}
|
|
|
|
|
2016-08-11 00:39:12 +00:00
|
|
|
ret = 0;
|
2016-05-19 08:14:33 +00:00
|
|
|
|
2016-08-11 00:39:12 +00:00
|
|
|
cleanup:
|
|
|
|
virUSBDeviceFree(usb);
|
|
|
|
|
|
|
|
return ret;
|
2016-05-19 08:14:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlMakeUSBList(virDomainDefPtr def, libxl_domain_config *d_config)
|
|
|
|
{
|
|
|
|
virDomainHostdevDefPtr *l_hostdevs = def->hostdevs;
|
|
|
|
size_t nhostdevs = def->nhostdevs;
|
|
|
|
size_t nusbdevs = 0;
|
|
|
|
libxl_device_usbdev *x_usbdevs;
|
|
|
|
size_t i, j;
|
|
|
|
|
|
|
|
if (nhostdevs == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(x_usbdevs, nhostdevs) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0, j = 0; i < nhostdevs; i++) {
|
|
|
|
if (l_hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
|
|
|
|
continue;
|
|
|
|
if (l_hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
libxl_device_usbdev_init(&x_usbdevs[j]);
|
|
|
|
|
|
|
|
if (libxlMakeUSB(l_hostdevs[i], &x_usbdevs[j]) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
nusbdevs++;
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_SHRINK_N(x_usbdevs, nhostdevs, nhostdevs - nusbdevs);
|
|
|
|
d_config->usbdevs = x_usbdevs;
|
|
|
|
d_config->num_usbdevs = nusbdevs;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
for (i = 0; i < nusbdevs; i++)
|
|
|
|
libxl_device_usbdev_dispose(&x_usbdevs[i]);
|
|
|
|
|
|
|
|
VIR_FREE(x_usbdevs);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-03-06 09:46:11 +00:00
|
|
|
int
|
2014-03-13 11:59:32 +00:00
|
|
|
libxlMakePCI(virDomainHostdevDefPtr hostdev, libxl_device_pci *pcidev)
|
2014-03-06 09:46:11 +00:00
|
|
|
{
|
2014-07-03 20:31:39 +00:00
|
|
|
virDomainHostdevSubsysPCIPtr pcisrc = &hostdev->source.subsys.u.pci;
|
2014-03-06 09:46:11 +00:00
|
|
|
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
|
|
|
|
return -1;
|
|
|
|
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
|
|
|
|
return -1;
|
|
|
|
|
2014-07-03 20:31:39 +00:00
|
|
|
pcidev->domain = pcisrc->addr.domain;
|
|
|
|
pcidev->bus = pcisrc->addr.bus;
|
|
|
|
pcidev->dev = pcisrc->addr.slot;
|
|
|
|
pcidev->func = pcisrc->addr.function;
|
2014-03-06 09:46:11 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-03-13 11:59:32 +00:00
|
|
|
libxlMakePCIList(virDomainDefPtr def, libxl_domain_config *d_config)
|
2014-03-06 09:46:11 +00:00
|
|
|
{
|
|
|
|
virDomainHostdevDefPtr *l_hostdevs = def->hostdevs;
|
|
|
|
size_t nhostdevs = def->nhostdevs;
|
|
|
|
size_t npcidevs = 0;
|
|
|
|
libxl_device_pci *x_pcidevs;
|
|
|
|
size_t i, j;
|
|
|
|
|
|
|
|
if (nhostdevs == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(x_pcidevs, nhostdevs) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0, j = 0; i < nhostdevs; i++) {
|
|
|
|
if (l_hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
|
|
|
|
continue;
|
|
|
|
if (l_hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
libxl_device_pci_init(&x_pcidevs[j]);
|
|
|
|
|
2014-03-13 11:59:32 +00:00
|
|
|
if (libxlMakePCI(l_hostdevs[i], &x_pcidevs[j]) < 0)
|
2014-03-06 09:46:11 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
npcidevs++;
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_SHRINK_N(x_pcidevs, nhostdevs, nhostdevs - npcidevs);
|
|
|
|
d_config->pcidevs = x_pcidevs;
|
|
|
|
d_config->num_pcidevs = npcidevs;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:51:17 +00:00
|
|
|
error:
|
2014-03-06 09:46:11 +00:00
|
|
|
for (i = 0; i < npcidevs; i++)
|
|
|
|
libxl_device_pci_dispose(&x_pcidevs[i]);
|
|
|
|
|
|
|
|
VIR_FREE(x_pcidevs);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-07-01 07:58:18 +00:00
|
|
|
static int
|
|
|
|
libxlMakeVideo(virDomainDefPtr def, libxl_domain_config *d_config)
|
|
|
|
|
|
|
|
{
|
|
|
|
libxl_domain_build_info *b_info = &d_config->b_info;
|
|
|
|
int dm_type = libxlDomainGetEmulatorType(def);
|
|
|
|
|
|
|
|
if (d_config->c_info.type != LIBXL_DOMAIN_TYPE_HVM)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Take the first defined video device (graphics card) to display
|
|
|
|
* on the first graphics device (display).
|
|
|
|
*/
|
|
|
|
if (def->nvideos) {
|
|
|
|
switch (def->videos[0]->type) {
|
|
|
|
case VIR_DOMAIN_VIDEO_TYPE_VGA:
|
|
|
|
case VIR_DOMAIN_VIDEO_TYPE_XEN:
|
|
|
|
b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_STD;
|
|
|
|
if (dm_type == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
|
|
|
|
if (def->videos[0]->vram < 16 * 1024) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("videoram must be at least 16MB for VGA"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (def->videos[0]->vram < 8 * 1024) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("videoram must be at least 8MB for VGA"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
|
|
|
|
b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
|
|
|
|
if (dm_type == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
|
|
|
|
if (def->videos[0]->vram < 8 * 1024) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("videoram must be at least 8MB for CIRRUS"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (def->videos[0]->vram < 4 * 1024) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("videoram must be at least 4MB for CIRRUS"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2015-04-29 16:50:33 +00:00
|
|
|
#ifdef LIBXL_HAVE_QXL
|
|
|
|
case VIR_DOMAIN_VIDEO_TYPE_QXL:
|
|
|
|
b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_QXL;
|
|
|
|
if (def->videos[0]->vram < 128 * 1024) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("videoram must be at least 128MB for QXL"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
2014-07-01 07:58:18 +00:00
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("video type %s is not supported by libxl"),
|
|
|
|
virDomainVideoTypeToString(def->videos[0]->type));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
/* vram validated for each video type, now set it */
|
|
|
|
b_info->video_memkb = def->videos[0]->vram;
|
|
|
|
} else {
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.nographic, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-02-26 20:44:09 +00:00
|
|
|
int
|
|
|
|
libxlDriverNodeGetInfo(libxlDriverPrivatePtr driver, virNodeInfoPtr info)
|
|
|
|
{
|
|
|
|
libxl_physinfo phy_info;
|
|
|
|
virArch hostarch = virArchFromHost();
|
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
|
|
|
int ret = -1;
|
|
|
|
|
2017-02-01 03:07:30 +00:00
|
|
|
libxl_physinfo_init(&phy_info);
|
2014-02-26 20:44:09 +00:00
|
|
|
if (libxl_get_physinfo(cfg->ctx, &phy_info)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxl_get_physinfo_info failed"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virStrcpyStatic(info->model, virArchToString(hostarch)) == NULL) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("machine type %s too big for destination"),
|
|
|
|
virArchToString(hostarch));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
info->memory = phy_info.total_pages * (cfg->verInfo->pagesize / 1024);
|
|
|
|
info->cpus = phy_info.nr_cpus;
|
|
|
|
info->nodes = phy_info.nr_nodes;
|
|
|
|
info->cores = phy_info.cores_per_socket;
|
|
|
|
info->threads = phy_info.threads_per_core;
|
|
|
|
info->sockets = 1;
|
|
|
|
info->mhz = phy_info.cpu_khz / 1000;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:51:17 +00:00
|
|
|
cleanup:
|
2017-02-01 03:07:30 +00:00
|
|
|
libxl_physinfo_dispose(&phy_info);
|
2014-02-26 20:44:09 +00:00
|
|
|
virObjectUnref(cfg);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
int
|
2018-02-06 09:09:06 +00:00
|
|
|
libxlBuildDomainConfig(virPortAllocatorRangePtr graphicsports,
|
2014-05-30 13:46:35 +00:00
|
|
|
virDomainDefPtr def,
|
libxl: channels support
And allow libxl to handle channel element which creates a Xen
console visible to the guest as a low-bandwitdh communication
channel. If type is PTY we also fetch the tty after boot using
libxl_channel_getinfo to fetch the tty path. On socket case,
we autogenerate a path if not specified in the XML. Path autogenerated
is slightly different from qemu driver: qemu stores also on
"channels/target" but it creates then a directory per domain with
each channel target name. libxl doesn't appear to have a clear
definition of private files associated with each domain, so for
simplicity we do it slightly different. On qemu each autogenerated
channel goes like:
channels/target/<domain-name>/<target name>
Whereas for libxl:
channels/target/<domain-name>-<target name>
Should note that if path is not specified it won't persist,
existing only on live XML, unless user had initially specified it.
Since support for libxl channels only came on Xen >= 4.5 we therefore
need to conditionally compile it with LIBXL_HAVE_DEVICE_CHANNEL.
After this patch and having a qemu guest agent:
$ cat domain.xml | grep -a1 channel | head -n 5 | tail -n 4
<channel type='unix'>
<source mode='bind' path='/tmp/channel'/>
<target type='xen' name='org.qemu.guest_agent.0'/>
</channel>
$ virsh create domain.xml
$ echo '{"execute":"guest-network-get-interfaces"}' | socat
stdio,ignoreeof unix-connect:/tmp/channel
{"execute":"guest-network-get-interfaces"}
{"return": [{"name": "lo", "ip-addresses": [{"ip-address-type": "ipv4",
"ip-address": "127.0.0.1", "prefix": 8}, {"ip-address-type": "ipv6",
"ip-address": "::1", "prefix": 128}], "hardware-address":
"00:00:00:00:00:00"}, {"name": "eth0", "ip-addresses":
[{"ip-address-type": "ipv4", "ip-address": "10.100.0.6", "prefix": 24},
{"ip-address-type": "ipv6", "ip-address": "fe80::216:3eff:fe40:88eb",
"prefix": 64}], "hardware-address": "00:16:3e:40:88:eb"}, {"name":
"sit0"}]}
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2016-09-26 17:33:16 +00:00
|
|
|
const char *channelDir LIBXL_ATTR_UNUSED,
|
2014-05-30 13:46:35 +00:00
|
|
|
libxl_ctx *ctx,
|
2017-04-24 13:06:59 +00:00
|
|
|
virCapsPtr caps,
|
2014-05-30 13:46:35 +00:00
|
|
|
libxl_domain_config *d_config)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
2013-06-13 01:54:10 +00:00
|
|
|
libxl_domain_config_init(d_config);
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2014-05-30 13:46:35 +00:00
|
|
|
if (libxlMakeDomCreateInfo(ctx, def, &d_config->c_info) < 0)
|
2011-02-10 22:42:34 +00:00
|
|
|
return -1;
|
|
|
|
|
2017-04-24 13:06:59 +00:00
|
|
|
if (libxlMakeDomBuildInfo(def, ctx, caps, d_config) < 0)
|
2013-04-29 23:04:55 +00:00
|
|
|
return -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2017-11-02 15:47:22 +00:00
|
|
|
#ifdef LIBXL_HAVE_VNUMA
|
|
|
|
if (libxlMakeVnumaList(def, ctx, d_config) < 0)
|
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
|
2013-08-14 21:33:48 +00:00
|
|
|
if (libxlMakeDiskList(def, d_config) < 0)
|
2013-04-29 23:04:55 +00:00
|
|
|
return -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2013-08-14 21:33:48 +00:00
|
|
|
if (libxlMakeNicList(def, d_config) < 0)
|
2013-04-29 23:04:55 +00:00
|
|
|
return -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2014-05-30 13:48:56 +00:00
|
|
|
if (libxlMakeVfbList(graphicsports, def, d_config) < 0)
|
2013-04-29 23:04:55 +00:00
|
|
|
return -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2015-04-27 22:27:52 +00:00
|
|
|
if (libxlMakeBuildInfoVfb(graphicsports, def, d_config) < 0)
|
2015-04-27 18:32:55 +00:00
|
|
|
return -1;
|
|
|
|
|
2014-03-13 11:59:32 +00:00
|
|
|
if (libxlMakePCIList(def, d_config) < 0)
|
2014-03-06 09:46:11 +00:00
|
|
|
return -1;
|
|
|
|
|
2016-05-19 08:14:33 +00:00
|
|
|
#ifdef LIBXL_HAVE_PVUSB
|
2016-06-15 06:00:09 +00:00
|
|
|
if (libxlMakeUSBControllerList(def, d_config) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2016-05-19 08:14:33 +00:00
|
|
|
if (libxlMakeUSBList(def, d_config) < 0)
|
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
|
libxl: channels support
And allow libxl to handle channel element which creates a Xen
console visible to the guest as a low-bandwitdh communication
channel. If type is PTY we also fetch the tty after boot using
libxl_channel_getinfo to fetch the tty path. On socket case,
we autogenerate a path if not specified in the XML. Path autogenerated
is slightly different from qemu driver: qemu stores also on
"channels/target" but it creates then a directory per domain with
each channel target name. libxl doesn't appear to have a clear
definition of private files associated with each domain, so for
simplicity we do it slightly different. On qemu each autogenerated
channel goes like:
channels/target/<domain-name>/<target name>
Whereas for libxl:
channels/target/<domain-name>-<target name>
Should note that if path is not specified it won't persist,
existing only on live XML, unless user had initially specified it.
Since support for libxl channels only came on Xen >= 4.5 we therefore
need to conditionally compile it with LIBXL_HAVE_DEVICE_CHANNEL.
After this patch and having a qemu guest agent:
$ cat domain.xml | grep -a1 channel | head -n 5 | tail -n 4
<channel type='unix'>
<source mode='bind' path='/tmp/channel'/>
<target type='xen' name='org.qemu.guest_agent.0'/>
</channel>
$ virsh create domain.xml
$ echo '{"execute":"guest-network-get-interfaces"}' | socat
stdio,ignoreeof unix-connect:/tmp/channel
{"execute":"guest-network-get-interfaces"}
{"return": [{"name": "lo", "ip-addresses": [{"ip-address-type": "ipv4",
"ip-address": "127.0.0.1", "prefix": 8}, {"ip-address-type": "ipv6",
"ip-address": "::1", "prefix": 128}], "hardware-address":
"00:00:00:00:00:00"}, {"name": "eth0", "ip-addresses":
[{"ip-address-type": "ipv4", "ip-address": "10.100.0.6", "prefix": 24},
{"ip-address-type": "ipv6", "ip-address": "fe80::216:3eff:fe40:88eb",
"prefix": 64}], "hardware-address": "00:16:3e:40:88:eb"}, {"name":
"sit0"}]}
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2016-09-26 17:33:16 +00:00
|
|
|
#ifdef LIBXL_HAVE_DEVICE_CHANNEL
|
|
|
|
if (libxlMakeChannelList(channelDir, def, d_config) < 0)
|
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
|
2014-07-01 07:58:18 +00:00
|
|
|
/*
|
|
|
|
* Now that any potential VFBs are defined, update the build info with
|
|
|
|
* the data of the primary display. Some day libxl might implicitely do
|
|
|
|
* so but as it does not right now, better be explicit.
|
|
|
|
*/
|
|
|
|
if (libxlMakeVideo(def, d_config) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2014-09-03 20:14:50 +00:00
|
|
|
d_config->on_reboot = libxlActionFromVirLifecycle(def->onReboot);
|
|
|
|
d_config->on_poweroff = libxlActionFromVirLifecycle(def->onPoweroff);
|
2017-10-10 12:51:38 +00:00
|
|
|
d_config->on_crash = libxlActionFromVirLifecycle(def->onCrash);
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2014-05-30 14:53:12 +00:00
|
|
|
|
|
|
|
virDomainXMLOptionPtr
|
|
|
|
libxlCreateXMLConf(void)
|
|
|
|
{
|
|
|
|
return virDomainXMLOptionNew(&libxlDomainDefParserConfig,
|
|
|
|
&libxlDomainXMLPrivateDataCallbacks,
|
2017-06-01 22:44:46 +00:00
|
|
|
NULL, NULL, NULL);
|
2014-05-30 14:53:12 +00:00
|
|
|
}
|