2010-03-14 11:11:51 +00:00
|
|
|
/*
|
|
|
|
* xenapi_utils.c: Xen API driver -- utils parts.
|
2014-03-18 08:14:16 +00:00
|
|
|
* Copyright (C) 2011-2014 Red Hat, Inc.
|
2010-03-14 11:11:51 +00:00
|
|
|
* Copyright (C) 2009, 2010 Citrix Ltd.
|
|
|
|
*
|
|
|
|
* 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/>.
|
2010-03-14 11:11:51 +00:00
|
|
|
*
|
|
|
|
* Author: Sharadha Prabhakar <sharadha.prabhakar@citrix.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <xen/api/xen_all.h>
|
|
|
|
#include "internal.h"
|
|
|
|
#include "domain_conf.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2010-03-14 11:11:51 +00:00
|
|
|
#include "datatypes.h"
|
2012-12-13 18:01:25 +00:00
|
|
|
#include "viruuid.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-04 12:04:07 +00:00
|
|
|
#include "virbuffer.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2012-02-24 18:48:55 +00:00
|
|
|
#include "viruri.h"
|
2010-03-14 11:11:51 +00:00
|
|
|
#include "xenapi_driver_private.h"
|
|
|
|
#include "xenapi_utils.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
2010-03-14 11:11:51 +00:00
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("xenapi.xenapi_utils");
|
|
|
|
|
2010-03-14 11:11:51 +00:00
|
|
|
void
|
|
|
|
xenSessionFree(xen_session *session)
|
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/{xen,xenapi,xenxs} 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;
|
2014-07-15 19:44:26 +00:00
|
|
|
char *tmp;
|
2010-03-14 11:11:51 +00:00
|
|
|
if (session->error_description != NULL) {
|
|
|
|
for (i = 0; i < session->error_description_count; i++)
|
|
|
|
VIR_FREE(session->error_description[i]);
|
|
|
|
VIR_FREE(session->error_description);
|
|
|
|
}
|
2014-07-15 11:36:00 +00:00
|
|
|
/* The session_id member is type of 'const char *'. Sigh. */
|
2014-07-15 19:44:26 +00:00
|
|
|
tmp = (char *)session->session_id;
|
|
|
|
VIR_FREE(tmp);
|
2010-03-14 11:11:51 +00:00
|
|
|
VIR_FREE(session);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
xenapiUtil_RequestPassword(virConnectAuthPtr auth, const char *username,
|
|
|
|
const char *hostname)
|
|
|
|
{
|
|
|
|
unsigned int ncred;
|
|
|
|
virConnectCredential cred;
|
|
|
|
char *prompt;
|
|
|
|
|
2012-03-29 09:52:04 +00:00
|
|
|
memset(&cred, 0, sizeof(virConnectCredential));
|
2010-03-14 11:11:51 +00:00
|
|
|
|
|
|
|
if (virAsprintf(&prompt, "Enter %s password for %s", username,
|
|
|
|
hostname) < 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (ncred = 0; ncred < auth->ncredtype; ncred++) {
|
|
|
|
if (auth->credtype[ncred] != VIR_CRED_PASSPHRASE &&
|
|
|
|
auth->credtype[ncred] != VIR_CRED_NOECHOPROMPT) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
cred.type = auth->credtype[ncred];
|
|
|
|
cred.prompt = prompt;
|
|
|
|
cred.challenge = hostname;
|
|
|
|
cred.defresult = NULL;
|
|
|
|
cred.result = NULL;
|
|
|
|
cred.resultlen = 0;
|
|
|
|
|
2014-11-13 14:29:45 +00:00
|
|
|
if ((*(auth->cb))(&cred, 1, auth->cbdata) < 0)
|
2010-03-14 11:11:51 +00:00
|
|
|
VIR_FREE(cred.result);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(prompt);
|
|
|
|
|
|
|
|
return cred.result;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-02-24 18:48:55 +00:00
|
|
|
xenapiUtil_ParseQuery(virConnectPtr conn, virURIPtr uri, int *noVerify)
|
2010-03-14 11:11:51 +00:00
|
|
|
{
|
|
|
|
int result = 0;
|
Convert 'int i' to 'size_t i' in src/{xen,xenapi,xenxs} 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;
|
2010-03-14 11:11:51 +00:00
|
|
|
|
2012-03-20 14:11:10 +00:00
|
|
|
for (i = 0; i < uri->paramsCount; i++) {
|
|
|
|
virURIParamPtr queryParam = &uri->params[i];
|
2010-03-14 11:11:51 +00:00
|
|
|
if (STRCASEEQ(queryParam->name, "no_verify")) {
|
2014-11-13 14:29:45 +00:00
|
|
|
if (noVerify == NULL)
|
2010-03-14 11:11:51 +00:00
|
|
|
continue;
|
|
|
|
if (virStrToLong_i(queryParam->value, NULL, 10, noVerify) < 0 ||
|
|
|
|
(*noVerify != 0 && *noVerify != 1)) {
|
|
|
|
xenapiSessionErrorHandler(conn, VIR_ERR_INVALID_ARG,
|
2010-03-31 10:24:25 +00:00
|
|
|
_("Query parameter 'no_verify' has unexpected value (should be 0 or 1)"));
|
2010-03-14 11:11:51 +00:00
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2010-03-14 11:11:51 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
failure:
|
2010-03-14 11:11:51 +00:00
|
|
|
result = -1;
|
|
|
|
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enum xen_on_normal_exit
|
2014-06-03 07:18:58 +00:00
|
|
|
actionShutdownLibvirt2XenapiEnum(virDomainLifecycleAction action)
|
2010-03-14 11:11:51 +00:00
|
|
|
{
|
|
|
|
enum xen_on_normal_exit num = XEN_ON_NORMAL_EXIT_RESTART;
|
|
|
|
if (action == VIR_DOMAIN_LIFECYCLE_DESTROY)
|
|
|
|
num = XEN_ON_NORMAL_EXIT_DESTROY;
|
|
|
|
else if (action == VIR_DOMAIN_LIFECYCLE_RESTART)
|
|
|
|
num = XEN_ON_NORMAL_EXIT_RESTART;
|
|
|
|
return num;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
enum xen_on_crash_behaviour
|
2014-06-03 07:18:58 +00:00
|
|
|
actionCrashLibvirt2XenapiEnum(virDomainLifecycleCrashAction action)
|
2010-03-14 11:11:51 +00:00
|
|
|
{
|
|
|
|
enum xen_on_crash_behaviour num = XEN_ON_CRASH_BEHAVIOUR_RESTART;
|
2010-08-12 17:15:44 +00:00
|
|
|
if (action == VIR_DOMAIN_LIFECYCLE_CRASH_DESTROY)
|
2010-03-14 11:11:51 +00:00
|
|
|
num = XEN_ON_CRASH_BEHAVIOUR_DESTROY;
|
2010-08-12 17:15:44 +00:00
|
|
|
else if (action == VIR_DOMAIN_LIFECYCLE_CRASH_RESTART)
|
2010-03-14 11:11:51 +00:00
|
|
|
num = XEN_ON_CRASH_BEHAVIOUR_RESTART;
|
2010-08-12 17:15:44 +00:00
|
|
|
else if (action == VIR_DOMAIN_LIFECYCLE_CRASH_PRESERVE)
|
2010-03-14 11:11:51 +00:00
|
|
|
num = XEN_ON_CRASH_BEHAVIOUR_PRESERVE;
|
2010-08-12 17:15:44 +00:00
|
|
|
else if (action == VIR_DOMAIN_LIFECYCLE_CRASH_RESTART_RENAME)
|
2010-03-14 11:11:51 +00:00
|
|
|
num = XEN_ON_CRASH_BEHAVIOUR_RENAME_RESTART;
|
2010-08-12 17:15:44 +00:00
|
|
|
else if (action == VIR_DOMAIN_LIFECYCLE_CRASH_COREDUMP_DESTROY)
|
|
|
|
num = XEN_ON_CRASH_BEHAVIOUR_COREDUMP_AND_DESTROY;
|
|
|
|
else if (action == VIR_DOMAIN_LIFECYCLE_CRASH_COREDUMP_RESTART)
|
|
|
|
num = XEN_ON_CRASH_BEHAVIOUR_COREDUMP_AND_RESTART;
|
2010-03-14 11:11:51 +00:00
|
|
|
return num;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* generate XenAPI boot order format from libvirt format */
|
|
|
|
char *
|
|
|
|
createXenAPIBootOrderString(int nboot, int *bootDevs)
|
|
|
|
{
|
|
|
|
virBuffer ret = VIR_BUFFER_INITIALIZER;
|
|
|
|
char *val = NULL;
|
Convert 'int i' to 'size_t i' in src/{xen,xenapi,xenxs} 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;
|
2010-03-14 11:11:51 +00:00
|
|
|
for (i = 0; i < nboot; i++) {
|
|
|
|
if (bootDevs[i] == VIR_DOMAIN_BOOT_FLOPPY)
|
|
|
|
val = (char *)"a";
|
|
|
|
else if (bootDevs[i] == VIR_DOMAIN_BOOT_DISK)
|
|
|
|
val = (char *)"c";
|
|
|
|
else if (bootDevs[i] == VIR_DOMAIN_BOOT_CDROM)
|
|
|
|
val = (char *)"d";
|
|
|
|
else if (bootDevs[i] == VIR_DOMAIN_BOOT_NET)
|
|
|
|
val = (char *)"n";
|
|
|
|
if (val)
|
2013-11-19 22:32:34 +00:00
|
|
|
virBufferEscapeString(&ret, "%s", val);
|
2010-03-14 11:11:51 +00:00
|
|
|
}
|
|
|
|
return virBufferContentAndReset(&ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* convert boot order string to libvirt boot order enum */
|
2014-06-03 07:18:58 +00:00
|
|
|
virDomainBootOrder
|
2014-03-18 08:14:16 +00:00
|
|
|
map2LibvirtBootOrder(char c)
|
|
|
|
{
|
2010-03-14 11:11:51 +00:00
|
|
|
switch (c) {
|
|
|
|
case 'a':
|
|
|
|
return VIR_DOMAIN_BOOT_FLOPPY;
|
|
|
|
case 'c':
|
|
|
|
return VIR_DOMAIN_BOOT_DISK;
|
|
|
|
case 'd':
|
|
|
|
return VIR_DOMAIN_BOOT_CDROM;
|
|
|
|
case 'n':
|
|
|
|
return VIR_DOMAIN_BOOT_NET;
|
|
|
|
default:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-03 07:18:58 +00:00
|
|
|
virDomainLifecycleAction
|
2010-03-14 11:11:51 +00:00
|
|
|
xenapiNormalExitEnum2virDomainLifecycle(enum xen_on_normal_exit action)
|
|
|
|
{
|
2014-06-03 07:18:58 +00:00
|
|
|
virDomainLifecycleAction num = VIR_DOMAIN_LIFECYCLE_RESTART;
|
2010-03-14 11:11:51 +00:00
|
|
|
if (action == XEN_ON_NORMAL_EXIT_DESTROY)
|
|
|
|
num = VIR_DOMAIN_LIFECYCLE_DESTROY;
|
|
|
|
else if (action == XEN_ON_NORMAL_EXIT_RESTART)
|
|
|
|
num = VIR_DOMAIN_LIFECYCLE_RESTART;
|
|
|
|
return num;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-03 07:18:58 +00:00
|
|
|
virDomainLifecycleCrashAction
|
2010-03-14 11:11:51 +00:00
|
|
|
xenapiCrashExitEnum2virDomainLifecycle(enum xen_on_crash_behaviour action)
|
|
|
|
{
|
2014-06-03 07:18:58 +00:00
|
|
|
virDomainLifecycleCrashAction num = VIR_DOMAIN_LIFECYCLE_CRASH_RESTART;
|
2010-03-14 11:11:51 +00:00
|
|
|
if (action == XEN_ON_CRASH_BEHAVIOUR_DESTROY)
|
2010-08-12 17:15:44 +00:00
|
|
|
num = VIR_DOMAIN_LIFECYCLE_CRASH_DESTROY;
|
2010-03-14 11:11:51 +00:00
|
|
|
else if (action == XEN_ON_CRASH_BEHAVIOUR_RESTART)
|
2010-08-12 17:15:44 +00:00
|
|
|
num = VIR_DOMAIN_LIFECYCLE_CRASH_RESTART;
|
2010-03-14 11:11:51 +00:00
|
|
|
else if (action == XEN_ON_CRASH_BEHAVIOUR_PRESERVE)
|
2010-08-12 17:15:44 +00:00
|
|
|
num = VIR_DOMAIN_LIFECYCLE_CRASH_PRESERVE;
|
2010-03-14 11:11:51 +00:00
|
|
|
else if (action == XEN_ON_CRASH_BEHAVIOUR_RENAME_RESTART)
|
2010-08-12 17:15:44 +00:00
|
|
|
num = VIR_DOMAIN_LIFECYCLE_CRASH_RESTART_RENAME;
|
|
|
|
else if (action == XEN_ON_CRASH_BEHAVIOUR_COREDUMP_AND_DESTROY)
|
|
|
|
num = VIR_DOMAIN_LIFECYCLE_CRASH_COREDUMP_DESTROY;
|
|
|
|
else if (action == XEN_ON_CRASH_BEHAVIOUR_COREDUMP_AND_RESTART)
|
|
|
|
num = VIR_DOMAIN_LIFECYCLE_CRASH_COREDUMP_RESTART;
|
2010-03-14 11:11:51 +00:00
|
|
|
return num;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* returns 'file' or 'block' for the storage type */
|
|
|
|
int
|
|
|
|
getStorageVolumeType(char *type)
|
|
|
|
{
|
2013-11-19 22:32:34 +00:00
|
|
|
if (STREQ(type, "lvmoiscsi") ||
|
|
|
|
STREQ(type, "lvmohba") ||
|
|
|
|
STREQ(type, "lvm") ||
|
|
|
|
STREQ(type, "file") ||
|
|
|
|
STREQ(type, "iso") ||
|
|
|
|
STREQ(type, "ext") ||
|
|
|
|
STREQ(type, "nfs"))
|
2010-03-14 11:11:51 +00:00
|
|
|
return (int)VIR_STORAGE_VOL_FILE;
|
2013-11-19 22:32:34 +00:00
|
|
|
else if (STREQ(type, "iscsi") ||
|
|
|
|
STREQ(type, "equal") ||
|
|
|
|
STREQ(type, "hba") ||
|
|
|
|
STREQ(type, "cslg") ||
|
|
|
|
STREQ(type, "udev") ||
|
|
|
|
STREQ(type, "netapp"))
|
2010-03-14 11:11:51 +00:00
|
|
|
return (int)VIR_STORAGE_VOL_BLOCK;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* returns error description if any received from the server */
|
|
|
|
char *
|
|
|
|
returnErrorFromSession(xen_session *session)
|
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/{xen,xenapi,xenxs} 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;
|
2010-03-14 11:11:51 +00:00
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
2011-07-21 13:16:11 +00:00
|
|
|
for (i = 0; i < session->error_description_count; i++) {
|
2010-03-14 11:11:51 +00:00
|
|
|
if (!i)
|
|
|
|
virBufferEscapeString(&buf, "%s", session->error_description[i]);
|
|
|
|
else
|
|
|
|
virBufferEscapeString(&buf, " : %s", session->error_description[i]);
|
|
|
|
}
|
2011-07-21 13:16:11 +00:00
|
|
|
if (virBufferUse(&buf) < 1)
|
|
|
|
virBufferAdd(&buf, _("unknown error"), -1);
|
2010-03-14 11:11:51 +00:00
|
|
|
return virBufferContentAndReset(&buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* converts bitmap to string of the form '1,2...' */
|
|
|
|
char *
|
|
|
|
mapDomainPinVcpu(unsigned char *cpumap, int maplen)
|
|
|
|
{
|
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
|
size_t len;
|
|
|
|
char *ret = NULL;
|
Convert 'int i' to 'size_t i' in src/{xen,xenapi,xenxs} 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, j;
|
2010-03-14 11:11:51 +00:00
|
|
|
for (i = 0; i < maplen; i++) {
|
|
|
|
for (j = 0; j < 8; j++) {
|
2014-11-13 14:29:45 +00:00
|
|
|
if (cpumap[i] & (1 << j))
|
Convert 'int i' to 'size_t i' in src/{xen,xenapi,xenxs} 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
|
|
|
virBufferAsprintf(&buf, "%zu,", (8*i)+j);
|
2010-03-14 11:11:51 +00:00
|
|
|
}
|
|
|
|
}
|
2014-06-27 08:40:15 +00:00
|
|
|
if (virBufferCheckError(&buf) < 0)
|
2010-03-14 11:11:51 +00:00
|
|
|
return NULL;
|
|
|
|
ret = virBufferContentAndReset(&buf);
|
|
|
|
len = strlen(ret);
|
|
|
|
if (len > 0 && ret[len - 1] == ',')
|
|
|
|
ret[len - 1] = 0;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* obtains the CPU bitmap from the string passed */
|
|
|
|
void
|
|
|
|
getCpuBitMapfromString(char *mask, unsigned char *cpumap, int maplen)
|
|
|
|
{
|
|
|
|
int pos;
|
|
|
|
int max_bits = maplen * 8;
|
|
|
|
char *num = NULL, *bp = NULL;
|
|
|
|
bzero(cpumap, maplen);
|
|
|
|
num = strtok_r(mask, ",", &bp);
|
|
|
|
while (num != NULL) {
|
2010-03-30 14:51:04 +00:00
|
|
|
if (virStrToLong_i(num, NULL, 10, &pos) < 0)
|
2010-03-14 11:11:51 +00:00
|
|
|
return;
|
|
|
|
if (pos < 0 || pos > max_bits - 1)
|
2012-10-17 09:23:12 +00:00
|
|
|
VIR_WARN("number in str %d exceeds cpumap's max bits %d", pos, max_bits);
|
2010-03-14 11:11:51 +00:00
|
|
|
else
|
|
|
|
(cpumap)[pos / 8] |= (1 << (pos % 8));
|
|
|
|
num = strtok_r(NULL, ",", &bp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* mapping XenServer power state to Libvirt power state */
|
|
|
|
virDomainState
|
|
|
|
mapPowerState(enum xen_vm_power_state state)
|
|
|
|
{
|
|
|
|
virDomainState virState;
|
|
|
|
switch (state) {
|
|
|
|
case XEN_VM_POWER_STATE_HALTED:
|
|
|
|
case XEN_VM_POWER_STATE_SUSPENDED:
|
|
|
|
virState = VIR_DOMAIN_SHUTOFF;
|
|
|
|
break;
|
|
|
|
case XEN_VM_POWER_STATE_PAUSED:
|
|
|
|
virState = VIR_DOMAIN_PAUSED;
|
|
|
|
break;
|
|
|
|
case XEN_VM_POWER_STATE_RUNNING:
|
|
|
|
virState = VIR_DOMAIN_RUNNING;
|
|
|
|
break;
|
|
|
|
case XEN_VM_POWER_STATE_UNDEFINED:
|
|
|
|
default:
|
2010-08-20 23:35:54 +00:00
|
|
|
/* Includes XEN_VM_POWER_STATE_UNKNOWN from libxenserver
|
|
|
|
* 5.5.0, which is gone in 5.6.0. */
|
2010-03-14 11:11:51 +00:00
|
|
|
virState = VIR_DOMAIN_NOSTATE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return virState;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* allocate a flexible array and fill values(key,val) */
|
|
|
|
int
|
2012-10-17 09:23:12 +00:00
|
|
|
allocStringMap(xen_string_string_map **strings, char *key, char *val)
|
2010-03-14 11:11:51 +00:00
|
|
|
{
|
|
|
|
int sz = ((*strings) == NULL) ? 0 : (*strings)->size;
|
|
|
|
sz++;
|
|
|
|
if (VIR_REALLOC_N(*strings, sizeof(xen_string_string_map) +
|
2013-07-04 10:19:05 +00:00
|
|
|
sizeof(xen_string_string_map_contents) * sz) < 0)
|
2010-03-14 11:11:51 +00:00
|
|
|
return -1;
|
|
|
|
(*strings)->size = sz;
|
2013-05-03 12:51:37 +00:00
|
|
|
if (VIR_STRDUP((*strings)->contents[sz-1].key, key) < 0 ||
|
|
|
|
VIR_STRDUP((*strings)->contents[sz-1].val, val) < 0)
|
|
|
|
goto error;
|
2010-03-14 11:11:51 +00:00
|
|
|
return 0;
|
2014-03-25 06:57:22 +00:00
|
|
|
error:
|
2010-03-14 11:11:51 +00:00
|
|
|
xen_string_string_map_free(*strings);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Error handling function returns error messages from the server if any */
|
|
|
|
void
|
|
|
|
xenapiSessionErrorHandle(virConnectPtr conn, virErrorNumber errNum,
|
|
|
|
const char *buf, const char *filename, const char *func,
|
|
|
|
size_t lineno)
|
|
|
|
{
|
2010-03-14 20:53:01 +00:00
|
|
|
struct _xenapiPrivate *priv = conn->privateData;
|
2010-03-14 11:11:51 +00:00
|
|
|
|
2010-03-14 20:53:01 +00:00
|
|
|
if (buf == NULL && priv != NULL && priv->session != NULL) {
|
|
|
|
char *ret = returnErrorFromSession(priv->session);
|
2012-07-10 21:43:08 +00:00
|
|
|
virReportErrorHelper(VIR_FROM_XENAPI, errNum, filename, func, lineno,
|
|
|
|
"%s", ret);
|
2010-03-14 20:53:01 +00:00
|
|
|
xen_session_clear_error(priv->session);
|
2010-03-14 11:11:51 +00:00
|
|
|
VIR_FREE(ret);
|
|
|
|
} else {
|
2012-07-10 21:43:08 +00:00
|
|
|
virReportErrorHelper(VIR_FROM_XENAPI, errNum, filename, func, lineno,
|
|
|
|
"%s", buf);
|
2010-03-14 11:11:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* creates network intereface for VM */
|
2010-08-18 22:57:00 +00:00
|
|
|
static int
|
2012-10-17 09:23:12 +00:00
|
|
|
createVifNetwork(virConnectPtr conn, xen_vm vm, int device,
|
|
|
|
char *bridge, char *mac)
|
2010-03-14 11:11:51 +00:00
|
|
|
{
|
|
|
|
xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
|
|
|
|
xen_vm xvm = NULL;
|
|
|
|
char *uuid = NULL;
|
|
|
|
xen_vm_get_uuid(session, &uuid, vm);
|
|
|
|
if (uuid) {
|
|
|
|
if (!xen_vm_get_by_uuid(session, &xvm, uuid))
|
|
|
|
return -1;
|
|
|
|
VIR_FREE(uuid);
|
|
|
|
}
|
|
|
|
xen_vm_record_opt *vm_opt = xen_vm_record_opt_alloc();
|
|
|
|
vm_opt->is_record = 0;
|
|
|
|
vm_opt->u.handle = xvm;
|
|
|
|
xen_network_set *net_set = NULL;
|
|
|
|
xen_network_record *net_rec = NULL;
|
2010-04-02 22:37:51 +00:00
|
|
|
int cnt = 0;
|
2015-03-10 23:10:34 +00:00
|
|
|
if (!xen_network_get_all(session, &net_set)) {
|
|
|
|
xen_vm_record_opt_free(vm_opt);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
for (cnt = 0; cnt < net_set->size; cnt++) {
|
|
|
|
if (xen_network_get_record(session, &net_rec, net_set->contents[cnt])) {
|
|
|
|
if (STREQ(net_rec->bridge, bridge)) {
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
xen_network_record_free(net_rec);
|
2010-03-14 11:11:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cnt < net_set->size && net_rec) {
|
|
|
|
xen_network network = NULL;
|
|
|
|
xen_network_get_by_uuid(session, &network, net_rec->uuid);
|
|
|
|
xen_network_record_opt *network_opt = xen_network_record_opt_alloc();
|
|
|
|
network_opt->is_record = 0;
|
|
|
|
network_opt->u.handle = network;
|
|
|
|
xen_vif_record *vif_record = xen_vif_record_alloc();
|
|
|
|
vif_record->mac = mac;
|
|
|
|
vif_record->vm = vm_opt;
|
|
|
|
vif_record->network = network_opt;
|
|
|
|
xen_vif vif = NULL;
|
|
|
|
|
|
|
|
vif_record->other_config = xen_string_string_map_alloc(0);
|
|
|
|
vif_record->runtime_properties = xen_string_string_map_alloc(0);
|
|
|
|
vif_record->qos_algorithm_params = xen_string_string_map_alloc(0);
|
2015-03-10 23:10:34 +00:00
|
|
|
if (virAsprintfQuiet(&vif_record->device, "%d", device) < 0) {
|
|
|
|
xen_vif_record_free(vif_record);
|
|
|
|
xen_network_record_free(net_rec);
|
|
|
|
xen_network_set_free(net_set);
|
2010-08-18 22:57:00 +00:00
|
|
|
return -1;
|
2015-03-10 23:10:34 +00:00
|
|
|
}
|
2010-03-14 11:11:51 +00:00
|
|
|
xen_vif_create(session, &vif, vif_record);
|
|
|
|
if (!vif) {
|
|
|
|
xen_vif_free(vif);
|
|
|
|
xen_vif_record_free(vif_record);
|
|
|
|
xen_network_record_free(net_rec);
|
|
|
|
xen_network_set_free(net_set);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
xen_vif_record_free(vif_record);
|
|
|
|
xen_network_record_free(net_rec);
|
|
|
|
}
|
2015-03-10 23:10:34 +00:00
|
|
|
xen_network_set_free(net_set);
|
2010-03-14 11:11:51 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create a VM record from the XML description */
|
|
|
|
int
|
2012-10-17 09:23:12 +00:00
|
|
|
createVMRecordFromXml(virConnectPtr conn, virDomainDefPtr def,
|
|
|
|
xen_vm_record **record, xen_vm *vm)
|
2010-03-14 11:11:51 +00:00
|
|
|
{
|
|
|
|
char uuidStr[VIR_UUID_STRING_BUFLEN];
|
build: detect potentential uninitialized variables
Even with -Wuninitialized (which is part of autobuild.sh
--enable-compile-warnings=error), gcc does NOT catch this
use of an uninitialized variable:
{
if (cond)
goto error;
int a = 1;
error:
printf("%d", a);
}
which prints 0 (supposing the stack started life wiped) if
cond was true. Clang will catch it, but we don't use clang
as often. Using gcc -Wjump-misses-init catches it, but also
gives false positives:
{
if (cond)
goto error;
int a = 1;
return a;
error:
return 0;
}
Here, a was never used in the scope of the error block, so
declaring it after goto is technically fine (and clang agrees).
However, given that our HACKING already documents a preference
to C89 decl-before-statement, the false positive warning is
enough of a prod to comply with HACKING.
[Personally, I'd _really_ rather use C99 decl-after-statement
to minimize scope, but until gcc can efficiently and reliably
catch scoping and uninitialized usage bugs, I'll settle with
the compromise of enforcing a coding standard that happens to
reject false positives if it can also detect real bugs.]
* acinclude.m4 (LIBVIRT_COMPILE_WARNINGS): Add -Wjump-misses-init.
* src/util/util.c (__virExec): Adjust offenders.
* src/conf/domain_conf.c (virDomainTimerDefParseXML): Likewise.
* src/remote/remote_driver.c (doRemoteOpen): Likewise.
* src/phyp/phyp_driver.c (phypGetLparNAME, phypGetLparProfile)
(phypGetVIOSFreeSCSIAdapter, phypVolumeGetKey)
(phypGetStoragePoolDevice)
(phypVolumeGetPhysicalVolumeByStoragePool)
(phypVolumeGetPath): Likewise.
* src/vbox/vbox_tmpl.c (vboxNetworkUndefineDestroy)
(vboxNetworkCreate, vboxNetworkDumpXML)
(vboxNetworkDefineCreateXML): Likewise.
* src/xenapi/xenapi_driver.c (getCapsObject)
(xenapiDomainDumpXML): Likewise.
* src/xenapi/xenapi_utils.c (createVMRecordFromXml): Likewise.
* src/security/security_selinux.c (SELinuxGenNewContext):
Likewise.
* src/qemu/qemu_command.c (qemuBuildCommandLine): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainChangeEjectableMedia):
Likewise.
* src/qemu/qemu_process.c (qemuProcessWaitForMonitor): Likewise.
* src/qemu/qemu_monitor_text.c (qemuMonitorTextGetPtyPaths):
Likewise.
* src/qemu/qemu_driver.c (qemudDomainShutdown)
(qemudDomainBlockStats, qemudDomainMemoryPeek): Likewise.
* src/storage/storage_backend_iscsi.c
(virStorageBackendCreateIfaceIQN): Likewise.
* src/node_device/node_device_udev.c (udevProcessPCI): Likewise.
2011-04-01 15:41:45 +00:00
|
|
|
xen_string_string_map *strings = NULL;
|
|
|
|
int device_number = 0;
|
Convert 'int i' to 'size_t i' in src/{xen,xenapi,xenxs} 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;
|
build: detect potentential uninitialized variables
Even with -Wuninitialized (which is part of autobuild.sh
--enable-compile-warnings=error), gcc does NOT catch this
use of an uninitialized variable:
{
if (cond)
goto error;
int a = 1;
error:
printf("%d", a);
}
which prints 0 (supposing the stack started life wiped) if
cond was true. Clang will catch it, but we don't use clang
as often. Using gcc -Wjump-misses-init catches it, but also
gives false positives:
{
if (cond)
goto error;
int a = 1;
return a;
error:
return 0;
}
Here, a was never used in the scope of the error block, so
declaring it after goto is technically fine (and clang agrees).
However, given that our HACKING already documents a preference
to C89 decl-before-statement, the false positive warning is
enough of a prod to comply with HACKING.
[Personally, I'd _really_ rather use C99 decl-after-statement
to minimize scope, but until gcc can efficiently and reliably
catch scoping and uninitialized usage bugs, I'll settle with
the compromise of enforcing a coding standard that happens to
reject false positives if it can also detect real bugs.]
* acinclude.m4 (LIBVIRT_COMPILE_WARNINGS): Add -Wjump-misses-init.
* src/util/util.c (__virExec): Adjust offenders.
* src/conf/domain_conf.c (virDomainTimerDefParseXML): Likewise.
* src/remote/remote_driver.c (doRemoteOpen): Likewise.
* src/phyp/phyp_driver.c (phypGetLparNAME, phypGetLparProfile)
(phypGetVIOSFreeSCSIAdapter, phypVolumeGetKey)
(phypGetStoragePoolDevice)
(phypVolumeGetPhysicalVolumeByStoragePool)
(phypVolumeGetPath): Likewise.
* src/vbox/vbox_tmpl.c (vboxNetworkUndefineDestroy)
(vboxNetworkCreate, vboxNetworkDumpXML)
(vboxNetworkDefineCreateXML): Likewise.
* src/xenapi/xenapi_driver.c (getCapsObject)
(xenapiDomainDumpXML): Likewise.
* src/xenapi/xenapi_utils.c (createVMRecordFromXml): Likewise.
* src/security/security_selinux.c (SELinuxGenNewContext):
Likewise.
* src/qemu/qemu_command.c (qemuBuildCommandLine): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainChangeEjectableMedia):
Likewise.
* src/qemu/qemu_process.c (qemuProcessWaitForMonitor): Likewise.
* src/qemu/qemu_monitor_text.c (qemuMonitorTextGetPtyPaths):
Likewise.
* src/qemu/qemu_driver.c (qemudDomainShutdown)
(qemudDomainBlockStats, qemudDomainMemoryPeek): Likewise.
* src/storage/storage_backend_iscsi.c
(virStorageBackendCreateIfaceIQN): Likewise.
* src/node_device/node_device_udev.c (udevProcessPCI): Likewise.
2011-04-01 15:41:45 +00:00
|
|
|
|
2010-03-14 11:11:51 +00:00
|
|
|
*record = xen_vm_record_alloc();
|
2013-05-03 12:51:37 +00:00
|
|
|
if (VIR_STRDUP((*record)->name_label, def->name) < 0)
|
|
|
|
goto error;
|
2015-03-10 22:41:18 +00:00
|
|
|
virUUIDFormat(def->uuid, uuidStr);
|
|
|
|
if (VIR_STRDUP((*record)->uuid, uuidStr) < 0)
|
|
|
|
goto error;
|
2015-04-17 00:11:06 +00:00
|
|
|
if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
|
2010-03-14 11:11:51 +00:00
|
|
|
char *boot_order = NULL;
|
2013-05-03 12:51:37 +00:00
|
|
|
if (VIR_STRDUP((*record)->hvm_boot_policy, "BIOS order") < 0)
|
|
|
|
goto error;
|
2010-03-14 11:11:51 +00:00
|
|
|
if (def->os.nBootDevs != 0)
|
|
|
|
boot_order = createXenAPIBootOrderString(def->os.nBootDevs, &def->os.bootDevs[0]);
|
|
|
|
if (boot_order != NULL) {
|
|
|
|
xen_string_string_map *hvm_boot_params = NULL;
|
|
|
|
allocStringMap(&hvm_boot_params, (char *)"order", boot_order);
|
|
|
|
(*record)->hvm_boot_params = hvm_boot_params;
|
|
|
|
VIR_FREE(boot_order);
|
|
|
|
}
|
2015-04-17 00:11:06 +00:00
|
|
|
} else if (def->os.type == VIR_DOMAIN_OSTYPE_XEN) {
|
2013-05-03 12:51:37 +00:00
|
|
|
if (VIR_STRDUP((*record)->pv_bootloader, "pygrub") < 0)
|
|
|
|
goto error;
|
2010-03-14 11:11:51 +00:00
|
|
|
if (def->os.kernel) {
|
2013-05-03 12:51:37 +00:00
|
|
|
if (VIR_STRDUP((*record)->pv_kernel, def->os.kernel) < 0)
|
|
|
|
goto error;
|
2010-03-14 11:11:51 +00:00
|
|
|
}
|
|
|
|
if (def->os.initrd) {
|
2013-05-03 12:51:37 +00:00
|
|
|
if (VIR_STRDUP((*record)->pv_ramdisk, def->os.initrd) < 0)
|
|
|
|
goto error;
|
2010-03-14 11:11:51 +00:00
|
|
|
}
|
|
|
|
if (def->os.cmdline) {
|
2013-05-03 12:51:37 +00:00
|
|
|
if (VIR_STRDUP((*record)->pv_args, def->os.cmdline) < 0)
|
|
|
|
goto error;
|
2010-03-14 11:11:51 +00:00
|
|
|
}
|
|
|
|
(*record)->hvm_boot_params = xen_string_string_map_alloc(0);
|
|
|
|
}
|
|
|
|
if (def->os.bootloaderArgs)
|
2013-05-03 12:51:37 +00:00
|
|
|
if (VIR_STRDUP((*record)->pv_bootloader_args, def->os.bootloaderArgs) < 0)
|
|
|
|
goto error;
|
2010-03-14 11:11:51 +00:00
|
|
|
|
2010-10-12 14:43:39 +00:00
|
|
|
if (def->mem.cur_balloon)
|
|
|
|
(*record)->memory_static_max = (int64_t) (def->mem.cur_balloon * 1024);
|
2016-06-15 13:34:04 +00:00
|
|
|
if (virDomainDefGetMemoryTotal(def))
|
|
|
|
(*record)->memory_dynamic_max = (int64_t) (virDomainDefGetMemoryTotal(def) * 1024);
|
2010-03-14 11:11:51 +00:00
|
|
|
else
|
|
|
|
(*record)->memory_dynamic_max = (*record)->memory_static_max;
|
|
|
|
|
2015-10-19 17:21:24 +00:00
|
|
|
if (virDomainDefGetVcpusMax(def) > 0) {
|
|
|
|
(*record)->vcpus_max = (int64_t) virDomainDefGetVcpusMax(def);
|
2015-10-22 12:59:03 +00:00
|
|
|
(*record)->vcpus_at_startup = (int64_t) virDomainDefGetVcpus(def);
|
2010-03-14 11:11:51 +00:00
|
|
|
}
|
|
|
|
if (def->onPoweroff)
|
|
|
|
(*record)->actions_after_shutdown = actionShutdownLibvirt2XenapiEnum(def->onPoweroff);
|
|
|
|
if (def->onReboot)
|
|
|
|
(*record)->actions_after_reboot = actionShutdownLibvirt2XenapiEnum(def->onReboot);
|
|
|
|
if (def->onCrash)
|
|
|
|
(*record)->actions_after_crash = actionCrashLibvirt2XenapiEnum(def->onCrash);
|
|
|
|
|
2014-06-27 15:18:53 +00:00
|
|
|
if (def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_TRISTATE_SWITCH_ON)
|
2013-09-23 13:02:38 +00:00
|
|
|
allocStringMap(&strings, (char *)"acpi", (char *)"true");
|
2014-06-27 15:18:53 +00:00
|
|
|
if (def->features[VIR_DOMAIN_FEATURE_APIC] == VIR_TRISTATE_SWITCH_ON)
|
2013-09-23 13:02:38 +00:00
|
|
|
allocStringMap(&strings, (char *)"apic", (char *)"true");
|
2014-06-27 15:18:53 +00:00
|
|
|
if (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_TRISTATE_SWITCH_ON)
|
2013-09-23 13:02:38 +00:00
|
|
|
allocStringMap(&strings, (char *)"pae", (char *)"true");
|
2014-06-27 15:18:53 +00:00
|
|
|
if (def->features[VIR_DOMAIN_FEATURE_HAP] == VIR_TRISTATE_SWITCH_ON)
|
2013-09-23 13:02:38 +00:00
|
|
|
allocStringMap(&strings, (char *)"hap", (char *)"true");
|
2014-06-27 15:18:53 +00:00
|
|
|
if (def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] == VIR_TRISTATE_SWITCH_ON)
|
2013-09-23 13:02:38 +00:00
|
|
|
allocStringMap(&strings, (char *)"viridian", (char *)"true");
|
2010-03-14 11:11:51 +00:00
|
|
|
if (strings != NULL)
|
|
|
|
(*record)->platform = strings;
|
|
|
|
|
|
|
|
(*record)->vcpus_params = xen_string_string_map_alloc(0);
|
|
|
|
(*record)->other_config = xen_string_string_map_alloc(0);
|
|
|
|
(*record)->last_boot_cpu_flags = xen_string_string_map_alloc(0);
|
|
|
|
(*record)->xenstore_data = xen_string_string_map_alloc(0);
|
|
|
|
(*record)->hvm_shadow_multiplier = 1.000;
|
|
|
|
if (!xen_vm_create(((struct _xenapiPrivate *)(conn->privateData))->session,
|
|
|
|
vm, *record)) {
|
|
|
|
xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < def->nnets; i++) {
|
2012-07-17 15:18:36 +00:00
|
|
|
if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE &&
|
|
|
|
def->nets[i]->data.bridge.brname) {
|
|
|
|
char *mac;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(mac, VIR_MAC_STRING_BUFLEN) < 0)
|
2013-07-04 10:19:05 +00:00
|
|
|
goto error;
|
2012-07-17 15:18:36 +00:00
|
|
|
virMacAddrFormat(&def->nets[i]->mac, mac);
|
|
|
|
|
|
|
|
if (createVifNetwork(conn, *vm, device_number,
|
|
|
|
def->nets[i]->data.bridge.brname,
|
|
|
|
mac) < 0) {
|
|
|
|
VIR_FREE(mac);
|
2013-07-04 10:19:05 +00:00
|
|
|
virReportOOMError();
|
|
|
|
goto error;
|
2010-03-14 11:11:51 +00:00
|
|
|
}
|
2012-07-17 15:18:36 +00:00
|
|
|
device_number++;
|
2010-03-14 11:11:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
error:
|
2010-03-14 11:11:51 +00:00
|
|
|
xen_vm_record_free(*record);
|
|
|
|
return -1;
|
|
|
|
}
|