2009-07-23 20:21:08 +00:00
|
|
|
|
|
|
|
/*
|
2010-03-02 21:19:24 +00:00
|
|
|
* esx_util.c: utility functions for the VMware ESX driver
|
2009-07-23 20:21:08 +00:00
|
|
|
*
|
2010-03-01 23:38:28 +00:00
|
|
|
* Copyright (C) 2010 Red Hat, Inc.
|
2011-05-04 07:07:41 +00:00
|
|
|
* Copyright (C) 2009-2011 Matthias Bolte <matthias.bolte@googlemail.com>
|
2009-07-23 20:21:08 +00:00
|
|
|
* Copyright (C) 2009 Maximilian Wilhelm <max@rfc2324.org>
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <netdb.h>
|
|
|
|
|
|
|
|
#include "internal.h"
|
|
|
|
#include "datatypes.h"
|
|
|
|
#include "qparams.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "logging.h"
|
|
|
|
#include "uuid.h"
|
2010-12-21 21:39:55 +00:00
|
|
|
#include "vmx.h"
|
2010-04-02 19:34:31 +00:00
|
|
|
#include "esx_private.h"
|
2009-07-23 20:21:08 +00:00
|
|
|
#include "esx_util.h"
|
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_ESX
|
|
|
|
|
2009-09-02 14:32:30 +00:00
|
|
|
|
2010-06-03 18:04:15 +00:00
|
|
|
|
2009-07-23 20:21:08 +00:00
|
|
|
int
|
2010-07-30 20:08:35 +00:00
|
|
|
esxUtil_ParseUri(esxUtil_ParsedUri **parsedUri, xmlURIPtr uri)
|
2009-07-23 20:21:08 +00:00
|
|
|
{
|
2010-05-19 20:59:32 +00:00
|
|
|
int result = -1;
|
2009-07-23 20:21:08 +00:00
|
|
|
struct qparam_set *queryParamSet = NULL;
|
|
|
|
struct qparam *queryParam = NULL;
|
2010-06-03 18:04:15 +00:00
|
|
|
int i;
|
|
|
|
int noVerify;
|
|
|
|
int autoAnswer;
|
2010-06-03 21:09:12 +00:00
|
|
|
char *tmp;
|
2010-07-30 20:08:35 +00:00
|
|
|
char *saveptr;
|
2009-07-23 20:21:08 +00:00
|
|
|
|
2010-07-30 20:08:35 +00:00
|
|
|
if (parsedUri == NULL || *parsedUri != NULL) {
|
2010-06-03 18:04:15 +00:00
|
|
|
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
|
|
|
|
return -1;
|
2009-11-15 21:22:47 +00:00
|
|
|
}
|
|
|
|
|
2010-07-30 20:08:35 +00:00
|
|
|
if (VIR_ALLOC(*parsedUri) < 0) {
|
2010-06-03 18:04:15 +00:00
|
|
|
virReportOOMError();
|
|
|
|
return -1;
|
2009-11-15 21:22:47 +00:00
|
|
|
}
|
|
|
|
|
2009-07-23 20:21:08 +00:00
|
|
|
#ifdef HAVE_XMLURI_QUERY_RAW
|
2010-01-15 22:05:26 +00:00
|
|
|
queryParamSet = qparam_query_parse(uri->query_raw);
|
2009-07-23 20:21:08 +00:00
|
|
|
#else
|
2010-01-15 22:05:26 +00:00
|
|
|
queryParamSet = qparam_query_parse(uri->query);
|
2009-07-23 20:21:08 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (queryParamSet == NULL) {
|
2010-06-03 18:04:15 +00:00
|
|
|
goto cleanup;
|
2009-07-23 20:21:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < queryParamSet->n; i++) {
|
|
|
|
queryParam = &queryParamSet->p[i];
|
|
|
|
|
2009-09-02 14:32:30 +00:00
|
|
|
if (STRCASEEQ(queryParam->name, "transport")) {
|
2010-07-30 20:08:35 +00:00
|
|
|
VIR_FREE((*parsedUri)->transport);
|
2009-09-02 14:32:30 +00:00
|
|
|
|
2010-07-30 20:08:35 +00:00
|
|
|
(*parsedUri)->transport = strdup(queryParam->value);
|
2009-07-23 20:21:08 +00:00
|
|
|
|
2010-07-30 20:08:35 +00:00
|
|
|
if ((*parsedUri)->transport == NULL) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2010-05-19 20:59:32 +00:00
|
|
|
goto cleanup;
|
2009-07-23 20:21:08 +00:00
|
|
|
}
|
|
|
|
|
2010-07-30 20:08:35 +00:00
|
|
|
if (STRNEQ((*parsedUri)->transport, "http") &&
|
|
|
|
STRNEQ((*parsedUri)->transport, "https")) {
|
2010-01-15 22:05:26 +00:00
|
|
|
ESX_ERROR(VIR_ERR_INVALID_ARG,
|
2010-04-02 19:34:31 +00:00
|
|
|
_("Query parameter 'transport' has unexpected value "
|
2010-06-03 18:04:15 +00:00
|
|
|
"'%s' (should be http|https)"),
|
2010-07-30 20:08:35 +00:00
|
|
|
(*parsedUri)->transport);
|
2010-05-19 20:59:32 +00:00
|
|
|
goto cleanup;
|
2009-07-23 20:21:08 +00:00
|
|
|
}
|
2009-09-02 14:32:30 +00:00
|
|
|
} else if (STRCASEEQ(queryParam->name, "vcenter")) {
|
2010-07-30 20:08:35 +00:00
|
|
|
VIR_FREE((*parsedUri)->vCenter);
|
2009-09-02 14:32:30 +00:00
|
|
|
|
2010-07-30 20:08:35 +00:00
|
|
|
(*parsedUri)->vCenter = strdup(queryParam->value);
|
2009-07-23 20:21:08 +00:00
|
|
|
|
2010-07-30 20:08:35 +00:00
|
|
|
if ((*parsedUri)->vCenter == NULL) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2010-05-19 20:59:32 +00:00
|
|
|
goto cleanup;
|
2009-07-23 20:21:08 +00:00
|
|
|
}
|
2009-09-02 14:32:30 +00:00
|
|
|
} else if (STRCASEEQ(queryParam->name, "no_verify")) {
|
2010-06-03 18:04:15 +00:00
|
|
|
if (virStrToLong_i(queryParam->value, NULL, 10, &noVerify) < 0 ||
|
|
|
|
(noVerify != 0 && noVerify != 1)) {
|
2010-01-15 22:05:26 +00:00
|
|
|
ESX_ERROR(VIR_ERR_INVALID_ARG,
|
2010-04-02 19:34:31 +00:00
|
|
|
_("Query parameter 'no_verify' has unexpected value "
|
|
|
|
"'%s' (should be 0 or 1)"), queryParam->value);
|
2010-05-19 20:59:32 +00:00
|
|
|
goto cleanup;
|
2009-07-27 12:18:25 +00:00
|
|
|
}
|
2009-11-15 21:22:47 +00:00
|
|
|
|
2010-07-30 20:08:35 +00:00
|
|
|
(*parsedUri)->noVerify = noVerify != 0;
|
2010-06-03 18:04:15 +00:00
|
|
|
} else if (STRCASEEQ(queryParam->name, "auto_answer")) {
|
|
|
|
if (virStrToLong_i(queryParam->value, NULL, 10, &autoAnswer) < 0 ||
|
|
|
|
(autoAnswer != 0 && autoAnswer != 1)) {
|
2010-01-15 22:05:26 +00:00
|
|
|
ESX_ERROR(VIR_ERR_INVALID_ARG,
|
2010-04-02 19:34:31 +00:00
|
|
|
_("Query parameter 'auto_answer' has unexpected "
|
|
|
|
"value '%s' (should be 0 or 1)"), queryParam->value);
|
2010-05-19 20:59:32 +00:00
|
|
|
goto cleanup;
|
2009-11-15 21:22:47 +00:00
|
|
|
}
|
2010-06-03 18:04:15 +00:00
|
|
|
|
2010-07-30 20:08:35 +00:00
|
|
|
(*parsedUri)->autoAnswer = autoAnswer != 0;
|
2010-06-03 21:09:12 +00:00
|
|
|
} else if (STRCASEEQ(queryParam->name, "proxy")) {
|
|
|
|
/* Expected format: [<type>://]<hostname>[:<port>] */
|
2010-07-30 20:08:35 +00:00
|
|
|
(*parsedUri)->proxy = true;
|
|
|
|
(*parsedUri)->proxy_type = CURLPROXY_HTTP;
|
|
|
|
VIR_FREE((*parsedUri)->proxy_hostname);
|
|
|
|
(*parsedUri)->proxy_port = 1080;
|
2010-06-03 21:09:12 +00:00
|
|
|
|
|
|
|
if ((tmp = STRSKIP(queryParam->value, "http://")) != NULL) {
|
2010-07-30 20:08:35 +00:00
|
|
|
(*parsedUri)->proxy_type = CURLPROXY_HTTP;
|
2010-06-03 21:09:12 +00:00
|
|
|
} else if ((tmp = STRSKIP(queryParam->value, "socks://")) != NULL ||
|
|
|
|
(tmp = STRSKIP(queryParam->value, "socks5://")) != NULL) {
|
2010-07-30 20:08:35 +00:00
|
|
|
(*parsedUri)->proxy_type = CURLPROXY_SOCKS5;
|
2010-06-03 21:09:12 +00:00
|
|
|
} else if ((tmp = STRSKIP(queryParam->value, "socks4://")) != NULL) {
|
2010-07-30 20:08:35 +00:00
|
|
|
(*parsedUri)->proxy_type = CURLPROXY_SOCKS4;
|
2010-06-03 21:09:12 +00:00
|
|
|
} else if ((tmp = STRSKIP(queryParam->value, "socks4a://")) != NULL) {
|
2010-07-30 20:08:35 +00:00
|
|
|
(*parsedUri)->proxy_type = CURLPROXY_SOCKS4A;
|
2010-06-03 21:09:12 +00:00
|
|
|
} else if ((tmp = strstr(queryParam->value, "://")) != NULL) {
|
|
|
|
*tmp = '\0';
|
|
|
|
|
|
|
|
ESX_ERROR(VIR_ERR_INVALID_ARG,
|
|
|
|
_("Query parameter 'proxy' contains unexpected "
|
|
|
|
"type '%s' (should be (http|socks(|4|4a|5))"),
|
|
|
|
queryParam->value);
|
|
|
|
goto cleanup;
|
|
|
|
} else {
|
|
|
|
tmp = queryParam->value;
|
|
|
|
}
|
|
|
|
|
2010-07-30 20:08:35 +00:00
|
|
|
(*parsedUri)->proxy_hostname = strdup(tmp);
|
2010-06-03 21:09:12 +00:00
|
|
|
|
2010-07-30 20:08:35 +00:00
|
|
|
if ((*parsedUri)->proxy_hostname == NULL) {
|
2010-06-03 21:09:12 +00:00
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2010-07-30 20:08:35 +00:00
|
|
|
if ((tmp = strchr((*parsedUri)->proxy_hostname, ':')) != NULL) {
|
|
|
|
if (tmp == (*parsedUri)->proxy_hostname) {
|
2010-06-03 21:09:12 +00:00
|
|
|
ESX_ERROR(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("Query parameter 'proxy' doesn't contain a "
|
|
|
|
"hostname"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
*tmp++ = '\0';
|
|
|
|
|
|
|
|
if (virStrToLong_i(tmp, NULL, 10,
|
2010-07-30 20:08:35 +00:00
|
|
|
&(*parsedUri)->proxy_port) < 0 ||
|
|
|
|
(*parsedUri)->proxy_port < 1 ||
|
|
|
|
(*parsedUri)->proxy_port > 65535) {
|
2010-06-03 21:09:12 +00:00
|
|
|
ESX_ERROR(VIR_ERR_INVALID_ARG,
|
|
|
|
_("Query parameter 'proxy' has unexpected port"
|
|
|
|
"value '%s' (should be [1..65535])"), tmp);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
2009-07-23 20:21:08 +00:00
|
|
|
} else {
|
|
|
|
VIR_WARN("Ignoring unexpected query parameter '%s'",
|
|
|
|
queryParam->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-30 20:08:35 +00:00
|
|
|
/* Expected format: [/]<datacenter>/<computeresource>[/<hostsystem>] */
|
|
|
|
if (uri->path != NULL) {
|
|
|
|
tmp = strdup(uri->path);
|
2009-07-23 20:21:08 +00:00
|
|
|
|
2010-07-30 20:08:35 +00:00
|
|
|
if (tmp == NULL) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (esxVI_String_DeepCopyValue(&(*parsedUri)->path_datacenter,
|
|
|
|
strtok_r(tmp, "/", &saveptr)) < 0 ||
|
|
|
|
esxVI_String_DeepCopyValue(&(*parsedUri)->path_computeResource,
|
|
|
|
strtok_r(NULL, "/", &saveptr)) < 0 ||
|
|
|
|
esxVI_String_DeepCopyValue(&(*parsedUri)->path_hostSystem,
|
|
|
|
strtok_r(NULL, "", &saveptr)) < 0) {
|
|
|
|
VIR_FREE(tmp);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((*parsedUri)->transport == NULL) {
|
|
|
|
(*parsedUri)->transport = strdup("https");
|
|
|
|
|
|
|
|
if ((*parsedUri)->transport == NULL) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2010-05-19 20:59:32 +00:00
|
|
|
goto cleanup;
|
2009-07-23 20:21:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-19 20:59:32 +00:00
|
|
|
result = 0;
|
2009-07-23 20:21:08 +00:00
|
|
|
|
2010-05-19 20:59:32 +00:00
|
|
|
cleanup:
|
|
|
|
if (result < 0) {
|
2010-07-30 20:08:35 +00:00
|
|
|
esxUtil_FreeParsedUri(parsedUri);
|
2009-07-23 20:21:08 +00:00
|
|
|
}
|
|
|
|
|
2010-05-19 20:59:32 +00:00
|
|
|
if (queryParamSet != NULL) {
|
|
|
|
free_qparam_set(queryParamSet);
|
2009-07-23 20:21:08 +00:00
|
|
|
}
|
|
|
|
|
2010-05-19 20:59:32 +00:00
|
|
|
return result;
|
2009-07-23 20:21:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-06-03 18:04:15 +00:00
|
|
|
|
|
|
|
void
|
2010-07-30 20:08:35 +00:00
|
|
|
esxUtil_FreeParsedUri(esxUtil_ParsedUri **parsedUri)
|
2010-06-03 18:04:15 +00:00
|
|
|
{
|
2010-07-30 20:08:35 +00:00
|
|
|
if (parsedUri == NULL || *parsedUri == NULL) {
|
2010-06-03 18:04:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-07-30 20:08:35 +00:00
|
|
|
VIR_FREE((*parsedUri)->transport);
|
|
|
|
VIR_FREE((*parsedUri)->vCenter);
|
|
|
|
VIR_FREE((*parsedUri)->proxy_hostname);
|
|
|
|
VIR_FREE((*parsedUri)->path_datacenter);
|
|
|
|
VIR_FREE((*parsedUri)->path_computeResource);
|
|
|
|
VIR_FREE((*parsedUri)->path_hostSystem);
|
2010-06-03 18:04:15 +00:00
|
|
|
|
2010-07-30 20:08:35 +00:00
|
|
|
VIR_FREE(*parsedUri);
|
2010-06-03 18:04:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-07-23 20:21:08 +00:00
|
|
|
int
|
|
|
|
esxUtil_ParseVirtualMachineIDString(const char *id_string, int *id)
|
|
|
|
{
|
|
|
|
/* Try to parse an integer from the complete string. */
|
|
|
|
if (virStrToLong_i(id_string, NULL, 10, id) == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If that fails try to parse an integer from the string tail
|
|
|
|
* assuming the naming scheme Virtual Center seems to use.
|
|
|
|
*/
|
|
|
|
if (STRPREFIX(id_string, "vm-")) {
|
|
|
|
if (virStrToLong_i(id_string + 3, NULL, 10, id) == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-09-23 12:52:36 +00:00
|
|
|
int
|
2010-08-01 17:53:00 +00:00
|
|
|
esxUtil_ParseDatastorePath(const char *datastorePath, char **datastoreName,
|
2010-08-25 09:44:57 +00:00
|
|
|
char **directoryName, char **directoryAndFileName)
|
2009-09-23 12:52:36 +00:00
|
|
|
{
|
2010-05-19 20:59:32 +00:00
|
|
|
int result = -1;
|
2010-08-01 17:53:00 +00:00
|
|
|
char *copyOfDatastorePath = NULL;
|
2010-04-13 22:03:12 +00:00
|
|
|
char *tmp = NULL;
|
|
|
|
char *saveptr = NULL;
|
|
|
|
char *preliminaryDatastoreName = NULL;
|
2010-08-25 09:44:57 +00:00
|
|
|
char *preliminaryDirectoryAndFileName = NULL;
|
2009-09-23 12:52:36 +00:00
|
|
|
|
2010-08-25 09:44:57 +00:00
|
|
|
if ((datastoreName != NULL && *datastoreName != NULL) ||
|
|
|
|
(directoryName != NULL && *directoryName != NULL) ||
|
|
|
|
(directoryAndFileName != NULL && *directoryAndFileName != NULL)) {
|
2010-04-02 19:34:31 +00:00
|
|
|
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
|
2009-12-15 18:08:49 +00:00
|
|
|
return -1;
|
2009-09-23 12:52:36 +00:00
|
|
|
}
|
|
|
|
|
2010-08-01 17:53:00 +00:00
|
|
|
if (esxVI_String_DeepCopyValue(©OfDatastorePath, datastorePath) < 0) {
|
2010-05-19 20:59:32 +00:00
|
|
|
goto cleanup;
|
2010-04-13 22:03:12 +00:00
|
|
|
}
|
|
|
|
|
2010-08-25 09:44:57 +00:00
|
|
|
/* Expected format: '[<datastore>] <path>' where <path> is optional */
|
|
|
|
if ((tmp = STRSKIP(copyOfDatastorePath, "[")) == NULL || *tmp == ']' ||
|
|
|
|
(preliminaryDatastoreName = strtok_r(tmp, "]", &saveptr)) == NULL) {
|
2010-01-15 22:05:26 +00:00
|
|
|
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
|
2010-08-01 17:53:00 +00:00
|
|
|
_("Datastore path '%s' doesn't have expected format "
|
|
|
|
"'[<datastore>] <path>'"), datastorePath);
|
2010-05-19 20:59:32 +00:00
|
|
|
goto cleanup;
|
2009-09-23 12:52:36 +00:00
|
|
|
}
|
|
|
|
|
2010-08-25 09:44:57 +00:00
|
|
|
if (datastoreName != NULL &&
|
|
|
|
esxVI_String_DeepCopyValue(datastoreName,
|
2010-04-13 22:03:12 +00:00
|
|
|
preliminaryDatastoreName) < 0) {
|
2010-05-19 20:59:32 +00:00
|
|
|
goto cleanup;
|
2010-04-13 22:03:12 +00:00
|
|
|
}
|
|
|
|
|
2010-08-25 09:44:57 +00:00
|
|
|
preliminaryDirectoryAndFileName = strtok_r(NULL, "", &saveptr);
|
2010-04-13 22:03:12 +00:00
|
|
|
|
2010-08-25 09:44:57 +00:00
|
|
|
if (preliminaryDirectoryAndFileName == NULL) {
|
|
|
|
preliminaryDirectoryAndFileName = (char *)"";
|
|
|
|
} else {
|
|
|
|
preliminaryDirectoryAndFileName +=
|
|
|
|
strspn(preliminaryDirectoryAndFileName, " ");
|
|
|
|
}
|
2009-09-23 12:52:36 +00:00
|
|
|
|
2010-08-25 09:44:57 +00:00
|
|
|
if (directoryAndFileName != NULL &&
|
|
|
|
esxVI_String_DeepCopyValue(directoryAndFileName,
|
|
|
|
preliminaryDirectoryAndFileName) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-09-23 12:52:36 +00:00
|
|
|
|
2010-08-25 09:44:57 +00:00
|
|
|
if (directoryName != NULL) {
|
2011-05-04 07:07:41 +00:00
|
|
|
/* Split <path> into <directory>/<file> and remove /<file> */
|
|
|
|
tmp = strrchr(preliminaryDirectoryAndFileName, '/');
|
2010-08-25 09:44:57 +00:00
|
|
|
|
2011-05-04 07:07:41 +00:00
|
|
|
if (tmp != NULL) {
|
|
|
|
*tmp = '\0';
|
2009-09-23 12:52:36 +00:00
|
|
|
}
|
|
|
|
|
2010-04-13 22:03:12 +00:00
|
|
|
if (esxVI_String_DeepCopyValue(directoryName,
|
2010-08-25 09:44:57 +00:00
|
|
|
preliminaryDirectoryAndFileName) < 0) {
|
2010-05-19 20:59:32 +00:00
|
|
|
goto cleanup;
|
2010-04-13 22:03:12 +00:00
|
|
|
}
|
2009-09-23 12:52:36 +00:00
|
|
|
}
|
|
|
|
|
2010-05-19 20:59:32 +00:00
|
|
|
result = 0;
|
|
|
|
|
2009-09-23 12:52:36 +00:00
|
|
|
cleanup:
|
2010-05-19 20:59:32 +00:00
|
|
|
if (result < 0) {
|
2010-08-25 09:44:57 +00:00
|
|
|
if (datastoreName != NULL) {
|
|
|
|
VIR_FREE(*datastoreName);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (directoryName != NULL) {
|
|
|
|
VIR_FREE(*directoryName);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (directoryAndFileName != NULL) {
|
|
|
|
VIR_FREE(*directoryAndFileName);
|
|
|
|
}
|
2010-05-19 20:59:32 +00:00
|
|
|
}
|
|
|
|
|
2010-08-01 17:53:00 +00:00
|
|
|
VIR_FREE(copyOfDatastorePath);
|
2009-09-23 12:52:36 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-07-23 20:21:08 +00:00
|
|
|
int
|
2010-01-15 22:05:26 +00:00
|
|
|
esxUtil_ResolveHostname(const char *hostname,
|
2009-08-06 13:15:45 +00:00
|
|
|
char *ipAddress, size_t ipAddress_length)
|
2009-07-23 20:21:08 +00:00
|
|
|
{
|
|
|
|
struct addrinfo hints;
|
|
|
|
struct addrinfo *result = NULL;
|
|
|
|
int errcode;
|
|
|
|
|
2010-05-19 20:59:32 +00:00
|
|
|
memset(&hints, 0, sizeof (hints));
|
2009-07-23 20:21:08 +00:00
|
|
|
|
|
|
|
hints.ai_flags = AI_ADDRCONFIG;
|
|
|
|
hints.ai_family = AF_INET;
|
|
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
|
|
hints.ai_protocol = 0;
|
|
|
|
|
|
|
|
errcode = getaddrinfo(hostname, NULL, &hints, &result);
|
|
|
|
|
|
|
|
if (errcode != 0) {
|
2010-01-15 22:05:26 +00:00
|
|
|
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
|
2010-04-02 19:34:31 +00:00
|
|
|
_("IP address lookup for host '%s' failed: %s"), hostname,
|
2009-07-23 20:21:08 +00:00
|
|
|
gai_strerror(errcode));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result == NULL) {
|
2010-01-15 22:05:26 +00:00
|
|
|
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
|
2010-04-02 19:34:31 +00:00
|
|
|
_("No IP address for host '%s' found: %s"), hostname,
|
2009-07-23 20:21:08 +00:00
|
|
|
gai_strerror(errcode));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-08-06 13:15:45 +00:00
|
|
|
errcode = getnameinfo(result->ai_addr, result->ai_addrlen, ipAddress,
|
|
|
|
ipAddress_length, NULL, 0, NI_NUMERICHOST);
|
2009-07-23 20:21:08 +00:00
|
|
|
|
|
|
|
if (errcode != 0) {
|
2010-01-15 22:05:26 +00:00
|
|
|
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
|
2010-04-02 19:34:31 +00:00
|
|
|
_("Formating IP address for host '%s' failed: %s"), hostname,
|
2009-07-23 20:21:08 +00:00
|
|
|
gai_strerror(errcode));
|
|
|
|
freeaddrinfo(result);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
freeaddrinfo(result);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-08-29 17:33:49 +00:00
|
|
|
int
|
|
|
|
esxUtil_ReformatUuid(const char *input, char *output)
|
|
|
|
{
|
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
|
|
|
|
|
|
|
if (virUUIDParse(input, uuid) < 0) {
|
2010-10-15 15:50:23 +00:00
|
|
|
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not parse UUID from string '%s'"),
|
|
|
|
input);
|
2010-08-29 17:33:49 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
virUUIDFormat(uuid, output);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2010-10-12 17:37:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
esxUtil_EscapeBase64(const char *string)
|
|
|
|
{
|
|
|
|
/* 'normal' characters don't get base64 encoded */
|
|
|
|
static const char *normal =
|
|
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'(),. _-";
|
|
|
|
|
|
|
|
/* VMware uses ',' instead of the path separator '/' in the base64 alphabet */
|
|
|
|
static const char *base64 =
|
|
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
|
|
|
|
|
|
|
|
virBuffer buffer = VIR_BUFFER_INITIALIZER;
|
|
|
|
const char *tmp1 = string;
|
|
|
|
size_t length;
|
|
|
|
unsigned char c1, c2, c3;
|
|
|
|
|
|
|
|
/* Escape sequences of non-'normal' characters as base64 without padding */
|
|
|
|
while (*tmp1 != '\0') {
|
|
|
|
length = strspn(tmp1, normal);
|
|
|
|
|
|
|
|
if (length > 0) {
|
|
|
|
virBufferAdd(&buffer, tmp1, length);
|
|
|
|
|
|
|
|
tmp1 += length;
|
|
|
|
} else {
|
|
|
|
length = strcspn(tmp1, normal);
|
|
|
|
|
|
|
|
virBufferAddChar(&buffer, '+');
|
|
|
|
|
|
|
|
while (length > 0) {
|
|
|
|
c1 = *tmp1++;
|
|
|
|
c2 = length > 1 ? *tmp1++ : 0;
|
|
|
|
c3 = length > 2 ? *tmp1++ : 0;
|
|
|
|
|
|
|
|
virBufferAddChar(&buffer, base64[(c1 >> 2) & 0x3f]);
|
|
|
|
virBufferAddChar(&buffer, base64[((c1 << 4) + (c2 >> 4)) & 0x3f]);
|
|
|
|
|
|
|
|
if (length > 1) {
|
|
|
|
virBufferAddChar(&buffer, base64[((c2 << 2) + (c3 >> 6)) & 0x3f]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (length > 2) {
|
|
|
|
virBufferAddChar(&buffer, base64[c3 & 0x3f]);
|
|
|
|
}
|
|
|
|
|
|
|
|
length -= length > 3 ? 3 : length;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*tmp1 != '\0') {
|
|
|
|
virBufferAddChar(&buffer, '-');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virBufferError(&buffer)) {
|
|
|
|
virReportOOMError();
|
|
|
|
virBufferFreeAndReset(&buffer);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return virBufferContentAndReset(&buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
esxUtil_ReplaceSpecialWindowsPathChars(char *string)
|
|
|
|
{
|
|
|
|
/* '/' and '\\' are missing on purpose */
|
|
|
|
static const char *specials = "\"*<>:|?";
|
|
|
|
|
|
|
|
char *tmp = string;
|
|
|
|
size_t length;
|
|
|
|
|
|
|
|
while (*tmp != '\0') {
|
|
|
|
length = strspn(tmp, specials);
|
|
|
|
|
|
|
|
while (length > 0) {
|
|
|
|
*tmp++ = '_';
|
|
|
|
--length;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*tmp != '\0') {
|
|
|
|
++tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
esxUtil_EscapeDatastoreItem(const char *string)
|
|
|
|
{
|
|
|
|
char *replaced = strdup(string);
|
|
|
|
char *escaped1;
|
|
|
|
char *escaped2 = NULL;
|
|
|
|
|
|
|
|
if (replaced == NULL) {
|
|
|
|
virReportOOMError();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
esxUtil_ReplaceSpecialWindowsPathChars(replaced);
|
|
|
|
|
2010-12-21 21:39:55 +00:00
|
|
|
escaped1 = virVMXEscapeHexPercent(replaced);
|
2010-10-12 17:37:39 +00:00
|
|
|
|
|
|
|
if (escaped1 == NULL) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
escaped2 = esxUtil_EscapeBase64(escaped1);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(replaced);
|
|
|
|
VIR_FREE(escaped1);
|
|
|
|
|
|
|
|
return escaped2;
|
|
|
|
}
|
2011-03-03 21:11:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
esxUtil_EscapeForXml(const char *string)
|
|
|
|
{
|
|
|
|
virBuffer buffer = VIR_BUFFER_INITIALIZER;
|
|
|
|
|
|
|
|
virBufferEscapeString(&buffer, "%s", string);
|
|
|
|
|
|
|
|
if (virBufferError(&buffer)) {
|
|
|
|
virReportOOMError();
|
|
|
|
virBufferFreeAndReset(&buffer);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return virBufferContentAndReset(&buffer);
|
|
|
|
}
|