esx_driver.c 124.5 KB
Newer Older
1 2

/*
3
 * esx_driver.c: core driver functions for managing VMware ESX hosts
4
 *
E
Eric Blake 已提交
5
 * Copyright (C) 2010 Red Hat, Inc.
6
 * Copyright (C) 2009-2010 Matthias Bolte <matthias.bolte@googlemail.com>
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
 * 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 "domain_conf.h"
31
#include "authhelper.h"
32 33 34 35 36
#include "util.h"
#include "memory.h"
#include "logging.h"
#include "uuid.h"
#include "esx_driver.h"
37 38 39 40 41
#include "esx_interface_driver.h"
#include "esx_network_driver.h"
#include "esx_storage_driver.h"
#include "esx_device_monitor.h"
#include "esx_secret_driver.h"
M
Matthias Bolte 已提交
42
#include "esx_nwfilter_driver.h"
43
#include "esx_private.h"
44 45 46 47 48 49 50 51 52 53 54
#include "esx_vi.h"
#include "esx_vi_methods.h"
#include "esx_util.h"
#include "esx_vmx.h"

#define VIR_FROM_THIS VIR_FROM_ESX

static int esxDomainGetMaxVcpus(virDomainPtr domain);



55
static esxVI_Boolean
56
esxSupportsLongMode(esxPrivate *priv)
57 58 59 60 61 62
{
    esxVI_String *propertyNameList = NULL;
    esxVI_ObjectContent *hostSystem = NULL;
    esxVI_DynamicProperty *dynamicProperty = NULL;
    esxVI_HostCpuIdInfo *hostCpuIdInfoList = NULL;
    esxVI_HostCpuIdInfo *hostCpuIdInfo = NULL;
63
    esxVI_ParsedHostCpuIdInfo parsedHostCpuIdInfo;
64 65 66 67 68 69
    char edxLongModeBit = '?';

    if (priv->supportsLongMode != esxVI_Boolean_Undefined) {
        return priv->supportsLongMode;
    }

70 71 72 73 74
    if (priv->host == NULL) {
        /* FIXME: Currently no host for a vpx:// connection */
        return esxVI_Boolean_False;
    }

75
    if (esxVI_EnsureSession(priv->host) < 0) {
M
Matthias Bolte 已提交
76
        return esxVI_Boolean_Undefined;
77 78
    }

79
    if (esxVI_String_AppendValueToList(&propertyNameList,
80
                                       "hardware.cpuFeature") < 0 ||
81
        esxVI_LookupObjectContentByType(priv->host, priv->host->hostFolder,
82 83
                                        "HostSystem", propertyNameList,
                                        esxVI_Boolean_True, &hostSystem) < 0) {
M
Matthias Bolte 已提交
84
        goto cleanup;
85 86 87
    }

    if (hostSystem == NULL) {
88 89
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                  _("Could not retrieve the HostSystem object"));
M
Matthias Bolte 已提交
90
        goto cleanup;
91 92 93 94 95 96
    }

    for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
         dynamicProperty = dynamicProperty->_next) {
        if (STREQ(dynamicProperty->name, "hardware.cpuFeature")) {
            if (esxVI_HostCpuIdInfo_CastListFromAnyType
97
                  (dynamicProperty->val, &hostCpuIdInfoList) < 0) {
M
Matthias Bolte 已提交
98
                goto cleanup;
99 100 101 102 103
            }

            for (hostCpuIdInfo = hostCpuIdInfoList; hostCpuIdInfo != NULL;
                 hostCpuIdInfo = hostCpuIdInfo->_next) {
                if (hostCpuIdInfo->level->value == -2147483647) { /* 0x80000001 */
104 105
                    if (esxVI_ParseHostCpuIdInfo(&parsedHostCpuIdInfo,
                                                 hostCpuIdInfo) < 0) {
M
Matthias Bolte 已提交
106
                        goto cleanup;
107 108
                    }

109
                    edxLongModeBit = parsedHostCpuIdInfo.edx[29];
110 111 112 113 114 115

                    if (edxLongModeBit == '1') {
                        priv->supportsLongMode = esxVI_Boolean_True;
                    } else if (edxLongModeBit == '0') {
                        priv->supportsLongMode = esxVI_Boolean_False;
                    } else {
116
                        ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
117 118 119 120
                                  _("Bit 29 (Long Mode) of HostSystem property "
                                    "'hardware.cpuFeature[].edx' with value '%s' "
                                    "has unexpected value '%c', expecting '0' "
                                    "or '1'"), hostCpuIdInfo->edx, edxLongModeBit);
M
Matthias Bolte 已提交
121
                        goto cleanup;
122 123 124 125 126 127 128 129 130 131 132 133 134
                    }

                    break;
                }
            }

            break;
        } else {
            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
        }
    }

  cleanup:
M
Matthias Bolte 已提交
135 136 137 138
    /*
     * If we goto cleanup in case of an error then priv->supportsLongMode
     * is still esxVI_Boolean_Undefined, therefore we don't need to set it.
     */
139 140 141 142 143 144 145 146 147
    esxVI_String_Free(&propertyNameList);
    esxVI_ObjectContent_Free(&hostSystem);
    esxVI_HostCpuIdInfo_Free(&hostCpuIdInfoList);

    return priv->supportsLongMode;
}



148 149 150 151 152 153 154 155
static int
esxLookupHostSystemBiosUuid(esxPrivate *priv, unsigned char *uuid)
{
    int result = -1;
    esxVI_String *propertyNameList = NULL;
    esxVI_ObjectContent *hostSystem = NULL;
    esxVI_DynamicProperty *dynamicProperty = NULL;

156 157 158 159 160
    if (priv->host == NULL) {
        /* FIXME: Currently no host for a vpx:// connection */
        return 0;
    }

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
    if (esxVI_EnsureSession(priv->host) < 0) {
        return -1;
    }

    if (esxVI_String_AppendValueToList(&propertyNameList,
                                       "hardware.systemInfo.uuid") < 0 ||
        esxVI_LookupObjectContentByType(priv->host, priv->host->hostFolder,
                                        "HostSystem", propertyNameList,
                                        esxVI_Boolean_True, &hostSystem) < 0) {
        goto cleanup;
    }

    if (hostSystem == NULL) {
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                  _("Could not retrieve the HostSystem object"));
        goto cleanup;
    }

    for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
         dynamicProperty = dynamicProperty->_next) {
        if (STREQ(dynamicProperty->name, "hardware.systemInfo.uuid")) {
            if (esxVI_AnyType_ExpectType(dynamicProperty->val,
                                         esxVI_Type_String) < 0) {
                goto cleanup;
            }

            if (strlen(dynamicProperty->val->string) > 0) {
                if (virUUIDParse(dynamicProperty->val->string, uuid) < 0) {
                    ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
                              _("Could not parse UUID from string '%s'"),
                              dynamicProperty->val->string);
                    goto cleanup;
                }
            } else {
                /* HostSystem has an empty UUID */
                memset(uuid, 0, VIR_UUID_BUFLEN);
            }

            break;
        } else {
            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
        }
    }

    result = 0;

  cleanup:
    esxVI_String_Free(&propertyNameList);
    esxVI_ObjectContent_Free(&hostSystem);

    return result;
}



216
static virCapsPtr
217
esxCapsInit(esxPrivate *priv)
218
{
219
    esxVI_Boolean supportsLongMode = esxSupportsLongMode(priv);
220 221 222
    virCapsPtr caps = NULL;
    virCapsGuestPtr guest = NULL;

223 224 225 226 227 228 229 230 231
    if (supportsLongMode == esxVI_Boolean_Undefined) {
        return NULL;
    }

    if (supportsLongMode == esxVI_Boolean_True) {
        caps = virCapabilitiesNew("x86_64", 1, 1);
    } else {
        caps = virCapabilitiesNew("i686", 1, 1);
    }
232 233

    if (caps == NULL) {
234
        virReportOOMError();
235 236 237
        return NULL;
    }

238
    virCapabilitiesSetMacPrefix(caps, (unsigned char[]){ 0x00, 0x0c, 0x29 });
239 240
    virCapabilitiesAddHostMigrateTransport(caps, "esx");

241 242
    caps->hasWideScsiBus = true;

243 244 245 246
    if (esxLookupHostSystemBiosUuid(priv, caps->host.host_uuid) < 0) {
        goto failure;
    }

247 248 249
    /* i686 */
    guest = virCapabilitiesAddGuest(caps, "hvm", "i686", 32, NULL, NULL, 0,
                                    NULL);
250 251 252 253 254 255 256 257 258 259 260 261 262 263

    if (guest == NULL) {
        goto failure;
    }

    /*
     * FIXME: Maybe distinguish betwen ESX and GSX here, see
     * esxVMX_ParseConfig() and VIR_DOMAIN_VIRT_VMWARE
     */
    if (virCapabilitiesAddGuestDomain(guest, "vmware", NULL, NULL, 0,
                                      NULL) == NULL) {
        goto failure;
    }

264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
    /* x86_64 */
    if (supportsLongMode == esxVI_Boolean_True) {
        guest = virCapabilitiesAddGuest(caps, "hvm", "x86_64", 64, NULL, NULL,
                                        0, NULL);

        if (guest == NULL) {
            goto failure;
        }

        /*
         * FIXME: Maybe distinguish betwen ESX and GSX here, see
         * esxVMX_ParseConfig() and VIR_DOMAIN_VIRT_VMWARE
         */
        if (virCapabilitiesAddGuestDomain(guest, "vmware", NULL, NULL, 0,
                                          NULL) == NULL) {
            goto failure;
        }
    }

283 284 285 286 287 288 289 290 291 292
    return caps;

  failure:
    virCapabilitiesFree(caps);

    return NULL;
}



293 294 295 296
static int
esxConnectToHost(esxPrivate *priv, virConnectAuthPtr auth,
                 const char *hostname, int port,
                 const char *predefinedUsername,
M
Matthias Bolte 已提交
297
                 esxUtil_ParsedUri *parsedUri,
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
                 esxVI_ProductVersion expectedProductVersion,
                 char **vCenterIpAddress)
{
    int result = -1;
    char ipAddress[NI_MAXHOST] = "";
    char *username = NULL;
    char *password = NULL;
    char *url = NULL;
    esxVI_String *propertyNameList = NULL;
    esxVI_ObjectContent *hostSystem = NULL;
    esxVI_Boolean inMaintenanceMode = esxVI_Boolean_Undefined;

    if (vCenterIpAddress == NULL || *vCenterIpAddress != NULL) {
        ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
        return -1;
    }

    if (esxUtil_ResolveHostname(hostname, ipAddress, NI_MAXHOST) < 0) {
        return -1;
    }

    if (predefinedUsername != NULL) {
        username = strdup(predefinedUsername);

        if (username == NULL) {
            virReportOOMError();
            goto cleanup;
        }
    } else {
        username = virRequestUsername(auth, "root", hostname);

        if (username == NULL) {
            ESX_ERROR(VIR_ERR_AUTH_FAILED, "%s", _("Username request failed"));
            goto cleanup;
        }
    }

    password = virRequestPassword(auth, username, hostname);

    if (password == NULL) {
        ESX_ERROR(VIR_ERR_AUTH_FAILED, "%s", _("Password request failed"));
        goto cleanup;
    }

    if (virAsprintf(&url, "%s://%s:%d/sdk", priv->transport, hostname,
                    port) < 0) {
        virReportOOMError();
        goto cleanup;
    }

    if (esxVI_Context_Alloc(&priv->host) < 0 ||
        esxVI_Context_Connect(priv->host, url, ipAddress, username, password,
M
Matthias Bolte 已提交
350
                              parsedUri) < 0) {
351 352 353 354 355
        goto cleanup;
    }

    if (expectedProductVersion == esxVI_ProductVersion_ESX) {
        if (priv->host->productVersion != esxVI_ProductVersion_ESX35 &&
M
Matthias Bolte 已提交
356 357 358
            priv->host->productVersion != esxVI_ProductVersion_ESX40 &&
            priv->host->productVersion != esxVI_ProductVersion_ESX41 &&
            priv->host->productVersion != esxVI_ProductVersion_ESX4x) {
359
            ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
M
Matthias Bolte 已提交
360
                      _("%s is neither an ESX 3.5 host nor an ESX 4.x host"),
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
                      hostname);
            goto cleanup;
        }
    } else { /* GSX */
        if (priv->host->productVersion != esxVI_ProductVersion_GSX20) {
            ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
                      _("%s isn't a GSX 2.0 host"), hostname);
            goto cleanup;
        }
    }

    /* Query the host for maintenance mode and vCenter IP address */
    if (esxVI_String_AppendValueListToList(&propertyNameList,
                                           "runtime.inMaintenanceMode\0"
                                           "summary.managementServerIp\0") < 0 ||
        esxVI_LookupHostSystemByIp(priv->host, ipAddress, propertyNameList,
                                   &hostSystem) < 0 ||
        esxVI_GetBoolean(hostSystem, "runtime.inMaintenanceMode",
                         &inMaintenanceMode,
                         esxVI_Occurrence_RequiredItem) < 0 ||
        esxVI_GetStringValue(hostSystem, "summary.managementServerIp",
                             vCenterIpAddress,
                             esxVI_Occurrence_OptionalItem) < 0) {
        goto cleanup;
    }

    /* Warn if host is in maintenance mode */
    if (inMaintenanceMode == esxVI_Boolean_True) {
        VIR_WARN0("The server is in maintenance mode");
    }

    if (*vCenterIpAddress != NULL) {
        *vCenterIpAddress = strdup(*vCenterIpAddress);

        if (*vCenterIpAddress == NULL) {
            virReportOOMError();
            goto cleanup;
        }
    }

    result = 0;

  cleanup:
    VIR_FREE(password);
    VIR_FREE(username);
    VIR_FREE(url);
    esxVI_String_Free(&propertyNameList);
    esxVI_ObjectContent_Free(&hostSystem);

    return result;
}



static int
esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth,
                    const char *hostname, int port,
                    const char *predefinedUsername,
M
Matthias Bolte 已提交
419
                    esxUtil_ParsedUri *parsedUri)
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
{
    int result = -1;
    char ipAddress[NI_MAXHOST] = "";
    char *username = NULL;
    char *password = NULL;
    char *url = NULL;

    if (esxUtil_ResolveHostname(hostname, ipAddress, NI_MAXHOST) < 0) {
        return -1;
    }

    if (predefinedUsername != NULL) {
        username = strdup(predefinedUsername);

        if (username == NULL) {
            virReportOOMError();
            goto cleanup;
        }
    } else {
        username = virRequestUsername(auth, "administrator", hostname);

        if (username == NULL) {
            ESX_ERROR(VIR_ERR_AUTH_FAILED, "%s", _("Username request failed"));
            goto cleanup;
        }
    }

    password = virRequestPassword(auth, username, hostname);

    if (password == NULL) {
        ESX_ERROR(VIR_ERR_AUTH_FAILED, "%s", _("Password request failed"));
        goto cleanup;
    }

    if (virAsprintf(&url, "%s://%s:%d/sdk", priv->transport, hostname,
                    port) < 0) {
        virReportOOMError();
        goto cleanup;
    }

    if (esxVI_Context_Alloc(&priv->vCenter) < 0 ||
        esxVI_Context_Connect(priv->vCenter, url, ipAddress, username,
M
Matthias Bolte 已提交
462
                              password, parsedUri) < 0) {
463 464 465 466
        goto cleanup;
    }

    if (priv->vCenter->productVersion != esxVI_ProductVersion_VPX25 &&
M
Matthias Bolte 已提交
467 468 469
        priv->vCenter->productVersion != esxVI_ProductVersion_VPX40 &&
        priv->vCenter->productVersion != esxVI_ProductVersion_VPX41 &&
        priv->vCenter->productVersion != esxVI_ProductVersion_VPX4x) {
470 471
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
                  _("%s is neither a vCenter 2.5 server nor a vCenter "
M
Matthias Bolte 已提交
472
                    "4.x server"), hostname);
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
        goto cleanup;
    }

    result = 0;

  cleanup:
    VIR_FREE(password);
    VIR_FREE(username);
    VIR_FREE(url);

    return result;
}



488
/*
489
 * URI format: {vpx|esx|gsx}://[<username>@]<hostname>[:<port>]/[<query parameter> ...]
490
 *
491 492
 * If no port is specified the default port is set dependent on the scheme and
 * transport parameter:
493 494
 * - vpx+http  80
 * - vpx+https 443
495
 * - esx+http  80
496
 * - esx+https 443
497 498 499
 * - gsx+http  8222
 * - gsx+https 8333
 *
500 501
 * Optional query parameters:
 * - transport={http|https}
502
 * - vcenter={<vcenter>|*}             only useful for an esx:// connection
503 504
 * - no_verify={0|1}
 * - auto_answer={0|1}
M
Matthias Bolte 已提交
505
 * - proxy=[{http|socks|socks4|socks4a|socks5}://]<hostname>[:<port>]
506
 *
507 508 509
 * If no transport parameter is specified https is used.
 *
 * The vcenter parameter is only necessary for migration, because the vCenter
510 511 512 513
 * server is in charge to initiate a migration between two ESX hosts. The
 * vcenter parameter can be set to an explicity hostname or to *. If set to *,
 * the driver will check if the ESX host is managed by a vCenter and connect to
 * it. If the ESX host is not managed by a vCenter an error is reported.
514 515
 *
 * If the no_verify parameter is set to 1, this disables libcurl client checks
516
 * of the server's certificate. The default value it 0.
517 518 519 520
 *
 * If the auto_answer parameter is set to 1, the driver will respond to all
 * virtual machine questions with the default answer, otherwise virtual machine
 * questions will be reported as errors. The default value it 0.
M
Matthias Bolte 已提交
521 522 523 524
 *
 * The proxy parameter allows to specify a proxy for to be used by libcurl.
 * The default for the optional <type> part is http and socks is synonymous for
 * socks5. The optional <port> part allows to override the default port 1080.
525 526 527 528
 */
static virDrvOpenStatus
esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED)
{
M
Matthias Bolte 已提交
529
    virDrvOpenStatus result = VIR_DRV_OPEN_ERROR;
530
    esxPrivate *priv = NULL;
M
Matthias Bolte 已提交
531
    esxUtil_ParsedUri *parsedUri = NULL;
532
    char *potentialVCenterIpAddress = NULL;
M
Matthias Bolte 已提交
533
    char vCenterIpAddress[NI_MAXHOST] = "";
534

535
    /* Decline if the URI is NULL or the scheme is not one of {vpx|esx|gsx} */
536
    if (conn->uri == NULL || conn->uri->scheme == NULL ||
537 538
        (STRCASENEQ(conn->uri->scheme, "vpx") &&
         STRCASENEQ(conn->uri->scheme, "esx") &&
539
         STRCASENEQ(conn->uri->scheme, "gsx"))) {
540 541 542
        return VIR_DRV_OPEN_DECLINED;
    }

M
Matthias Bolte 已提交
543 544 545
    /* Decline URIs without server part, or missing auth */
    if (conn->uri->server == NULL || auth == NULL || auth->cb == NULL) {
        return VIR_DRV_OPEN_DECLINED;
546 547 548 549
    }

    /* Allocate per-connection private data */
    if (VIR_ALLOC(priv) < 0) {
550
        virReportOOMError();
M
Matthias Bolte 已提交
551
        goto cleanup;
552 553
    }

M
Matthias Bolte 已提交
554
    if (esxUtil_ParseUri(&parsedUri, conn->uri) < 0) {
555 556 557
        goto cleanup;
    }

M
Matthias Bolte 已提交
558 559
    priv->transport = parsedUri->transport;
    parsedUri->transport = NULL;
560

M
Matthias Bolte 已提交
561 562
    priv->maxVcpus = -1;
    priv->supportsVMotion = esxVI_Boolean_Undefined;
563
    priv->supportsLongMode = esxVI_Boolean_Undefined;
M
Matthias Bolte 已提交
564 565
    priv->autoAnswer = parsedUri->autoAnswer ? esxVI_Boolean_True
                                             : esxVI_Boolean_False;
566 567
    priv->usedCpuTimeCounterId = -1;

M
Matthias Bolte 已提交
568 569 570 571 572 573 574
    /*
     * Set the port dependent on the transport protocol if no port is
     * specified. This allows us to rely on the port parameter being
     * correctly set when building URIs later on, without the need to
     * distinguish between the situations port == 0 and port != 0
     */
    if (conn->uri->port == 0) {
575 576
        if (STRCASEEQ(conn->uri->scheme, "vpx") ||
            STRCASEEQ(conn->uri->scheme, "esx")) {
M
Matthias Bolte 已提交
577 578 579 580 581 582 583 584 585 586 587
            if (STRCASEEQ(priv->transport, "https")) {
                conn->uri->port = 443;
            } else {
                conn->uri->port = 80;
            }
        } else { /* GSX */
            if (STRCASEEQ(priv->transport, "https")) {
                conn->uri->port = 8333;
            } else {
                conn->uri->port = 8222;
            }
588
        }
M
Matthias Bolte 已提交
589
    }
590

591 592 593 594
    if (STRCASEEQ(conn->uri->scheme, "esx") ||
        STRCASEEQ(conn->uri->scheme, "gsx")) {
        /* Connect to host */
        if (esxConnectToHost(priv, auth, conn->uri->server, conn->uri->port,
M
Matthias Bolte 已提交
595
                             conn->uri->user, parsedUri,
596 597 598 599
                             STRCASEEQ(conn->uri->scheme, "esx")
                               ? esxVI_ProductVersion_ESX
                               : esxVI_ProductVersion_GSX,
                             &potentialVCenterIpAddress) < 0) {
M
Matthias Bolte 已提交
600
            goto cleanup;
601
        }
602

603
        /* Connect to vCenter */
M
Matthias Bolte 已提交
604 605
        if (parsedUri->vCenter != NULL) {
            if (STREQ(parsedUri->vCenter, "*")) {
606 607 608
                if (potentialVCenterIpAddress == NULL) {
                    ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                              _("This host is not managed by a vCenter"));
M
Matthias Bolte 已提交
609
                    goto cleanup;
610 611
                }

612 613 614 615 616 617 618 619
                if (virStrcpyStatic(vCenterIpAddress,
                                    potentialVCenterIpAddress) == NULL) {
                    ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
                              _("vCenter IP address %s too big for destination"),
                              potentialVCenterIpAddress);
                    goto cleanup;
                }
            } else {
M
Matthias Bolte 已提交
620
                if (esxUtil_ResolveHostname(parsedUri->vCenter,
621 622 623
                                            vCenterIpAddress, NI_MAXHOST) < 0) {
                    goto cleanup;
                }
624

625 626
                if (potentialVCenterIpAddress != NULL &&
                    STRNEQ(vCenterIpAddress, potentialVCenterIpAddress)) {
627
                    ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
628 629 630
                              _("This host is managed by a vCenter with IP "
                                "address %s, but a mismachting vCenter '%s' "
                                "(%s) has been specified"),
M
Matthias Bolte 已提交
631
                              potentialVCenterIpAddress, parsedUri->vCenter,
632
                              vCenterIpAddress);
M
Matthias Bolte 已提交
633
                    goto cleanup;
634 635
                }
            }
636

637
            if (esxConnectToVCenter(priv, auth, vCenterIpAddress,
M
Matthias Bolte 已提交
638
                                    conn->uri->port, NULL, parsedUri) < 0) {
639 640
                goto cleanup;
            }
641 642
        }

643 644 645 646
        priv->primary = priv->host;
    } else { /* VPX */
        /* Connect to vCenter */
        if (esxConnectToVCenter(priv, auth, conn->uri->server, conn->uri->port,
M
Matthias Bolte 已提交
647
                                conn->uri->user, parsedUri) < 0) {
M
Matthias Bolte 已提交
648
            goto cleanup;
649 650
        }

651
        priv->primary = priv->vCenter;
652 653 654
    }

    conn->privateData = priv;
655

M
Matthias Bolte 已提交
656
    /* Setup capabilities */
657
    priv->caps = esxCapsInit(priv);
658

M
Matthias Bolte 已提交
659
    if (priv->caps == NULL) {
M
Matthias Bolte 已提交
660
        goto cleanup;
661 662
    }

M
Matthias Bolte 已提交
663
    result = VIR_DRV_OPEN_SUCCESS;
664

M
Matthias Bolte 已提交
665 666
  cleanup:
    if (result == VIR_DRV_OPEN_ERROR && priv != NULL) {
667
        esxVI_Context_Free(&priv->host);
M
Matthias Bolte 已提交
668
        esxVI_Context_Free(&priv->vCenter);
669

670 671
        virCapabilitiesFree(priv->caps);

M
Matthias Bolte 已提交
672
        VIR_FREE(priv->transport);
673 674 675
        VIR_FREE(priv);
    }

M
Matthias Bolte 已提交
676
    esxUtil_FreeParsedUri(&parsedUri);
677
    VIR_FREE(potentialVCenterIpAddress);
678

M
Matthias Bolte 已提交
679
    return result;
680 681 682 683 684 685 686
}



static int
esxClose(virConnectPtr conn)
{
M
Matthias Bolte 已提交
687
    esxPrivate *priv = conn->privateData;
E
Eric Blake 已提交
688
    int result = 0;
689

690 691 692 693 694
    if (priv->host != NULL) {
        if (esxVI_EnsureSession(priv->host) < 0 ||
            esxVI_Logout(priv->host) < 0) {
            result = -1;
        }
695

696 697
        esxVI_Context_Free(&priv->host);
    }
698

M
Matthias Bolte 已提交
699
    if (priv->vCenter != NULL) {
E
Eric Blake 已提交
700 701 702 703
        if (esxVI_EnsureSession(priv->vCenter) < 0 ||
            esxVI_Logout(priv->vCenter) < 0) {
            result = -1;
        }
704

M
Matthias Bolte 已提交
705
        esxVI_Context_Free(&priv->vCenter);
706 707
    }

708 709
    virCapabilitiesFree(priv->caps);

710 711 712 713 714
    VIR_FREE(priv->transport);
    VIR_FREE(priv);

    conn->privateData = NULL;

E
Eric Blake 已提交
715
    return result;
716 717 718 719 720
}



static esxVI_Boolean
721
esxSupportsVMotion(esxPrivate *priv)
722 723 724 725 726
{
    esxVI_String *propertyNameList = NULL;
    esxVI_ObjectContent *hostSystem = NULL;
    esxVI_DynamicProperty *dynamicProperty = NULL;

M
Matthias Bolte 已提交
727 728
    if (priv->supportsVMotion != esxVI_Boolean_Undefined) {
        return priv->supportsVMotion;
729 730
    }

731 732 733 734 735
    if (priv->host == NULL) {
        /* FIXME: Currently no host for a vpx:// connection */
        return esxVI_Boolean_False;
    }

736
    if (esxVI_EnsureSession(priv->host) < 0) {
M
Matthias Bolte 已提交
737
        return esxVI_Boolean_Undefined;
738 739
    }

740
    if (esxVI_String_AppendValueToList(&propertyNameList,
741
                                       "capability.vmotionSupported") < 0 ||
742
        esxVI_LookupObjectContentByType(priv->host, priv->host->hostFolder,
743 744
                                        "HostSystem", propertyNameList,
                                        esxVI_Boolean_True, &hostSystem) < 0) {
M
Matthias Bolte 已提交
745
        goto cleanup;
746 747 748
    }

    if (hostSystem == NULL) {
749 750
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                  _("Could not retrieve the HostSystem object"));
M
Matthias Bolte 已提交
751
        goto cleanup;
752 753 754 755 756
    }

    for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
         dynamicProperty = dynamicProperty->_next) {
        if (STREQ(dynamicProperty->name, "capability.vmotionSupported")) {
757
            if (esxVI_AnyType_ExpectType(dynamicProperty->val,
758
                                         esxVI_Type_Boolean) < 0) {
M
Matthias Bolte 已提交
759
                goto cleanup;
760 761
            }

M
Matthias Bolte 已提交
762
            priv->supportsVMotion = dynamicProperty->val->boolean;
763 764 765 766 767 768 769
            break;
        } else {
            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
        }
    }

  cleanup:
M
Matthias Bolte 已提交
770 771 772 773
    /*
     * If we goto cleanup in case of an error then priv->supportsVMotion is
     * still esxVI_Boolean_Undefined, therefore we don't need to set it.
     */
774 775 776
    esxVI_String_Free(&propertyNameList);
    esxVI_ObjectContent_Free(&hostSystem);

M
Matthias Bolte 已提交
777
    return priv->supportsVMotion;
778 779 780 781 782 783 784
}



static int
esxSupportsFeature(virConnectPtr conn, int feature)
{
M
Matthias Bolte 已提交
785
    esxPrivate *priv = conn->privateData;
M
Matthias Bolte 已提交
786
    esxVI_Boolean supportsVMotion = esxVI_Boolean_Undefined;
787 788 789

    switch (feature) {
      case VIR_DRV_FEATURE_MIGRATION_V1:
790
        supportsVMotion = esxSupportsVMotion(priv);
791

M
Matthias Bolte 已提交
792
        if (supportsVMotion == esxVI_Boolean_Undefined) {
793 794 795
            return -1;
        }

M
Matthias Bolte 已提交
796 797 798
        /* Migration is only possible via a vCenter and if VMotion is enabled */
        return priv->vCenter != NULL &&
               supportsVMotion == esxVI_Boolean_True ? 1 : 0;
799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817

      default:
        return 0;
    }
}



static const char *
esxGetType(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return "ESX";
}



static int
esxGetVersion(virConnectPtr conn, unsigned long *version)
{
M
Matthias Bolte 已提交
818
    esxPrivate *priv = conn->privateData;
819

820
    if (virParseVersionString(priv->primary->service->about->version,
821 822
                              version) < 0) {
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
823
                  _("Could not parse version number from '%s'"),
824
                  priv->primary->service->about->version);
825

826
        return -1;
827 828 829 830 831 832 833 834 835 836
    }

    return 0;
}



static char *
esxGetHostname(virConnectPtr conn)
{
M
Matthias Bolte 已提交
837
    esxPrivate *priv = conn->privateData;
838 839 840 841 842 843 844
    esxVI_String *propertyNameList = NULL;
    esxVI_ObjectContent *hostSystem = NULL;
    esxVI_DynamicProperty *dynamicProperty = NULL;
    const char *hostName = NULL;
    const char *domainName = NULL;
    char *complete = NULL;

845 846 847 848 849 850 851
    if (priv->host == NULL) {
        /* FIXME: Currently no host for a vpx:// connection */
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                  _("Could not retrieve the hostname for a vpx:// connection"));
        return NULL;
    }

852
    if (esxVI_EnsureSession(priv->host) < 0) {
M
Matthias Bolte 已提交
853
        return NULL;
854 855 856
    }

    if (esxVI_String_AppendValueListToList
857
          (&propertyNameList,
858 859
           "config.network.dnsConfig.hostName\0"
           "config.network.dnsConfig.domainName\0") < 0 ||
860
        esxVI_LookupObjectContentByType(priv->host, priv->host->hostFolder,
861 862
                                        "HostSystem", propertyNameList,
                                        esxVI_Boolean_True, &hostSystem) < 0) {
M
Matthias Bolte 已提交
863
        goto cleanup;
864 865 866
    }

    if (hostSystem == NULL) {
867 868
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                  _("Could not retrieve the HostSystem object"));
M
Matthias Bolte 已提交
869
        goto cleanup;
870 871 872 873 874 875
    }

    for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
         dynamicProperty = dynamicProperty->_next) {
        if (STREQ(dynamicProperty->name,
                  "config.network.dnsConfig.hostName")) {
876
            if (esxVI_AnyType_ExpectType(dynamicProperty->val,
877
                                         esxVI_Type_String) < 0) {
M
Matthias Bolte 已提交
878
                goto cleanup;
879 880 881 882 883
            }

            hostName = dynamicProperty->val->string;
        } else if (STREQ(dynamicProperty->name,
                         "config.network.dnsConfig.domainName")) {
884
            if (esxVI_AnyType_ExpectType(dynamicProperty->val,
885
                                         esxVI_Type_String) < 0) {
M
Matthias Bolte 已提交
886
                goto cleanup;
887 888 889 890 891 892 893 894
            }

            domainName = dynamicProperty->val->string;
        } else {
            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
        }
    }

M
Matthias Bolte 已提交
895
    if (hostName == NULL || strlen(hostName) < 1) {
896 897
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                  _("Missing or empty 'hostName' property"));
M
Matthias Bolte 已提交
898
        goto cleanup;
899 900
    }

M
Matthias Bolte 已提交
901
    if (domainName == NULL || strlen(domainName) < 1) {
902
        complete = strdup(hostName);
903

904
        if (complete == NULL) {
905
            virReportOOMError();
M
Matthias Bolte 已提交
906
            goto cleanup;
907 908 909
        }
    } else {
        if (virAsprintf(&complete, "%s.%s", hostName, domainName) < 0) {
910
            virReportOOMError();
M
Matthias Bolte 已提交
911
            goto cleanup;
912
        }
913 914 915
    }

  cleanup:
M
Matthias Bolte 已提交
916 917 918 919 920
    /*
     * If we goto cleanup in case of an error then complete is still NULL,
     * either strdup returned NULL or virAsprintf failed. When virAsprintf
     * fails it guarantees setting complete to NULL
     */
921 922 923 924 925 926 927 928 929 930 931
    esxVI_String_Free(&propertyNameList);
    esxVI_ObjectContent_Free(&hostSystem);

    return complete;
}



static int
esxNodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo)
{
M
Matthias Bolte 已提交
932
    int result = -1;
M
Matthias Bolte 已提交
933
    esxPrivate *priv = conn->privateData;
934 935 936 937 938 939 940 941 942 943 944
    esxVI_String *propertyNameList = NULL;
    esxVI_ObjectContent *hostSystem = NULL;
    esxVI_DynamicProperty *dynamicProperty = NULL;
    int64_t cpuInfo_hz = 0;
    int16_t cpuInfo_numCpuCores = 0;
    int16_t cpuInfo_numCpuPackages = 0;
    int16_t cpuInfo_numCpuThreads = 0;
    int64_t memorySize = 0;
    int32_t numaInfo_numNodes = 0;
    char *ptr = NULL;

M
Matthias Bolte 已提交
945
    memset(nodeinfo, 0, sizeof (*nodeinfo));
946

947 948 949 950 951 952 953
    if (priv->host == NULL) {
        /* FIXME: Currently no host for a vpx:// connection */
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                  _("Nodeinfo is not available for a vpx:// connection"));
        return -1;
    }

954
    if (esxVI_EnsureSession(priv->host) < 0) {
M
Matthias Bolte 已提交
955
        return -1;
956 957
    }

958
    if (esxVI_String_AppendValueListToList(&propertyNameList,
959 960 961 962 963 964 965
                                           "hardware.cpuInfo.hz\0"
                                           "hardware.cpuInfo.numCpuCores\0"
                                           "hardware.cpuInfo.numCpuPackages\0"
                                           "hardware.cpuInfo.numCpuThreads\0"
                                           "hardware.memorySize\0"
                                           "hardware.numaInfo.numNodes\0"
                                           "summary.hardware.cpuModel\0") < 0 ||
966
        esxVI_LookupObjectContentByType(priv->host, priv->host->hostFolder,
967 968
                                        "HostSystem", propertyNameList,
                                        esxVI_Boolean_True, &hostSystem) < 0) {
M
Matthias Bolte 已提交
969
        goto cleanup;
970 971 972
    }

    if (hostSystem == NULL) {
973 974
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                  _("Could not retrieve the HostSystem object"));
M
Matthias Bolte 已提交
975
        goto cleanup;
976 977 978 979 980
    }

    for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
         dynamicProperty = dynamicProperty->_next) {
        if (STREQ(dynamicProperty->name, "hardware.cpuInfo.hz")) {
981
            if (esxVI_AnyType_ExpectType(dynamicProperty->val,
982
                                         esxVI_Type_Long) < 0) {
M
Matthias Bolte 已提交
983
                goto cleanup;
984 985 986 987 988
            }

            cpuInfo_hz = dynamicProperty->val->int64;
        } else if (STREQ(dynamicProperty->name,
                         "hardware.cpuInfo.numCpuCores")) {
989
            if (esxVI_AnyType_ExpectType(dynamicProperty->val,
990
                                         esxVI_Type_Short) < 0) {
M
Matthias Bolte 已提交
991
                goto cleanup;
992 993 994 995 996
            }

            cpuInfo_numCpuCores = dynamicProperty->val->int16;
        } else if (STREQ(dynamicProperty->name,
                         "hardware.cpuInfo.numCpuPackages")) {
997
            if (esxVI_AnyType_ExpectType(dynamicProperty->val,
998
                                         esxVI_Type_Short) < 0) {
M
Matthias Bolte 已提交
999
                goto cleanup;
1000 1001 1002 1003 1004
            }

            cpuInfo_numCpuPackages = dynamicProperty->val->int16;
        } else if (STREQ(dynamicProperty->name,
                         "hardware.cpuInfo.numCpuThreads")) {
1005
            if (esxVI_AnyType_ExpectType(dynamicProperty->val,
1006
                                         esxVI_Type_Short) < 0) {
M
Matthias Bolte 已提交
1007
                goto cleanup;
1008 1009 1010 1011
            }

            cpuInfo_numCpuThreads = dynamicProperty->val->int16;
        } else if (STREQ(dynamicProperty->name, "hardware.memorySize")) {
1012
            if (esxVI_AnyType_ExpectType(dynamicProperty->val,
1013
                                         esxVI_Type_Long) < 0) {
M
Matthias Bolte 已提交
1014
                goto cleanup;
1015 1016 1017 1018 1019
            }

            memorySize = dynamicProperty->val->int64;
        } else if (STREQ(dynamicProperty->name,
                         "hardware.numaInfo.numNodes")) {
1020
            if (esxVI_AnyType_ExpectType(dynamicProperty->val,
1021
                                         esxVI_Type_Int) < 0) {
M
Matthias Bolte 已提交
1022
                goto cleanup;
1023 1024 1025 1026 1027
            }

            numaInfo_numNodes = dynamicProperty->val->int32;
        } else if (STREQ(dynamicProperty->name,
                         "summary.hardware.cpuModel")) {
1028
            if (esxVI_AnyType_ExpectType(dynamicProperty->val,
1029
                                         esxVI_Type_String) < 0) {
M
Matthias Bolte 已提交
1030
                goto cleanup;
1031 1032 1033 1034 1035 1036
            }

            ptr = dynamicProperty->val->string;

            /* Strip the string to fit more relevant information in 32 chars */
            while (*ptr != '\0') {
M
Matthias Bolte 已提交
1037 1038
                if (STRPREFIX(ptr, "  ")) {
                    memmove(ptr, ptr + 1, strlen(ptr + 1) + 1);
1039
                    continue;
1040
                } else if (STRPREFIX(ptr, "(R)") || STRPREFIX(ptr, "(C)")) {
M
Matthias Bolte 已提交
1041
                    memmove(ptr, ptr + 3, strlen(ptr + 3) + 1);
1042
                    continue;
1043 1044 1045
                } else if (STRPREFIX(ptr, "(TM)")) {
                    memmove(ptr, ptr + 4, strlen(ptr + 4) + 1);
                    continue;
1046 1047 1048 1049 1050
                }

                ++ptr;
            }

C
Chris Lalancette 已提交
1051 1052 1053
            if (virStrncpy(nodeinfo->model, dynamicProperty->val->string,
                           sizeof(nodeinfo->model) - 1,
                           sizeof(nodeinfo->model)) == NULL) {
1054
                ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
1055
                          _("CPU Model %s too long for destination"),
C
Chris Lalancette 已提交
1056
                          dynamicProperty->val->string);
M
Matthias Bolte 已提交
1057
                goto cleanup;
C
Chris Lalancette 已提交
1058
            }
1059 1060 1061 1062 1063 1064 1065
        } else {
            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
        }
    }

    nodeinfo->memory = memorySize / 1024; /* Scale from bytes to kilobytes */
    nodeinfo->cpus = cpuInfo_numCpuCores;
1066
    nodeinfo->mhz = cpuInfo_hz / (1000 * 1000); /* Scale from hz to mhz */
1067 1068 1069 1070 1071 1072 1073 1074 1075
    nodeinfo->nodes = numaInfo_numNodes;
    nodeinfo->sockets = cpuInfo_numCpuPackages;
    nodeinfo->cores = cpuInfo_numCpuPackages > 0
                        ? cpuInfo_numCpuCores / cpuInfo_numCpuPackages
                        : 0;
    nodeinfo->threads = cpuInfo_numCpuCores > 0
                          ? cpuInfo_numCpuThreads / cpuInfo_numCpuCores
                          : 0;

M
Matthias Bolte 已提交
1076 1077
    result = 0;

1078 1079 1080 1081 1082 1083 1084 1085 1086
  cleanup:
    esxVI_String_Free(&propertyNameList);
    esxVI_ObjectContent_Free(&hostSystem);

    return result;
}



1087 1088 1089
static char *
esxGetCapabilities(virConnectPtr conn)
{
M
Matthias Bolte 已提交
1090
    esxPrivate *priv = conn->privateData;
M
Matthias Bolte 已提交
1091
    char *xml = virCapabilitiesFormatXML(priv->caps);
1092 1093

    if (xml == NULL) {
1094
        virReportOOMError();
1095 1096 1097 1098 1099 1100 1101 1102
        return NULL;
    }

    return xml;
}



1103 1104 1105
static int
esxListDomains(virConnectPtr conn, int *ids, int maxids)
{
M
Matthias Bolte 已提交
1106
    bool success = false;
M
Matthias Bolte 已提交
1107
    esxPrivate *priv = conn->privateData;
1108 1109 1110 1111 1112 1113 1114
    esxVI_ObjectContent *virtualMachineList = NULL;
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_String *propertyNameList = NULL;
    esxVI_VirtualMachinePowerState powerState;
    int count = 0;

    if (ids == NULL || maxids < 0) {
1115 1116
        ESX_ERROR(VIR_ERR_INVALID_ARG, "%s", _("Invalid argument"));
        return -1;
1117 1118 1119 1120 1121 1122
    }

    if (maxids == 0) {
        return 0;
    }

1123
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
1124
        return -1;
1125 1126
    }

1127
    if (esxVI_String_AppendValueToList(&propertyNameList,
1128
                                       "runtime.powerState") < 0 ||
1129
        esxVI_LookupObjectContentByType(priv->primary, priv->primary->vmFolder,
1130 1131 1132
                                        "VirtualMachine", propertyNameList,
                                        esxVI_Boolean_True,
                                        &virtualMachineList) < 0) {
M
Matthias Bolte 已提交
1133
        goto cleanup;
1134 1135 1136 1137
    }

    for (virtualMachine = virtualMachineList; virtualMachine != NULL;
         virtualMachine = virtualMachine->_next) {
1138
        if (esxVI_GetVirtualMachinePowerState(virtualMachine,
1139
                                              &powerState) < 0) {
M
Matthias Bolte 已提交
1140
            goto cleanup;
1141 1142 1143 1144 1145 1146 1147 1148 1149
        }

        if (powerState != esxVI_VirtualMachinePowerState_PoweredOn) {
            continue;
        }

        if (esxUtil_ParseVirtualMachineIDString(virtualMachine->obj->value,
                                                &ids[count]) < 0 ||
            ids[count] <= 0) {
1150
            ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
1151
                      _("Failed to parse positive integer from '%s'"),
1152
                      virtualMachine->obj->value);
M
Matthias Bolte 已提交
1153
            goto cleanup;
1154 1155 1156 1157 1158 1159 1160 1161 1162
        }

        count++;

        if (count >= maxids) {
            break;
        }
    }

M
Matthias Bolte 已提交
1163 1164
    success = true;

1165 1166 1167 1168
  cleanup:
    esxVI_String_Free(&propertyNameList);
    esxVI_ObjectContent_Free(&virtualMachineList);

M
Matthias Bolte 已提交
1169
    return success ? count : -1;
1170 1171 1172 1173 1174 1175 1176
}



static int
esxNumberOfDomains(virConnectPtr conn)
{
M
Matthias Bolte 已提交
1177
    esxPrivate *priv = conn->privateData;
1178

1179
    if (esxVI_EnsureSession(priv->primary) < 0) {
1180 1181 1182
        return -1;
    }

1183
    return esxVI_LookupNumberOfDomainsByPowerState
1184
             (priv->primary, esxVI_VirtualMachinePowerState_PoweredOn,
1185 1186 1187 1188 1189 1190 1191 1192
              esxVI_Boolean_False);
}



static virDomainPtr
esxDomainLookupByID(virConnectPtr conn, int id)
{
M
Matthias Bolte 已提交
1193
    esxPrivate *priv = conn->privateData;
1194 1195 1196 1197
    esxVI_String *propertyNameList = NULL;
    esxVI_ObjectContent *virtualMachineList = NULL;
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_VirtualMachinePowerState powerState;
M
Matthias Bolte 已提交
1198 1199 1200
    int id_candidate = -1;
    char *name_candidate = NULL;
    unsigned char uuid_candidate[VIR_UUID_BUFLEN];
1201 1202
    virDomainPtr domain = NULL;

1203
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
1204
        return NULL;
1205 1206
    }

1207
    if (esxVI_String_AppendValueListToList(&propertyNameList,
1208
                                           "configStatus\0"
1209 1210
                                           "name\0"
                                           "runtime.powerState\0"
1211
                                           "config.uuid\0") < 0 ||
1212
        esxVI_LookupObjectContentByType(priv->primary, priv->primary->vmFolder,
1213 1214 1215
                                        "VirtualMachine", propertyNameList,
                                        esxVI_Boolean_True,
                                        &virtualMachineList) < 0) {
M
Matthias Bolte 已提交
1216
        goto cleanup;
1217 1218 1219 1220
    }

    for (virtualMachine = virtualMachineList; virtualMachine != NULL;
         virtualMachine = virtualMachine->_next) {
1221
        if (esxVI_GetVirtualMachinePowerState(virtualMachine,
1222
                                              &powerState) < 0) {
M
Matthias Bolte 已提交
1223
            goto cleanup;
1224 1225 1226 1227 1228 1229 1230
        }

        /* Only running/suspended domains have an ID != -1 */
        if (powerState == esxVI_VirtualMachinePowerState_PoweredOff) {
            continue;
        }

M
Matthias Bolte 已提交
1231
        VIR_FREE(name_candidate);
1232

1233
        if (esxVI_GetVirtualMachineIdentity(virtualMachine,
M
Matthias Bolte 已提交
1234 1235
                                            &id_candidate, &name_candidate,
                                            uuid_candidate) < 0) {
M
Matthias Bolte 已提交
1236
            goto cleanup;
1237 1238
        }

M
Matthias Bolte 已提交
1239
        if (id != id_candidate) {
1240 1241 1242
            continue;
        }

M
Matthias Bolte 已提交
1243
        domain = virGetDomain(conn, name_candidate, uuid_candidate);
1244 1245

        if (domain == NULL) {
M
Matthias Bolte 已提交
1246
            goto cleanup;
1247 1248 1249 1250 1251 1252 1253 1254
        }

        domain->id = id;

        break;
    }

    if (domain == NULL) {
1255
        ESX_ERROR(VIR_ERR_NO_DOMAIN, _("No domain with ID %d"), id);
1256 1257 1258 1259 1260
    }

  cleanup:
    esxVI_String_Free(&propertyNameList);
    esxVI_ObjectContent_Free(&virtualMachineList);
M
Matthias Bolte 已提交
1261
    VIR_FREE(name_candidate);
1262 1263 1264 1265 1266 1267 1268 1269 1270

    return domain;
}



static virDomainPtr
esxDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
{
M
Matthias Bolte 已提交
1271
    esxPrivate *priv = conn->privateData;
1272 1273 1274
    esxVI_String *propertyNameList = NULL;
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_VirtualMachinePowerState powerState;
1275 1276
    int id = -1;
    char *name = NULL;
1277 1278
    virDomainPtr domain = NULL;

1279
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
1280
        return NULL;
1281 1282
    }

1283
    if (esxVI_String_AppendValueListToList(&propertyNameList,
1284
                                           "name\0"
1285
                                           "runtime.powerState\0") < 0 ||
1286
        esxVI_LookupVirtualMachineByUuid(priv->primary, uuid, propertyNameList,
1287
                                         &virtualMachine,
M
Matthias Bolte 已提交
1288
                                         esxVI_Occurrence_RequiredItem) < 0 ||
1289 1290
        esxVI_GetVirtualMachineIdentity(virtualMachine, &id, &name, NULL) < 0 ||
        esxVI_GetVirtualMachinePowerState(virtualMachine, &powerState) < 0) {
M
Matthias Bolte 已提交
1291
        goto cleanup;
1292 1293
    }

1294
    domain = virGetDomain(conn, name, uuid);
1295 1296

    if (domain == NULL) {
M
Matthias Bolte 已提交
1297
        goto cleanup;
1298
    }
1299

1300 1301 1302 1303 1304
    /* Only running/suspended virtual machines have an ID != -1 */
    if (powerState != esxVI_VirtualMachinePowerState_PoweredOff) {
        domain->id = id;
    } else {
        domain->id = -1;
1305 1306 1307 1308
    }

  cleanup:
    esxVI_String_Free(&propertyNameList);
1309 1310
    esxVI_ObjectContent_Free(&virtualMachine);
    VIR_FREE(name);
1311 1312 1313 1314 1315 1316 1317 1318 1319

    return domain;
}



static virDomainPtr
esxDomainLookupByName(virConnectPtr conn, const char *name)
{
M
Matthias Bolte 已提交
1320
    esxPrivate *priv = conn->privateData;
1321 1322 1323
    esxVI_String *propertyNameList = NULL;
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_VirtualMachinePowerState powerState;
1324 1325
    int id = -1;
    unsigned char uuid[VIR_UUID_BUFLEN];
1326 1327
    virDomainPtr domain = NULL;

1328
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
1329
        return NULL;
1330 1331
    }

1332
    if (esxVI_String_AppendValueListToList(&propertyNameList,
1333
                                           "configStatus\0"
1334
                                           "runtime.powerState\0"
1335
                                           "config.uuid\0") < 0 ||
1336
        esxVI_LookupVirtualMachineByName(priv->primary, name, propertyNameList,
1337 1338
                                         &virtualMachine,
                                         esxVI_Occurrence_OptionalItem) < 0) {
M
Matthias Bolte 已提交
1339
        goto cleanup;
1340 1341
    }

1342
    if (virtualMachine == NULL) {
1343
        ESX_ERROR(VIR_ERR_NO_DOMAIN, _("No domain with name '%s'"), name);
M
Matthias Bolte 已提交
1344
        goto cleanup;
1345
    }
1346 1347


M
Matthias Bolte 已提交
1348 1349 1350
    if (esxVI_GetVirtualMachineIdentity(virtualMachine, &id, NULL, uuid) < 0 ||
        esxVI_GetVirtualMachinePowerState(virtualMachine, &powerState) < 0) {
        goto cleanup;
1351
    }
1352

1353
    domain = virGetDomain(conn, name, uuid);
1354

1355
    if (domain == NULL) {
M
Matthias Bolte 已提交
1356
        goto cleanup;
1357 1358
    }

1359 1360 1361 1362 1363
    /* Only running/suspended virtual machines have an ID != -1 */
    if (powerState != esxVI_VirtualMachinePowerState_PoweredOff) {
        domain->id = id;
    } else {
        domain->id = -1;
1364 1365 1366 1367
    }

  cleanup:
    esxVI_String_Free(&propertyNameList);
1368
    esxVI_ObjectContent_Free(&virtualMachine);
1369 1370 1371 1372 1373 1374 1375 1376 1377

    return domain;
}



static int
esxDomainSuspend(virDomainPtr domain)
{
M
Matthias Bolte 已提交
1378
    int result = -1;
M
Matthias Bolte 已提交
1379
    esxPrivate *priv = domain->conn->privateData;
1380 1381 1382 1383 1384 1385
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_String *propertyNameList = NULL;
    esxVI_VirtualMachinePowerState powerState;
    esxVI_ManagedObjectReference *task = NULL;
    esxVI_TaskInfoState taskInfoState;

1386
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
1387
        return -1;
1388 1389
    }

1390
    if (esxVI_String_AppendValueToList(&propertyNameList,
1391
                                       "runtime.powerState") < 0 ||
1392
        esxVI_LookupVirtualMachineByUuidAndPrepareForTask
1393
          (priv->primary, domain->uuid, propertyNameList, &virtualMachine,
1394 1395
           priv->autoAnswer) < 0 ||
        esxVI_GetVirtualMachinePowerState(virtualMachine, &powerState) < 0) {
M
Matthias Bolte 已提交
1396
        goto cleanup;
1397 1398 1399
    }

    if (powerState != esxVI_VirtualMachinePowerState_PoweredOn) {
1400 1401
        ESX_ERROR(VIR_ERR_OPERATION_INVALID, "%s",
                  _("Domain is not powered on"));
M
Matthias Bolte 已提交
1402
        goto cleanup;
1403 1404
    }

1405 1406
    if (esxVI_SuspendVM_Task(priv->primary, virtualMachine->obj, &task) < 0 ||
        esxVI_WaitForTaskCompletion(priv->primary, task, domain->uuid,
1407
                                    esxVI_Occurrence_RequiredItem,
1408
                                    priv->autoAnswer, &taskInfoState) < 0) {
M
Matthias Bolte 已提交
1409
        goto cleanup;
1410 1411 1412
    }

    if (taskInfoState != esxVI_TaskInfoState_Success) {
1413
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not suspend domain"));
M
Matthias Bolte 已提交
1414
        goto cleanup;
1415 1416
    }

M
Matthias Bolte 已提交
1417 1418
    result = 0;

1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431
  cleanup:
    esxVI_ObjectContent_Free(&virtualMachine);
    esxVI_String_Free(&propertyNameList);
    esxVI_ManagedObjectReference_Free(&task);

    return result;
}



static int
esxDomainResume(virDomainPtr domain)
{
M
Matthias Bolte 已提交
1432
    int result = -1;
M
Matthias Bolte 已提交
1433
    esxPrivate *priv = domain->conn->privateData;
1434 1435 1436 1437 1438 1439
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_String *propertyNameList = NULL;
    esxVI_VirtualMachinePowerState powerState;
    esxVI_ManagedObjectReference *task = NULL;
    esxVI_TaskInfoState taskInfoState;

1440
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
1441
        return -1;
1442 1443
    }

1444
    if (esxVI_String_AppendValueToList(&propertyNameList,
1445
                                       "runtime.powerState") < 0 ||
1446
        esxVI_LookupVirtualMachineByUuidAndPrepareForTask
1447
          (priv->primary, domain->uuid, propertyNameList, &virtualMachine,
1448 1449
           priv->autoAnswer) < 0 ||
        esxVI_GetVirtualMachinePowerState(virtualMachine, &powerState) < 0) {
M
Matthias Bolte 已提交
1450
        goto cleanup;
1451 1452 1453
    }

    if (powerState != esxVI_VirtualMachinePowerState_Suspended) {
1454
        ESX_ERROR(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not suspended"));
M
Matthias Bolte 已提交
1455
        goto cleanup;
1456 1457
    }

1458
    if (esxVI_PowerOnVM_Task(priv->primary, virtualMachine->obj, NULL,
1459
                             &task) < 0 ||
1460
        esxVI_WaitForTaskCompletion(priv->primary, task, domain->uuid,
1461
                                    esxVI_Occurrence_RequiredItem,
1462
                                    priv->autoAnswer, &taskInfoState) < 0) {
M
Matthias Bolte 已提交
1463
        goto cleanup;
1464 1465 1466
    }

    if (taskInfoState != esxVI_TaskInfoState_Success) {
1467
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not resume domain"));
M
Matthias Bolte 已提交
1468
        goto cleanup;
1469 1470
    }

M
Matthias Bolte 已提交
1471 1472
    result = 0;

1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485
  cleanup:
    esxVI_ObjectContent_Free(&virtualMachine);
    esxVI_String_Free(&propertyNameList);
    esxVI_ManagedObjectReference_Free(&task);

    return result;
}



static int
esxDomainShutdown(virDomainPtr domain)
{
M
Matthias Bolte 已提交
1486
    int result = -1;
M
Matthias Bolte 已提交
1487
    esxPrivate *priv = domain->conn->privateData;
1488 1489 1490 1491
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_String *propertyNameList = NULL;
    esxVI_VirtualMachinePowerState powerState;

1492
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
1493
        return -1;
1494 1495
    }

1496
    if (esxVI_String_AppendValueToList(&propertyNameList,
1497
                                       "runtime.powerState") < 0 ||
1498
        esxVI_LookupVirtualMachineByUuid(priv->primary, domain->uuid,
1499
                                         propertyNameList, &virtualMachine,
M
Matthias Bolte 已提交
1500
                                         esxVI_Occurrence_RequiredItem) < 0 ||
1501
        esxVI_GetVirtualMachinePowerState(virtualMachine, &powerState) < 0) {
M
Matthias Bolte 已提交
1502
        goto cleanup;
1503 1504 1505
    }

    if (powerState != esxVI_VirtualMachinePowerState_PoweredOn) {
1506 1507
        ESX_ERROR(VIR_ERR_OPERATION_INVALID, "%s",
                  _("Domain is not powered on"));
M
Matthias Bolte 已提交
1508
        goto cleanup;
1509 1510
    }

1511
    if (esxVI_ShutdownGuest(priv->primary, virtualMachine->obj) < 0) {
M
Matthias Bolte 已提交
1512
        goto cleanup;
1513 1514
    }

M
Matthias Bolte 已提交
1515 1516
    result = 0;

1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528
  cleanup:
    esxVI_ObjectContent_Free(&virtualMachine);
    esxVI_String_Free(&propertyNameList);

    return result;
}



static int
esxDomainReboot(virDomainPtr domain, unsigned int flags ATTRIBUTE_UNUSED)
{
M
Matthias Bolte 已提交
1529
    int result = -1;
M
Matthias Bolte 已提交
1530
    esxPrivate *priv = domain->conn->privateData;
1531 1532 1533 1534
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_String *propertyNameList = NULL;
    esxVI_VirtualMachinePowerState powerState;

1535
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
1536
        return -1;
1537 1538
    }

1539
    if (esxVI_String_AppendValueToList(&propertyNameList,
1540
                                       "runtime.powerState") < 0 ||
1541
        esxVI_LookupVirtualMachineByUuid(priv->primary, domain->uuid,
1542
                                         propertyNameList, &virtualMachine,
M
Matthias Bolte 已提交
1543
                                         esxVI_Occurrence_RequiredItem) < 0 ||
1544
        esxVI_GetVirtualMachinePowerState(virtualMachine, &powerState) < 0) {
M
Matthias Bolte 已提交
1545
        goto cleanup;
1546 1547 1548
    }

    if (powerState != esxVI_VirtualMachinePowerState_PoweredOn) {
1549 1550
        ESX_ERROR(VIR_ERR_OPERATION_INVALID, "%s",
                  _("Domain is not powered on"));
M
Matthias Bolte 已提交
1551
        goto cleanup;
1552 1553
    }

1554
    if (esxVI_RebootGuest(priv->primary, virtualMachine->obj) < 0) {
M
Matthias Bolte 已提交
1555
        goto cleanup;
1556 1557
    }

M
Matthias Bolte 已提交
1558 1559
    result = 0;

1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571
  cleanup:
    esxVI_ObjectContent_Free(&virtualMachine);
    esxVI_String_Free(&propertyNameList);

    return result;
}



static int
esxDomainDestroy(virDomainPtr domain)
{
M
Matthias Bolte 已提交
1572
    int result = -1;
M
Matthias Bolte 已提交
1573
    esxPrivate *priv = domain->conn->privateData;
1574
    esxVI_Context *ctx = NULL;
1575 1576 1577 1578 1579 1580
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_String *propertyNameList = NULL;
    esxVI_VirtualMachinePowerState powerState;
    esxVI_ManagedObjectReference *task = NULL;
    esxVI_TaskInfoState taskInfoState;

1581 1582 1583 1584 1585 1586
    if (priv->vCenter != NULL) {
        ctx = priv->vCenter;
    } else {
        ctx = priv->host;
    }

1587
    if (esxVI_EnsureSession(ctx) < 0) {
M
Matthias Bolte 已提交
1588
        return -1;
1589 1590
    }

1591
    if (esxVI_String_AppendValueToList(&propertyNameList,
1592
                                       "runtime.powerState") < 0 ||
1593
        esxVI_LookupVirtualMachineByUuidAndPrepareForTask
1594
          (ctx, domain->uuid, propertyNameList, &virtualMachine,
1595
           priv->autoAnswer) < 0 ||
1596
        esxVI_GetVirtualMachinePowerState(virtualMachine, &powerState) < 0) {
M
Matthias Bolte 已提交
1597
        goto cleanup;
1598 1599 1600
    }

    if (powerState != esxVI_VirtualMachinePowerState_PoweredOn) {
1601 1602
        ESX_ERROR(VIR_ERR_OPERATION_INVALID, "%s",
                  _("Domain is not powered on"));
M
Matthias Bolte 已提交
1603
        goto cleanup;
1604 1605
    }

1606
    if (esxVI_PowerOffVM_Task(ctx, virtualMachine->obj, &task) < 0 ||
1607 1608 1609
        esxVI_WaitForTaskCompletion(ctx, task, domain->uuid,
                                    esxVI_Occurrence_RequiredItem,
                                    priv->autoAnswer, &taskInfoState) < 0) {
M
Matthias Bolte 已提交
1610
        goto cleanup;
1611 1612 1613
    }

    if (taskInfoState != esxVI_TaskInfoState_Success) {
1614
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not destroy domain"));
M
Matthias Bolte 已提交
1615
        goto cleanup;
1616 1617
    }

1618
    domain->id = -1;
M
Matthias Bolte 已提交
1619 1620
    result = 0;

1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631
  cleanup:
    esxVI_ObjectContent_Free(&virtualMachine);
    esxVI_String_Free(&propertyNameList);
    esxVI_ManagedObjectReference_Free(&task);

    return result;
}



static char *
1632
esxDomainGetOSType(virDomainPtr domain ATTRIBUTE_UNUSED)
1633
{
1634 1635 1636
    char *osType = strdup("hvm");

    if (osType == NULL) {
1637
        virReportOOMError();
1638 1639 1640 1641
        return NULL;
    }

    return osType;
1642 1643 1644 1645 1646 1647 1648
}



static unsigned long
esxDomainGetMaxMemory(virDomainPtr domain)
{
M
Matthias Bolte 已提交
1649
    esxPrivate *priv = domain->conn->privateData;
1650 1651 1652 1653 1654
    esxVI_String *propertyNameList = NULL;
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_DynamicProperty *dynamicProperty = NULL;
    unsigned long memoryMB = 0;

1655
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
1656
        return 0;
1657 1658
    }

1659
    if (esxVI_String_AppendValueToList(&propertyNameList,
1660
                                       "config.hardware.memoryMB") < 0 ||
1661
        esxVI_LookupVirtualMachineByUuid(priv->primary, domain->uuid,
1662
                                         propertyNameList, &virtualMachine,
M
Matthias Bolte 已提交
1663
                                         esxVI_Occurrence_RequiredItem) < 0) {
M
Matthias Bolte 已提交
1664
        goto cleanup;
1665 1666 1667 1668 1669
    }

    for (dynamicProperty = virtualMachine->propSet; dynamicProperty != NULL;
         dynamicProperty = dynamicProperty->_next) {
        if (STREQ(dynamicProperty->name, "config.hardware.memoryMB")) {
1670
            if (esxVI_AnyType_ExpectType(dynamicProperty->val,
1671
                                         esxVI_Type_Int) < 0) {
M
Matthias Bolte 已提交
1672
                goto cleanup;
1673 1674 1675
            }

            if (dynamicProperty->val->int32 < 0) {
1676 1677
                ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
                          _("Got invalid memory size %d"),
1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700
                          dynamicProperty->val->int32);
            } else {
                memoryMB = dynamicProperty->val->int32;
            }

            break;
        } else {
            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
        }
    }

  cleanup:
    esxVI_String_Free(&propertyNameList);
    esxVI_ObjectContent_Free(&virtualMachine);

    return memoryMB * 1024; /* Scale from megabyte to kilobyte */
}



static int
esxDomainSetMaxMemory(virDomainPtr domain, unsigned long memory)
{
M
Matthias Bolte 已提交
1701
    int result = -1;
M
Matthias Bolte 已提交
1702
    esxPrivate *priv = domain->conn->privateData;
1703 1704 1705 1706 1707
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_VirtualMachineConfigSpec *spec = NULL;
    esxVI_ManagedObjectReference *task = NULL;
    esxVI_TaskInfoState taskInfoState;

1708
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
1709
        return -1;
1710 1711
    }

1712
    if (esxVI_LookupVirtualMachineByUuidAndPrepareForTask
1713
          (priv->primary, domain->uuid, NULL, &virtualMachine,
1714
           priv->autoAnswer) < 0 ||
1715 1716
        esxVI_VirtualMachineConfigSpec_Alloc(&spec) < 0 ||
        esxVI_Long_Alloc(&spec->memoryMB) < 0) {
M
Matthias Bolte 已提交
1717
        goto cleanup;
1718 1719 1720 1721 1722
    }

    spec->memoryMB->value =
      memory / 1024; /* Scale from kilobytes to megabytes */

1723
    if (esxVI_ReconfigVM_Task(priv->primary, virtualMachine->obj, spec,
1724
                              &task) < 0 ||
1725
        esxVI_WaitForTaskCompletion(priv->primary, task, domain->uuid,
1726
                                    esxVI_Occurrence_RequiredItem,
1727
                                    priv->autoAnswer, &taskInfoState) < 0) {
M
Matthias Bolte 已提交
1728
        goto cleanup;
1729 1730 1731
    }

    if (taskInfoState != esxVI_TaskInfoState_Success) {
1732
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
1733
                  _("Could not set max-memory to %lu kilobytes"), memory);
M
Matthias Bolte 已提交
1734
        goto cleanup;
1735 1736
    }

M
Matthias Bolte 已提交
1737 1738
    result = 0;

1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751
  cleanup:
    esxVI_ObjectContent_Free(&virtualMachine);
    esxVI_VirtualMachineConfigSpec_Free(&spec);
    esxVI_ManagedObjectReference_Free(&task);

    return result;
}



static int
esxDomainSetMemory(virDomainPtr domain, unsigned long memory)
{
M
Matthias Bolte 已提交
1752
    int result = -1;
M
Matthias Bolte 已提交
1753
    esxPrivate *priv = domain->conn->privateData;
1754 1755 1756 1757 1758
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_VirtualMachineConfigSpec *spec = NULL;
    esxVI_ManagedObjectReference *task = NULL;
    esxVI_TaskInfoState taskInfoState;

1759
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
1760
        return -1;
1761 1762
    }

1763
    if (esxVI_LookupVirtualMachineByUuidAndPrepareForTask
1764
          (priv->primary, domain->uuid, NULL, &virtualMachine,
1765
           priv->autoAnswer) < 0 ||
1766 1767 1768
        esxVI_VirtualMachineConfigSpec_Alloc(&spec) < 0 ||
        esxVI_ResourceAllocationInfo_Alloc(&spec->memoryAllocation) < 0 ||
        esxVI_Long_Alloc(&spec->memoryAllocation->limit) < 0) {
M
Matthias Bolte 已提交
1769
        goto cleanup;
1770 1771 1772 1773 1774
    }

    spec->memoryAllocation->limit->value =
      memory / 1024; /* Scale from kilobytes to megabytes */

1775
    if (esxVI_ReconfigVM_Task(priv->primary, virtualMachine->obj, spec,
1776
                              &task) < 0 ||
1777
        esxVI_WaitForTaskCompletion(priv->primary, task, domain->uuid,
1778
                                    esxVI_Occurrence_RequiredItem,
1779
                                    priv->autoAnswer, &taskInfoState) < 0) {
M
Matthias Bolte 已提交
1780
        goto cleanup;
1781 1782 1783
    }

    if (taskInfoState != esxVI_TaskInfoState_Success) {
1784
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
1785
                  _("Could not set memory to %lu kilobytes"), memory);
M
Matthias Bolte 已提交
1786
        goto cleanup;
1787 1788
    }

M
Matthias Bolte 已提交
1789 1790
    result = 0;

1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803
  cleanup:
    esxVI_ObjectContent_Free(&virtualMachine);
    esxVI_VirtualMachineConfigSpec_Free(&spec);
    esxVI_ManagedObjectReference_Free(&task);

    return result;
}



static int
esxDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
{
M
Matthias Bolte 已提交
1804
    int result = -1;
M
Matthias Bolte 已提交
1805
    esxPrivate *priv = domain->conn->privateData;
1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817
    esxVI_String *propertyNameList = NULL;
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_DynamicProperty *dynamicProperty = NULL;
    esxVI_VirtualMachinePowerState powerState;
    int64_t memory_limit = -1;
    esxVI_PerfMetricId *perfMetricId = NULL;
    esxVI_PerfMetricId *perfMetricIdList = NULL;
    esxVI_Int *counterId = NULL;
    esxVI_Int *counterIdList = NULL;
    esxVI_PerfCounterInfo *perfCounterInfo = NULL;
    esxVI_PerfCounterInfo *perfCounterInfoList = NULL;
    esxVI_PerfQuerySpec *querySpec = NULL;
1818 1819
    esxVI_PerfEntityMetricBase *perfEntityMetricBase = NULL;
    esxVI_PerfEntityMetricBase *perfEntityMetricBaseList = NULL;
1820 1821 1822 1823
    esxVI_PerfEntityMetric *perfEntityMetric = NULL;
    esxVI_PerfMetricIntSeries *perfMetricIntSeries = NULL;
    esxVI_Long *value = NULL;

M
Matthias Bolte 已提交
1824 1825
    memset(info, 0, sizeof (*info));

1826
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
1827
        return -1;
1828 1829
    }

1830
    if (esxVI_String_AppendValueListToList(&propertyNameList,
1831 1832 1833 1834
                                           "runtime.powerState\0"
                                           "config.hardware.memoryMB\0"
                                           "config.hardware.numCPU\0"
                                           "config.memoryAllocation.limit\0") < 0 ||
1835
        esxVI_LookupVirtualMachineByUuid(priv->primary, domain->uuid,
1836
                                         propertyNameList, &virtualMachine,
M
Matthias Bolte 已提交
1837
                                         esxVI_Occurrence_RequiredItem) < 0) {
M
Matthias Bolte 已提交
1838
        goto cleanup;
1839 1840 1841 1842 1843 1844 1845 1846
    }

    info->state = VIR_DOMAIN_NOSTATE;

    for (dynamicProperty = virtualMachine->propSet; dynamicProperty != NULL;
         dynamicProperty = dynamicProperty->_next) {
        if (STREQ(dynamicProperty->name, "runtime.powerState")) {
            if (esxVI_VirtualMachinePowerState_CastFromAnyType
1847
                  (dynamicProperty->val, &powerState) < 0) {
M
Matthias Bolte 已提交
1848
                goto cleanup;
1849 1850
            }

1851 1852
            info->state = esxVI_VirtualMachinePowerState_ConvertToLibvirt
                            (powerState);
1853
        } else if (STREQ(dynamicProperty->name, "config.hardware.memoryMB")) {
1854
            if (esxVI_AnyType_ExpectType(dynamicProperty->val,
1855
                                         esxVI_Type_Int) < 0) {
M
Matthias Bolte 已提交
1856
                goto cleanup;
1857 1858 1859 1860
            }

            info->maxMem = dynamicProperty->val->int32 * 1024; /* Scale from megabyte to kilobyte */
        } else if (STREQ(dynamicProperty->name, "config.hardware.numCPU")) {
1861
            if (esxVI_AnyType_ExpectType(dynamicProperty->val,
1862
                                         esxVI_Type_Int) < 0) {
M
Matthias Bolte 已提交
1863
                goto cleanup;
1864 1865 1866 1867 1868
            }

            info->nrVirtCpu = dynamicProperty->val->int32;
        } else if (STREQ(dynamicProperty->name,
                         "config.memoryAllocation.limit")) {
1869
            if (esxVI_AnyType_ExpectType(dynamicProperty->val,
1870
                                         esxVI_Type_Long) < 0) {
M
Matthias Bolte 已提交
1871
                goto cleanup;
1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887
            }

            memory_limit = dynamicProperty->val->int64;

            if (memory_limit > 0) {
                memory_limit *= 1024; /* Scale from megabyte to kilobyte */
            }
        } else {
            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
        }
    }

    /* memory_limit < 0 means no memory limit is set */
    info->memory = memory_limit < 0 ? info->maxMem : memory_limit;

    /* Verify the cached 'used CPU time' performance counter ID */
1888 1889 1890 1891 1892 1893
    /* FIXME: Currently no host for a vpx:// connection */
    if (priv->host != NULL) {
        if (info->state == VIR_DOMAIN_RUNNING && priv->usedCpuTimeCounterId >= 0) {
            if (esxVI_Int_Alloc(&counterId) < 0) {
                goto cleanup;
            }
1894

1895
            counterId->value = priv->usedCpuTimeCounterId;
1896

1897 1898 1899
            if (esxVI_Int_AppendToList(&counterIdList, counterId) < 0) {
                goto cleanup;
            }
1900

1901 1902 1903 1904
            if (esxVI_QueryPerfCounter(priv->host, counterIdList,
                                       &perfCounterInfo) < 0) {
                goto cleanup;
            }
1905

1906 1907 1908 1909 1910
            if (STRNEQ(perfCounterInfo->groupInfo->key, "cpu") ||
                STRNEQ(perfCounterInfo->nameInfo->key, "used") ||
                STRNEQ(perfCounterInfo->unitInfo->key, "millisecond")) {
                VIR_DEBUG("Cached usedCpuTimeCounterId %d is invalid",
                          priv->usedCpuTimeCounterId);
1911

1912 1913 1914 1915 1916
                priv->usedCpuTimeCounterId = -1;
            }

            esxVI_Int_Free(&counterIdList);
            esxVI_PerfCounterInfo_Free(&perfCounterInfo);
1917 1918
        }

1919 1920 1921 1922 1923 1924 1925 1926 1927 1928
        /*
         * Query the PerformanceManager for the 'used CPU time' performance
         * counter ID and cache it, if it's not already cached.
         */
        if (info->state == VIR_DOMAIN_RUNNING && priv->usedCpuTimeCounterId < 0) {
            if (esxVI_QueryAvailablePerfMetric(priv->host, virtualMachine->obj,
                                               NULL, NULL, NULL,
                                               &perfMetricIdList) < 0) {
                goto cleanup;
            }
1929

1930 1931 1932 1933
            for (perfMetricId = perfMetricIdList; perfMetricId != NULL;
                 perfMetricId = perfMetricId->_next) {
                VIR_DEBUG("perfMetricId counterId %d, instance '%s'",
                          perfMetricId->counterId->value, perfMetricId->instance);
1934

1935
                counterId = NULL;
1936

1937 1938 1939 1940 1941
                if (esxVI_Int_DeepCopy(&counterId, perfMetricId->counterId) < 0 ||
                    esxVI_Int_AppendToList(&counterIdList, counterId) < 0) {
                    goto cleanup;
                }
            }
1942

1943 1944
            if (esxVI_QueryPerfCounter(priv->host, counterIdList,
                                       &perfCounterInfoList) < 0) {
M
Matthias Bolte 已提交
1945
                goto cleanup;
1946 1947
            }

1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964
            for (perfCounterInfo = perfCounterInfoList; perfCounterInfo != NULL;
                 perfCounterInfo = perfCounterInfo->_next) {
                VIR_DEBUG("perfCounterInfo key %d, nameInfo '%s', groupInfo '%s', "
                          "unitInfo '%s', rollupType %d, statsType %d",
                          perfCounterInfo->key->value,
                          perfCounterInfo->nameInfo->key,
                          perfCounterInfo->groupInfo->key,
                          perfCounterInfo->unitInfo->key,
                          perfCounterInfo->rollupType,
                          perfCounterInfo->statsType);

                if (STREQ(perfCounterInfo->groupInfo->key, "cpu") &&
                    STREQ(perfCounterInfo->nameInfo->key, "used") &&
                    STREQ(perfCounterInfo->unitInfo->key, "millisecond")) {
                    priv->usedCpuTimeCounterId = perfCounterInfo->key->value;
                    break;
                }
1965 1966
            }

1967 1968 1969
            if (priv->usedCpuTimeCounterId < 0) {
                VIR_WARN0("Could not find 'used CPU time' performance counter");
            }
1970 1971
        }

1972 1973 1974 1975 1976 1977
        /*
         * Query the PerformanceManager for the 'used CPU time' performance
         * counter value.
         */
        if (info->state == VIR_DOMAIN_RUNNING && priv->usedCpuTimeCounterId >= 0) {
            VIR_DEBUG("usedCpuTimeCounterId %d BEGIN", priv->usedCpuTimeCounterId);
1978

1979 1980 1981 1982 1983 1984
            if (esxVI_PerfQuerySpec_Alloc(&querySpec) < 0 ||
                esxVI_Int_Alloc(&querySpec->maxSample) < 0 ||
                esxVI_PerfMetricId_Alloc(&querySpec->metricId) < 0 ||
                esxVI_Int_Alloc(&querySpec->metricId->counterId) < 0) {
                goto cleanup;
            }
1985

1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998
            querySpec->entity = virtualMachine->obj;
            querySpec->maxSample->value = 1;
            querySpec->metricId->counterId->value = priv->usedCpuTimeCounterId;
            querySpec->metricId->instance = (char *)"";
            querySpec->format = (char *)"normal";

            if (esxVI_QueryPerf(priv->host, querySpec,
                                &perfEntityMetricBaseList) < 0) {
                querySpec->entity = NULL;
                querySpec->metricId->instance = NULL;
                querySpec->format = NULL;
                goto cleanup;
            }
1999

2000 2001 2002 2003
            for (perfEntityMetricBase = perfEntityMetricBaseList;
                 perfEntityMetricBase != NULL;
                 perfEntityMetricBase = perfEntityMetricBase->_next) {
                VIR_DEBUG0("perfEntityMetric ...");
2004

2005 2006
                perfEntityMetric =
                  esxVI_PerfEntityMetric_DynamicCast(perfEntityMetricBase);
2007

2008 2009 2010
                if (perfMetricIntSeries == NULL) {
                    VIR_ERROR0(_("QueryPerf returned object with unexpected type"));
                }
2011

2012 2013
                perfMetricIntSeries =
                  esxVI_PerfMetricIntSeries_DynamicCast(perfEntityMetric->value);
2014

2015 2016 2017
                if (perfMetricIntSeries == NULL) {
                    VIR_ERROR0(_("QueryPerf returned object with unexpected type"));
                }
2018

2019 2020 2021
                for (; perfMetricIntSeries != NULL;
                     perfMetricIntSeries = perfMetricIntSeries->_next) {
                    VIR_DEBUG0("perfMetricIntSeries ...");
2022

2023 2024 2025 2026 2027
                    for (value = perfMetricIntSeries->value;
                         value != NULL;
                         value = value->_next) {
                        VIR_DEBUG("value %lld", (long long int)value->value);
                    }
2028 2029 2030
                }
            }

2031 2032 2033
            querySpec->entity = NULL;
            querySpec->metricId->instance = NULL;
            querySpec->format = NULL;
2034

2035
            VIR_DEBUG("usedCpuTimeCounterId %d END", priv->usedCpuTimeCounterId);
M
Matthias Bolte 已提交
2036

2037 2038 2039 2040 2041
            /*
             * FIXME: Cannot map between realtive used-cpu-time and absolute
             *        info->cpuTime
             */
        }
2042 2043
    }

M
Matthias Bolte 已提交
2044 2045
    result = 0;

2046 2047 2048 2049 2050 2051 2052
  cleanup:
    esxVI_String_Free(&propertyNameList);
    esxVI_ObjectContent_Free(&virtualMachine);
    esxVI_PerfMetricId_Free(&perfMetricIdList);
    esxVI_Int_Free(&counterIdList);
    esxVI_PerfCounterInfo_Free(&perfCounterInfoList);
    esxVI_PerfQuerySpec_Free(&querySpec);
2053
    esxVI_PerfEntityMetricBase_Free(&perfEntityMetricBaseList);
2054 2055 2056 2057 2058 2059 2060 2061 2062

    return result;
}



static int
esxDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus)
{
M
Matthias Bolte 已提交
2063
    int result = -1;
M
Matthias Bolte 已提交
2064
    esxPrivate *priv = domain->conn->privateData;
M
Matthias Bolte 已提交
2065
    int maxVcpus;
2066 2067 2068 2069 2070 2071
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_VirtualMachineConfigSpec *spec = NULL;
    esxVI_ManagedObjectReference *task = NULL;
    esxVI_TaskInfoState taskInfoState;

    if (nvcpus < 1) {
2072 2073
        ESX_ERROR(VIR_ERR_INVALID_ARG, "%s",
                  _("Requested number of virtual CPUs must at least be 1"));
M
Matthias Bolte 已提交
2074
        return -1;
2075 2076
    }

2077
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
2078
        return -1;
2079 2080
    }

M
Matthias Bolte 已提交
2081
    maxVcpus = esxDomainGetMaxVcpus(domain);
2082

M
Matthias Bolte 已提交
2083
    if (maxVcpus < 0) {
M
Matthias Bolte 已提交
2084
        return -1;
2085 2086
    }

M
Matthias Bolte 已提交
2087
    if (nvcpus > maxVcpus) {
2088
        ESX_ERROR(VIR_ERR_INVALID_ARG,
2089 2090
                  _("Requested number of virtual CPUs is greater than max "
                    "allowable number of virtual CPUs for the domain: %d > %d"),
M
Matthias Bolte 已提交
2091
                  nvcpus, maxVcpus);
M
Matthias Bolte 已提交
2092
        return -1;
2093 2094
    }

2095
    if (esxVI_LookupVirtualMachineByUuidAndPrepareForTask
2096
          (priv->primary, domain->uuid, NULL, &virtualMachine,
2097
           priv->autoAnswer) < 0 ||
2098 2099
        esxVI_VirtualMachineConfigSpec_Alloc(&spec) < 0 ||
        esxVI_Int_Alloc(&spec->numCPUs) < 0) {
M
Matthias Bolte 已提交
2100
        goto cleanup;
2101 2102 2103 2104
    }

    spec->numCPUs->value = nvcpus;

2105
    if (esxVI_ReconfigVM_Task(priv->primary, virtualMachine->obj, spec,
2106
                              &task) < 0 ||
2107
        esxVI_WaitForTaskCompletion(priv->primary, task, domain->uuid,
2108
                                    esxVI_Occurrence_RequiredItem,
2109
                                    priv->autoAnswer, &taskInfoState) < 0) {
M
Matthias Bolte 已提交
2110
        goto cleanup;
2111 2112 2113
    }

    if (taskInfoState != esxVI_TaskInfoState_Success) {
2114
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
2115
                  _("Could not set number of virtual CPUs to %d"), nvcpus);
M
Matthias Bolte 已提交
2116
        goto cleanup;
2117 2118
    }

M
Matthias Bolte 已提交
2119 2120
    result = 0;

2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133
  cleanup:
    esxVI_ObjectContent_Free(&virtualMachine);
    esxVI_VirtualMachineConfigSpec_Free(&spec);
    esxVI_ManagedObjectReference_Free(&task);

    return result;
}



static int
esxDomainGetMaxVcpus(virDomainPtr domain)
{
M
Matthias Bolte 已提交
2134
    esxPrivate *priv = domain->conn->privateData;
2135 2136 2137 2138
    esxVI_String *propertyNameList = NULL;
    esxVI_ObjectContent *hostSystem = NULL;
    esxVI_DynamicProperty *dynamicProperty = NULL;

M
Matthias Bolte 已提交
2139 2140
    if (priv->maxVcpus > 0) {
        return priv->maxVcpus;
2141 2142
    }

M
Matthias Bolte 已提交
2143 2144
    priv->maxVcpus = -1;

2145 2146 2147 2148 2149 2150 2151
    if (priv->host == NULL) {
        /* FIXME: Currently no host for a vpx:// connection */
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                  _("MaxVCPUs value is not available for a vpx:// connection"));
        return -1;
    }

2152
    if (esxVI_EnsureSession(priv->host) < 0) {
M
Matthias Bolte 已提交
2153
        return -1;
2154 2155
    }

2156
    if (esxVI_String_AppendValueToList(&propertyNameList,
2157
                                       "capability.maxSupportedVcpus") < 0 ||
2158 2159 2160
        esxVI_LookupObjectContentByType(priv->host, priv->host->hostFolder,
                                        "HostSystem", propertyNameList,
                                        esxVI_Boolean_True, &hostSystem) < 0) {
M
Matthias Bolte 已提交
2161
        goto cleanup;
2162 2163 2164
    }

    if (hostSystem == NULL) {
2165 2166
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                  _("Could not retrieve the HostSystem object"));
M
Matthias Bolte 已提交
2167
        goto cleanup;
2168 2169 2170 2171 2172
    }

    for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
         dynamicProperty = dynamicProperty->_next) {
        if (STREQ(dynamicProperty->name, "capability.maxSupportedVcpus")) {
2173
            if (esxVI_AnyType_ExpectType(dynamicProperty->val,
2174
                                         esxVI_Type_Int) < 0) {
M
Matthias Bolte 已提交
2175
                goto cleanup;
2176 2177
            }

M
Matthias Bolte 已提交
2178
            priv->maxVcpus = dynamicProperty->val->int32;
2179 2180 2181 2182 2183 2184 2185 2186 2187 2188
            break;
        } else {
            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
        }
    }

  cleanup:
    esxVI_String_Free(&propertyNameList);
    esxVI_ObjectContent_Free(&hostSystem);

M
Matthias Bolte 已提交
2189
    return priv->maxVcpus;
2190 2191 2192 2193 2194 2195 2196
}



static char *
esxDomainDumpXML(virDomainPtr domain, int flags)
{
M
Matthias Bolte 已提交
2197
    esxPrivate *priv = domain->conn->privateData;
2198
    esxVI_String *propertyNameList = NULL;
2199
    esxVI_ObjectContent *datacenter = NULL;
2200 2201 2202
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_DynamicProperty *dynamicProperty = NULL;
    const char *vmPathName = NULL;
2203
    char *datacenterName = NULL;
2204
    char *datastoreName = NULL;
M
Matthias Bolte 已提交
2205 2206
    char *directoryName = NULL;
    char *fileName = NULL;
2207
    virBuffer buffer = VIR_BUFFER_INITIALIZER;
2208 2209 2210 2211 2212
    char *url = NULL;
    char *vmx = NULL;
    virDomainDefPtr def = NULL;
    char *xml = NULL;

2213
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
2214
        return NULL;
2215 2216
    }

2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227
    if (esxVI_String_AppendValueToList(&propertyNameList, "name") < 0 ||
        esxVI_LookupObjectContentByType(priv->primary, priv->primary->datacenter,
                                        "Datacenter", propertyNameList,
                                        esxVI_Boolean_False, &datacenter) < 0 ||
        esxVI_GetStringValue(datacenter, "name", &datacenterName,
                             esxVI_Occurrence_RequiredItem) < 0) {
        goto cleanup;
    }

    esxVI_String_Free(&propertyNameList);

2228
    if (esxVI_String_AppendValueToList(&propertyNameList,
2229
                                       "config.files.vmPathName") < 0 ||
2230
        esxVI_LookupVirtualMachineByUuid(priv->primary, domain->uuid,
2231
                                         propertyNameList, &virtualMachine,
M
Matthias Bolte 已提交
2232
                                         esxVI_Occurrence_RequiredItem) < 0) {
M
Matthias Bolte 已提交
2233
        goto cleanup;
2234 2235 2236 2237 2238
    }

    for (dynamicProperty = virtualMachine->propSet; dynamicProperty != NULL;
         dynamicProperty = dynamicProperty->_next) {
        if (STREQ(dynamicProperty->name, "config.files.vmPathName")) {
2239
            if (esxVI_AnyType_ExpectType(dynamicProperty->val,
2240
                                         esxVI_Type_String) < 0) {
M
Matthias Bolte 已提交
2241
                goto cleanup;
2242 2243 2244 2245 2246 2247 2248
            }

            vmPathName = dynamicProperty->val->string;
            break;
        }
    }

2249 2250
    if (esxUtil_ParseDatastoreRelatedPath(vmPathName, &datastoreName,
                                          &directoryName, &fileName) < 0) {
M
Matthias Bolte 已提交
2251
        goto cleanup;
2252 2253
    }

2254 2255
    virBufferVSprintf(&buffer, "%s://%s:%d/folder/", priv->transport,
                      domain->conn->uri->server, domain->conn->uri->port);
M
Matthias Bolte 已提交
2256 2257 2258 2259 2260 2261 2262

    if (directoryName != NULL) {
        virBufferURIEncodeString(&buffer, directoryName);
        virBufferAddChar(&buffer, '/');
    }

    virBufferURIEncodeString(&buffer, fileName);
2263
    virBufferAddLit(&buffer, "?dcPath=");
2264
    virBufferURIEncodeString(&buffer, datacenterName);
2265 2266 2267 2268
    virBufferAddLit(&buffer, "&dsName=");
    virBufferURIEncodeString(&buffer, datastoreName);

    if (virBufferError(&buffer)) {
2269
        virReportOOMError();
M
Matthias Bolte 已提交
2270
        goto cleanup;
2271 2272
    }

2273 2274
    url = virBufferContentAndReset(&buffer);

2275
    if (esxVI_Context_DownloadFile(priv->primary, url, &vmx) < 0) {
M
Matthias Bolte 已提交
2276
        goto cleanup;
2277 2278
    }

2279 2280
    def = esxVMX_ParseConfig(priv->primary, priv->caps, vmx, datastoreName,
                             directoryName, priv->primary->productVersion);
2281 2282

    if (def != NULL) {
2283
        xml = virDomainDefFormat(def, flags);
2284 2285 2286
    }

  cleanup:
M
Matthias Bolte 已提交
2287 2288 2289 2290
    if (url == NULL) {
        virBufferFreeAndReset(&buffer);
    }

2291
    esxVI_String_Free(&propertyNameList);
2292
    esxVI_ObjectContent_Free(&datacenter);
2293
    esxVI_ObjectContent_Free(&virtualMachine);
2294
    VIR_FREE(datastoreName);
M
Matthias Bolte 已提交
2295 2296
    VIR_FREE(directoryName);
    VIR_FREE(fileName);
2297 2298
    VIR_FREE(url);
    VIR_FREE(vmx);
2299
    virDomainDefFree(def);
2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310

    return xml;
}



static char *
esxDomainXMLFromNative(virConnectPtr conn, const char *nativeFormat,
                       const char *nativeConfig,
                       unsigned int flags ATTRIBUTE_UNUSED)
{
M
Matthias Bolte 已提交
2311
    esxPrivate *priv = conn->privateData;
2312 2313 2314 2315
    virDomainDefPtr def = NULL;
    char *xml = NULL;

    if (STRNEQ(nativeFormat, "vmware-vmx")) {
2316
        ESX_ERROR(VIR_ERR_INVALID_ARG,
2317
                  _("Unsupported config format '%s'"), nativeFormat);
2318
        return NULL;
2319 2320
    }

2321 2322
    def = esxVMX_ParseConfig(priv->primary, priv->caps, nativeConfig, "?", "?",
                             priv->primary->productVersion);
2323 2324

    if (def != NULL) {
2325
        xml = virDomainDefFormat(def, VIR_DOMAIN_XML_INACTIVE);
2326 2327 2328 2329 2330 2331 2332 2333 2334
    }

    virDomainDefFree(def);

    return xml;
}



M
Matthias Bolte 已提交
2335 2336 2337 2338 2339
static char *
esxDomainXMLToNative(virConnectPtr conn, const char *nativeFormat,
                     const char *domainXml,
                     unsigned int flags ATTRIBUTE_UNUSED)
{
M
Matthias Bolte 已提交
2340
    esxPrivate *priv = conn->privateData;
M
Matthias Bolte 已提交
2341 2342 2343 2344
    virDomainDefPtr def = NULL;
    char *vmx = NULL;

    if (STRNEQ(nativeFormat, "vmware-vmx")) {
2345
        ESX_ERROR(VIR_ERR_INVALID_ARG,
2346
                  _("Unsupported config format '%s'"), nativeFormat);
M
Matthias Bolte 已提交
2347 2348 2349
        return NULL;
    }

2350
    def = virDomainDefParseString(priv->caps, domainXml, 0);
M
Matthias Bolte 已提交
2351 2352 2353 2354 2355

    if (def == NULL) {
        return NULL;
    }

2356 2357
    vmx = esxVMX_FormatConfig(priv->primary, priv->caps, def,
                              priv->primary->productVersion);
M
Matthias Bolte 已提交
2358 2359 2360 2361 2362 2363 2364 2365

    virDomainDefFree(def);

    return vmx;
}



2366 2367 2368
static int
esxListDefinedDomains(virConnectPtr conn, char **const names, int maxnames)
{
M
Matthias Bolte 已提交
2369
    bool success = false;
M
Matthias Bolte 已提交
2370
    esxPrivate *priv = conn->privateData;
2371 2372 2373 2374 2375 2376
    esxVI_String *propertyNameList = NULL;
    esxVI_ObjectContent *virtualMachineList = NULL;
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_DynamicProperty *dynamicProperty = NULL;
    esxVI_VirtualMachinePowerState powerState;
    int count = 0;
2377
    int i;
2378 2379

    if (names == NULL || maxnames < 0) {
2380 2381
        ESX_ERROR(VIR_ERR_INVALID_ARG, "%s", _("Invalid argument"));
        return -1;
2382 2383 2384 2385 2386 2387
    }

    if (maxnames == 0) {
        return 0;
    }

2388
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
2389
        return -1;
2390 2391
    }

2392
    if (esxVI_String_AppendValueListToList(&propertyNameList,
2393 2394
                                           "name\0"
                                           "runtime.powerState\0") < 0 ||
2395
        esxVI_LookupObjectContentByType(priv->primary, priv->primary->vmFolder,
2396 2397 2398
                                        "VirtualMachine", propertyNameList,
                                        esxVI_Boolean_True,
                                        &virtualMachineList) < 0) {
M
Matthias Bolte 已提交
2399
        goto cleanup;
2400 2401 2402 2403
    }

    for (virtualMachine = virtualMachineList; virtualMachine != NULL;
         virtualMachine = virtualMachine->_next) {
2404
        if (esxVI_GetVirtualMachinePowerState(virtualMachine,
2405
                                              &powerState) < 0) {
M
Matthias Bolte 已提交
2406
            goto cleanup;
2407 2408 2409 2410 2411 2412 2413 2414 2415 2416
        }

        if (powerState == esxVI_VirtualMachinePowerState_PoweredOn) {
            continue;
        }

        for (dynamicProperty = virtualMachine->propSet;
             dynamicProperty != NULL;
             dynamicProperty = dynamicProperty->_next) {
            if (STREQ(dynamicProperty->name, "name")) {
2417
                if (esxVI_AnyType_ExpectType(dynamicProperty->val,
2418
                                             esxVI_Type_String) < 0) {
M
Matthias Bolte 已提交
2419
                    goto cleanup;
2420 2421 2422 2423 2424
                }

                names[count] = strdup(dynamicProperty->val->string);

                if (names[count] == NULL) {
2425
                    virReportOOMError();
M
Matthias Bolte 已提交
2426
                    goto cleanup;
2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438
                }

                count++;
                break;
            }
        }

        if (count >= maxnames) {
            break;
        }
    }

M
Matthias Bolte 已提交
2439
    success = true;
2440

M
Matthias Bolte 已提交
2441 2442 2443 2444 2445
  cleanup:
    if (! success) {
        for (i = 0; i < count; ++i) {
            VIR_FREE(names[i]);
        }
2446

M
Matthias Bolte 已提交
2447
        count = -1;
2448 2449
    }

M
Matthias Bolte 已提交
2450 2451
    esxVI_String_Free(&propertyNameList);
    esxVI_ObjectContent_Free(&virtualMachineList);
2452

M
Matthias Bolte 已提交
2453
    return count;
2454 2455 2456 2457 2458 2459 2460
}



static int
esxNumberOfDefinedDomains(virConnectPtr conn)
{
M
Matthias Bolte 已提交
2461
    esxPrivate *priv = conn->privateData;
2462

2463
    if (esxVI_EnsureSession(priv->primary) < 0) {
2464 2465 2466
        return -1;
    }

2467
    return esxVI_LookupNumberOfDomainsByPowerState
2468
             (priv->primary, esxVI_VirtualMachinePowerState_PoweredOn,
2469 2470 2471 2472 2473 2474
              esxVI_Boolean_True);
}



static int
2475
esxDomainCreateWithFlags(virDomainPtr domain, unsigned int flags)
2476
{
M
Matthias Bolte 已提交
2477
    int result = -1;
M
Matthias Bolte 已提交
2478
    esxPrivate *priv = domain->conn->privateData;
2479 2480 2481
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_String *propertyNameList = NULL;
    esxVI_VirtualMachinePowerState powerState;
2482
    int id = -1;
2483 2484 2485
    esxVI_ManagedObjectReference *task = NULL;
    esxVI_TaskInfoState taskInfoState;

2486 2487
    virCheckFlags(0, -1);

2488
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
2489
        return -1;
2490 2491
    }

2492
    if (esxVI_String_AppendValueToList(&propertyNameList,
2493
                                       "runtime.powerState") < 0 ||
2494
        esxVI_LookupVirtualMachineByUuidAndPrepareForTask
2495
          (priv->primary, domain->uuid, propertyNameList, &virtualMachine,
2496
           priv->autoAnswer) < 0 ||
2497 2498
        esxVI_GetVirtualMachinePowerState(virtualMachine, &powerState) < 0 ||
        esxVI_GetVirtualMachineIdentity(virtualMachine, &id, NULL, NULL) < 0) {
M
Matthias Bolte 已提交
2499
        goto cleanup;
2500 2501 2502
    }

    if (powerState != esxVI_VirtualMachinePowerState_PoweredOff) {
2503 2504
        ESX_ERROR(VIR_ERR_OPERATION_INVALID, "%s",
                  _("Domain is not powered off"));
M
Matthias Bolte 已提交
2505
        goto cleanup;
2506 2507
    }

2508
    if (esxVI_PowerOnVM_Task(priv->primary, virtualMachine->obj, NULL,
2509
                             &task) < 0 ||
2510
        esxVI_WaitForTaskCompletion(priv->primary, task, domain->uuid,
2511
                                    esxVI_Occurrence_RequiredItem,
2512
                                    priv->autoAnswer, &taskInfoState) < 0) {
M
Matthias Bolte 已提交
2513
        goto cleanup;
2514 2515 2516
    }

    if (taskInfoState != esxVI_TaskInfoState_Success) {
2517
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not start domain"));
M
Matthias Bolte 已提交
2518
        goto cleanup;
2519 2520
    }

2521
    domain->id = id;
M
Matthias Bolte 已提交
2522 2523
    result = 0;

2524 2525 2526 2527 2528 2529 2530 2531
  cleanup:
    esxVI_ObjectContent_Free(&virtualMachine);
    esxVI_String_Free(&propertyNameList);
    esxVI_ManagedObjectReference_Free(&task);

    return result;
}

2532 2533 2534 2535 2536
static int
esxDomainCreate(virDomainPtr domain)
{
    return esxDomainCreateWithFlags(domain, 0);
}
2537

M
Matthias Bolte 已提交
2538 2539 2540
static virDomainPtr
esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED)
{
M
Matthias Bolte 已提交
2541
    esxPrivate *priv = conn->privateData;
M
Matthias Bolte 已提交
2542 2543
    virDomainDefPtr def = NULL;
    char *vmx = NULL;
2544 2545
    int i;
    virDomainDiskDefPtr disk = NULL;
M
Matthias Bolte 已提交
2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559
    esxVI_ObjectContent *virtualMachine = NULL;
    char *datastoreName = NULL;
    char *directoryName = NULL;
    char *fileName = NULL;
    virBuffer buffer = VIR_BUFFER_INITIALIZER;
    char *url = NULL;
    char *datastoreRelatedPath = NULL;
    esxVI_String *propertyNameList = NULL;
    esxVI_ObjectContent *hostSystem = NULL;
    esxVI_ManagedObjectReference *resourcePool = NULL;
    esxVI_ManagedObjectReference *task = NULL;
    esxVI_TaskInfoState taskInfoState;
    virDomainPtr domain = NULL;

2560 2561 2562 2563 2564 2565 2566
    if (priv->host == NULL) {
        /* FIXME: Currently no host for a vpx:// connection */
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                  _("Could not define domain with a vpx:// connection"));
        return NULL;
    }

2567
    if (esxVI_EnsureSession(priv->host) < 0) {
M
Matthias Bolte 已提交
2568
        return NULL;
M
Matthias Bolte 已提交
2569 2570 2571
    }

    /* Parse domain XML */
2572
    def = virDomainDefParseString(priv->caps, xml,
M
Matthias Bolte 已提交
2573 2574 2575
                                  VIR_DOMAIN_XML_INACTIVE);

    if (def == NULL) {
M
Matthias Bolte 已提交
2576
        return NULL;
M
Matthias Bolte 已提交
2577 2578 2579
    }

    /* Check if an existing domain should be edited */
2580
    if (esxVI_LookupVirtualMachineByUuid(priv->host, def->uuid, NULL,
M
Matthias Bolte 已提交
2581
                                         &virtualMachine,
M
Matthias Bolte 已提交
2582
                                         esxVI_Occurrence_OptionalItem) < 0) {
M
Matthias Bolte 已提交
2583
        goto cleanup;
M
Matthias Bolte 已提交
2584 2585 2586 2587
    }

    if (virtualMachine != NULL) {
        /* FIXME */
2588 2589 2590
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                  _("Domain already exists, editing existing domains is not "
                    "supported yet"));
M
Matthias Bolte 已提交
2591
        goto cleanup;
M
Matthias Bolte 已提交
2592 2593 2594
    }

    /* Build VMX from domain XML */
2595 2596
    vmx = esxVMX_FormatConfig(priv->host, priv->caps, def,
                              priv->host->productVersion);
M
Matthias Bolte 已提交
2597 2598

    if (vmx == NULL) {
M
Matthias Bolte 已提交
2599
        goto cleanup;
M
Matthias Bolte 已提交
2600 2601
    }

2602 2603 2604 2605 2606 2607 2608
    /*
     * Build VMX datastore URL. Use the source of the first file-based harddisk
     * to deduce the datastore and path for the VMX file. Don't just use the
     * first disk, because it may be CDROM disk and ISO images are normaly not
     * located in the virtual machine's directory. This approach to deduce the
     * datastore isn't perfect but should work in the majority of cases.
     */
M
Matthias Bolte 已提交
2609
    if (def->ndisks < 1) {
2610 2611 2612
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                  _("Domain XML doesn't contain any disks, cannot deduce "
                    "datastore and path for VMX file"));
M
Matthias Bolte 已提交
2613
        goto cleanup;
2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624
    }

    for (i = 0; i < def->ndisks; ++i) {
        if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
            def->disks[i]->type == VIR_DOMAIN_DISK_TYPE_FILE) {
            disk = def->disks[i];
            break;
        }
    }

    if (disk == NULL) {
2625 2626 2627
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                  _("Domain XML doesn't contain any file-based harddisks, "
                    "cannot deduce datastore and path for VMX file"));
M
Matthias Bolte 已提交
2628
        goto cleanup;
M
Matthias Bolte 已提交
2629 2630
    }

2631
    if (disk->src == NULL) {
2632 2633 2634
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                  _("First file-based harddisk has no source, cannot deduce "
                    "datastore and path for VMX file"));
M
Matthias Bolte 已提交
2635
        goto cleanup;
M
Matthias Bolte 已提交
2636 2637
    }

2638
    if (esxUtil_ParseDatastoreRelatedPath(disk->src, &datastoreName,
2639
                                          &directoryName, &fileName) < 0) {
M
Matthias Bolte 已提交
2640
        goto cleanup;
M
Matthias Bolte 已提交
2641 2642
    }

2643
    if (! virFileHasSuffix(fileName, ".vmdk")) {
2644
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
2645 2646
                  _("Expecting source '%s' of first file-based harddisk to "
                    "be a VMDK image"), disk->src);
M
Matthias Bolte 已提交
2647
        goto cleanup;
M
Matthias Bolte 已提交
2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664
    }

    virBufferVSprintf(&buffer, "%s://%s:%d/folder/", priv->transport,
                      conn->uri->server, conn->uri->port);

    if (directoryName != NULL) {
        virBufferURIEncodeString(&buffer, directoryName);
        virBufferAddChar(&buffer, '/');
    }

    virBufferURIEncodeString(&buffer, def->name);
    virBufferAddLit(&buffer, ".vmx?dcPath=");
    virBufferURIEncodeString(&buffer, priv->host->datacenter->value);
    virBufferAddLit(&buffer, "&dsName=");
    virBufferURIEncodeString(&buffer, datastoreName);

    if (virBufferError(&buffer)) {
2665
        virReportOOMError();
M
Matthias Bolte 已提交
2666
        goto cleanup;
M
Matthias Bolte 已提交
2667 2668 2669 2670 2671 2672 2673
    }

    url = virBufferContentAndReset(&buffer);

    if (directoryName != NULL) {
        if (virAsprintf(&datastoreRelatedPath, "[%s] %s/%s.vmx", datastoreName,
                        directoryName, def->name) < 0) {
2674
            virReportOOMError();
M
Matthias Bolte 已提交
2675
            goto cleanup;
M
Matthias Bolte 已提交
2676 2677 2678 2679
        }
    } else {
        if (virAsprintf(&datastoreRelatedPath, "[%s] %s.vmx", datastoreName,
                        def->name) < 0) {
2680
            virReportOOMError();
M
Matthias Bolte 已提交
2681
            goto cleanup;
M
Matthias Bolte 已提交
2682 2683 2684 2685
        }
    }

    /* Get resource pool */
2686 2687
    if (esxVI_String_AppendValueToList(&propertyNameList, "parent") < 0 ||
        esxVI_LookupHostSystemByIp(priv->host, priv->host->ipAddress,
M
Matthias Bolte 已提交
2688
                                   propertyNameList, &hostSystem) < 0) {
M
Matthias Bolte 已提交
2689
        goto cleanup;
M
Matthias Bolte 已提交
2690 2691
    }

2692
    if (esxVI_LookupResourcePoolByHostSystem(priv->host, hostSystem,
2693
                                             &resourcePool) < 0) {
M
Matthias Bolte 已提交
2694
        goto cleanup;
M
Matthias Bolte 已提交
2695 2696 2697 2698 2699 2700
    }

    /* Check, if VMX file already exists */
    /* FIXME */

    /* Upload VMX file */
2701
    if (esxVI_Context_UploadFile(priv->host, url, vmx) < 0) {
M
Matthias Bolte 已提交
2702
        goto cleanup;
M
Matthias Bolte 已提交
2703 2704 2705
    }

    /* Register the domain */
2706
    if (esxVI_RegisterVM_Task(priv->host, priv->host->vmFolder,
M
Matthias Bolte 已提交
2707 2708
                              datastoreRelatedPath, NULL, esxVI_Boolean_False,
                              resourcePool, hostSystem->obj, &task) < 0 ||
2709
        esxVI_WaitForTaskCompletion(priv->host, task, def->uuid,
2710
                                    esxVI_Occurrence_OptionalItem,
2711
                                    priv->autoAnswer, &taskInfoState) < 0) {
M
Matthias Bolte 已提交
2712
        goto cleanup;
M
Matthias Bolte 已提交
2713 2714 2715
    }

    if (taskInfoState != esxVI_TaskInfoState_Success) {
2716
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not define domain"));
M
Matthias Bolte 已提交
2717
        goto cleanup;
M
Matthias Bolte 已提交
2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728
    }

    domain = virGetDomain(conn, def->name, def->uuid);

    if (domain != NULL) {
        domain->id = -1;
    }

    /* FIXME: Add proper rollback in case of an error */

  cleanup:
M
Matthias Bolte 已提交
2729 2730 2731 2732
    if (url == NULL) {
        virBufferFreeAndReset(&buffer);
    }

M
Matthias Bolte 已提交
2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750
    virDomainDefFree(def);
    VIR_FREE(vmx);
    VIR_FREE(datastoreName);
    VIR_FREE(directoryName);
    VIR_FREE(fileName);
    VIR_FREE(url);
    VIR_FREE(datastoreRelatedPath);
    esxVI_ObjectContent_Free(&virtualMachine);
    esxVI_String_Free(&propertyNameList);
    esxVI_ObjectContent_Free(&hostSystem);
    esxVI_ManagedObjectReference_Free(&resourcePool);
    esxVI_ManagedObjectReference_Free(&task);

    return domain;
}



2751 2752 2753
static int
esxDomainUndefine(virDomainPtr domain)
{
M
Matthias Bolte 已提交
2754
    int result = -1;
M
Matthias Bolte 已提交
2755
    esxPrivate *priv = domain->conn->privateData;
2756
    esxVI_Context *ctx = NULL;
2757 2758 2759 2760
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_String *propertyNameList = NULL;
    esxVI_VirtualMachinePowerState powerState;

2761 2762 2763 2764 2765 2766
    if (priv->vCenter != NULL) {
        ctx = priv->vCenter;
    } else {
        ctx = priv->host;
    }

2767
    if (esxVI_EnsureSession(ctx) < 0) {
M
Matthias Bolte 已提交
2768
        return -1;
2769 2770
    }

2771
    if (esxVI_String_AppendValueToList(&propertyNameList,
2772
                                       "runtime.powerState") < 0 ||
2773 2774
        esxVI_LookupVirtualMachineByUuid(ctx, domain->uuid, propertyNameList,
                                         &virtualMachine,
M
Matthias Bolte 已提交
2775
                                         esxVI_Occurrence_RequiredItem) < 0 ||
2776
        esxVI_GetVirtualMachinePowerState(virtualMachine, &powerState) < 0) {
M
Matthias Bolte 已提交
2777
        goto cleanup;
2778 2779 2780 2781
    }

    if (powerState != esxVI_VirtualMachinePowerState_Suspended &&
        powerState != esxVI_VirtualMachinePowerState_PoweredOff) {
2782 2783
        ESX_ERROR(VIR_ERR_OPERATION_INVALID, "%s",
                  _("Domain is not suspended or powered off"));
M
Matthias Bolte 已提交
2784
        goto cleanup;
2785 2786
    }

2787
    if (esxVI_UnregisterVM(ctx, virtualMachine->obj) < 0) {
M
Matthias Bolte 已提交
2788
        goto cleanup;
2789 2790
    }

M
Matthias Bolte 已提交
2791 2792
    result = 0;

2793 2794 2795 2796 2797 2798 2799 2800 2801
  cleanup:
    esxVI_ObjectContent_Free(&virtualMachine);
    esxVI_String_Free(&propertyNameList);

    return result;
}



2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813
/*
 * The scheduler interface exposes basically the CPU ResourceAllocationInfo:
 *
 * - http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/vim.ResourceAllocationInfo.html
 * - http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/vim.SharesInfo.html
 * - http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/vim.SharesInfo.Level.html
 *
 *
 * Available parameters:
 *
 * - reservation (VIR_DOMAIN_SCHED_FIELD_LLONG >= 0, in megaherz)
 *
2814
 *   The amount of CPU resource that is guaranteed to be available to the domain.
2815 2816 2817 2818
 *
 *
 * - limit (VIR_DOMAIN_SCHED_FIELD_LLONG >= 0, or -1, in megaherz)
 *
2819 2820
 *   The CPU utilization of the domain will be limited to this value, even if
 *   more CPU resources are available. If the limit is set to -1, the CPU
2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831
 *   utilization of the domain is unlimited. If the limit is not set to -1, it
 *   must be greater than or equal to the reservation.
 *
 *
 * - shares (VIR_DOMAIN_SCHED_FIELD_INT >= 0, or in {-1, -2, -3}, no unit)
 *
 *   Shares are used to determine relative CPU allocation between domains. In
 *   general, a domain with more shares gets proportionally more of the CPU
 *   resource. The special values -1, -2 and -3 represent the predefined
 *   SharesLevel 'low', 'normal' and 'high'.
 */
2832
static char *
2833
esxDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED, int *nparams)
2834 2835 2836 2837
{
    char *type = strdup("allocation");

    if (type == NULL) {
2838
        virReportOOMError();
2839
        return NULL;
2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852
    }

    *nparams = 3; /* reservation, limit, shares */

    return type;
}



static int
esxDomainGetSchedulerParameters(virDomainPtr domain,
                                virSchedParameterPtr params, int *nparams)
{
M
Matthias Bolte 已提交
2853
    int result = -1;
M
Matthias Bolte 已提交
2854
    esxPrivate *priv = domain->conn->privateData;
2855 2856 2857 2858 2859 2860 2861 2862
    esxVI_String *propertyNameList = NULL;
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_DynamicProperty *dynamicProperty = NULL;
    esxVI_SharesInfo *sharesInfo = NULL;
    unsigned int mask = 0;
    int i = 0;

    if (*nparams < 3) {
2863 2864
        ESX_ERROR(VIR_ERR_INVALID_ARG, "%s",
                  _("Parameter array must have space for 3 items"));
M
Matthias Bolte 已提交
2865
        return -1;
2866 2867
    }

2868
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
2869
        return -1;
2870 2871
    }

2872
    if (esxVI_String_AppendValueListToList(&propertyNameList,
2873 2874 2875
                                           "config.cpuAllocation.reservation\0"
                                           "config.cpuAllocation.limit\0"
                                           "config.cpuAllocation.shares\0") < 0 ||
2876
        esxVI_LookupVirtualMachineByUuid(priv->primary, domain->uuid,
2877
                                         propertyNameList, &virtualMachine,
M
Matthias Bolte 已提交
2878
                                         esxVI_Occurrence_RequiredItem) < 0) {
M
Matthias Bolte 已提交
2879
        goto cleanup;
2880 2881 2882 2883 2884 2885
    }

    for (dynamicProperty = virtualMachine->propSet;
         dynamicProperty != NULL && mask != 7 && i < 3;
         dynamicProperty = dynamicProperty->_next) {
        if (STREQ(dynamicProperty->name, "config.cpuAllocation.reservation") &&
M
Matthias Bolte 已提交
2886
            ! (mask & (1 << 0))) {
2887 2888 2889 2890 2891
            snprintf (params[i].field, VIR_DOMAIN_SCHED_FIELD_LENGTH, "%s",
                      "reservation");

            params[i].type = VIR_DOMAIN_SCHED_FIELD_LLONG;

2892
            if (esxVI_AnyType_ExpectType(dynamicProperty->val,
2893
                                         esxVI_Type_Long) < 0) {
M
Matthias Bolte 已提交
2894
                goto cleanup;
2895 2896 2897 2898 2899 2900 2901
            }

            params[i].value.l = dynamicProperty->val->int64;
            mask |= 1 << 0;
            ++i;
        } else if (STREQ(dynamicProperty->name,
                         "config.cpuAllocation.limit") &&
M
Matthias Bolte 已提交
2902
                   ! (mask & (1 << 1))) {
2903 2904 2905 2906 2907
            snprintf (params[i].field, VIR_DOMAIN_SCHED_FIELD_LENGTH, "%s",
                      "limit");

            params[i].type = VIR_DOMAIN_SCHED_FIELD_LLONG;

2908
            if (esxVI_AnyType_ExpectType(dynamicProperty->val,
2909
                                         esxVI_Type_Long) < 0) {
M
Matthias Bolte 已提交
2910
                goto cleanup;
2911 2912 2913 2914 2915 2916 2917
            }

            params[i].value.l = dynamicProperty->val->int64;
            mask |= 1 << 1;
            ++i;
        } else if (STREQ(dynamicProperty->name,
                         "config.cpuAllocation.shares") &&
M
Matthias Bolte 已提交
2918
                   ! (mask & (1 << 2))) {
2919 2920 2921 2922 2923
            snprintf (params[i].field, VIR_DOMAIN_SCHED_FIELD_LENGTH, "%s",
                      "shares");

            params[i].type = VIR_DOMAIN_SCHED_FIELD_INT;

2924
            if (esxVI_SharesInfo_CastFromAnyType(dynamicProperty->val,
2925
                                                 &sharesInfo) < 0) {
M
Matthias Bolte 已提交
2926
                goto cleanup;
2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946
            }

            switch (sharesInfo->level) {
              case esxVI_SharesLevel_Custom:
                params[i].value.i = sharesInfo->shares->value;
                break;

              case esxVI_SharesLevel_Low:
                params[i].value.i = -1;
                break;

              case esxVI_SharesLevel_Normal:
                params[i].value.i = -2;
                break;

              case esxVI_SharesLevel_High:
                params[i].value.i = -3;
                break;

              default:
2947
                ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
2948
                          _("Shares level has unknown value %d"),
2949
                          (int)sharesInfo->level);
M
Matthias Bolte 已提交
2950
                goto cleanup;
2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962
            }

            esxVI_SharesInfo_Free(&sharesInfo);

            mask |= 1 << 2;
            ++i;
        } else {
            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
        }
    }

    *nparams = i;
M
Matthias Bolte 已提交
2963
    result = 0;
2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977

  cleanup:
    esxVI_String_Free(&propertyNameList);
    esxVI_ObjectContent_Free(&virtualMachine);

    return result;
}



static int
esxDomainSetSchedulerParameters(virDomainPtr domain,
                                virSchedParameterPtr params, int nparams)
{
M
Matthias Bolte 已提交
2978
    int result = -1;
M
Matthias Bolte 已提交
2979
    esxPrivate *priv = domain->conn->privateData;
2980 2981 2982 2983 2984 2985 2986
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_VirtualMachineConfigSpec *spec = NULL;
    esxVI_SharesInfo *sharesInfo = NULL;
    esxVI_ManagedObjectReference *task = NULL;
    esxVI_TaskInfoState taskInfoState;
    int i;

2987
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
2988
        return -1;
2989 2990
    }

2991
    if (esxVI_LookupVirtualMachineByUuidAndPrepareForTask
2992
          (priv->primary, domain->uuid, NULL, &virtualMachine,
2993
           priv->autoAnswer) < 0 ||
2994 2995
        esxVI_VirtualMachineConfigSpec_Alloc(&spec) < 0 ||
        esxVI_ResourceAllocationInfo_Alloc(&spec->cpuAllocation) < 0) {
M
Matthias Bolte 已提交
2996
        goto cleanup;
2997 2998 2999 3000 3001
    }

    for (i = 0; i < nparams; ++i) {
        if (STREQ (params[i].field, "reservation") &&
            params[i].type == VIR_DOMAIN_SCHED_FIELD_LLONG) {
3002
            if (esxVI_Long_Alloc(&spec->cpuAllocation->reservation) < 0) {
M
Matthias Bolte 已提交
3003
                goto cleanup;
3004 3005 3006
            }

            if (params[i].value.l < 0) {
3007
                ESX_ERROR(VIR_ERR_INVALID_ARG,
3008 3009
                          _("Could not set reservation to %lld MHz, expecting "
                            "positive value"), params[i].value.l);
M
Matthias Bolte 已提交
3010
                goto cleanup;
3011 3012 3013 3014 3015
            }

            spec->cpuAllocation->reservation->value = params[i].value.l;
        } else if (STREQ (params[i].field, "limit") &&
                   params[i].type == VIR_DOMAIN_SCHED_FIELD_LLONG) {
3016
            if (esxVI_Long_Alloc(&spec->cpuAllocation->limit) < 0) {
M
Matthias Bolte 已提交
3017
                goto cleanup;
3018 3019 3020
            }

            if (params[i].value.l < -1) {
3021
                ESX_ERROR(VIR_ERR_INVALID_ARG,
3022 3023
                          _("Could not set limit to %lld MHz, expecting "
                            "positive value or -1 (unlimited)"),
3024
                          params[i].value.l);
M
Matthias Bolte 已提交
3025
                goto cleanup;
3026 3027 3028 3029
            }

            spec->cpuAllocation->limit->value = params[i].value.l;
        } else if (STREQ (params[i].field, "shares") &&
3030
                   params[i].type == VIR_DOMAIN_SCHED_FIELD_INT) {
3031 3032
            if (esxVI_SharesInfo_Alloc(&sharesInfo) < 0 ||
                esxVI_Int_Alloc(&sharesInfo->shares) < 0) {
M
Matthias Bolte 已提交
3033
                goto cleanup;
3034 3035 3036 3037
            }

            spec->cpuAllocation->shares = sharesInfo;

3038
            if (params[i].value.i >= 0) {
3039
                spec->cpuAllocation->shares->level = esxVI_SharesLevel_Custom;
3040
                spec->cpuAllocation->shares->shares->value = params[i].value.i;
3041
            } else {
3042
                switch (params[i].value.i) {
3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060
                  case -1:
                    spec->cpuAllocation->shares->level = esxVI_SharesLevel_Low;
                    spec->cpuAllocation->shares->shares->value = -1;
                    break;

                  case -2:
                    spec->cpuAllocation->shares->level =
                      esxVI_SharesLevel_Normal;
                    spec->cpuAllocation->shares->shares->value = -1;
                    break;

                  case -3:
                    spec->cpuAllocation->shares->level =
                      esxVI_SharesLevel_High;
                    spec->cpuAllocation->shares->shares->value = -1;
                    break;

                  default:
3061
                    ESX_ERROR(VIR_ERR_INVALID_ARG,
3062 3063
                              _("Could not set shares to %d, expecting positive "
                                "value or -1 (low), -2 (normal) or -3 (high)"),
3064
                              params[i].value.i);
M
Matthias Bolte 已提交
3065
                    goto cleanup;
3066 3067 3068
                }
            }
        } else {
3069
            ESX_ERROR(VIR_ERR_INVALID_ARG, _("Unknown field '%s'"),
3070
                      params[i].field);
M
Matthias Bolte 已提交
3071
            goto cleanup;
3072 3073 3074
        }
    }

3075
    if (esxVI_ReconfigVM_Task(priv->primary, virtualMachine->obj, spec,
3076
                              &task) < 0 ||
3077
        esxVI_WaitForTaskCompletion(priv->primary, task, domain->uuid,
3078
                                    esxVI_Occurrence_RequiredItem,
3079
                                    priv->autoAnswer, &taskInfoState) < 0) {
M
Matthias Bolte 已提交
3080
        goto cleanup;
3081 3082 3083
    }

    if (taskInfoState != esxVI_TaskInfoState_Success) {
3084 3085
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                  _("Could not change scheduler parameters"));
M
Matthias Bolte 已提交
3086
        goto cleanup;
3087 3088
    }

M
Matthias Bolte 已提交
3089 3090
    result = 0;

3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109
  cleanup:
    esxVI_ObjectContent_Free(&virtualMachine);
    esxVI_VirtualMachineConfigSpec_Free(&spec);
    esxVI_ManagedObjectReference_Free(&task);

    return result;
}



static int
esxDomainMigratePrepare(virConnectPtr dconn,
                        char **cookie ATTRIBUTE_UNUSED,
                        int *cookielen ATTRIBUTE_UNUSED,
                        const char *uri_in, char **uri_out,
                        unsigned long flags ATTRIBUTE_UNUSED,
                        const char *dname ATTRIBUTE_UNUSED,
                        unsigned long resource ATTRIBUTE_UNUSED)
{
M
Matthias Bolte 已提交
3110
    int result = -1;
M
Matthias Bolte 已提交
3111
    esxUtil_ParsedUri *parsedUri = NULL;
3112 3113

    if (uri_in == NULL) {
M
Matthias Bolte 已提交
3114
        if (esxUtil_ParseUri(&parsedUri, dconn->uri) < 0) {
3115 3116 3117
            return -1;
        }

M
Matthias Bolte 已提交
3118
        if (virAsprintf(uri_out, "%s://%s:%d/sdk", parsedUri->transport,
3119
                        dconn->uri->server, dconn->uri->port) < 0) {
3120
            virReportOOMError();
M
Matthias Bolte 已提交
3121
            goto cleanup;
3122 3123 3124
        }
    }

M
Matthias Bolte 已提交
3125 3126
    result = 0;

3127
  cleanup:
M
Matthias Bolte 已提交
3128
    esxUtil_FreeParsedUri(&parsedUri);
3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143

    return result;
}



static int
esxDomainMigratePerform(virDomainPtr domain,
                        const char *cookie ATTRIBUTE_UNUSED,
                        int cookielen ATTRIBUTE_UNUSED,
                        const char *uri,
                        unsigned long flags ATTRIBUTE_UNUSED,
                        const char *dname,
                        unsigned long bandwidth ATTRIBUTE_UNUSED)
{
M
Matthias Bolte 已提交
3144
    int result = -1;
M
Matthias Bolte 已提交
3145
    esxPrivate *priv = domain->conn->privateData;
3146
    xmlURIPtr xmlUri = NULL;
M
Matthias Bolte 已提交
3147
    char hostIpAddress[NI_MAXHOST] = "";
3148 3149 3150 3151 3152 3153 3154 3155
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_String *propertyNameList = NULL;
    esxVI_ObjectContent *hostSystem = NULL;
    esxVI_ManagedObjectReference *resourcePool = NULL;
    esxVI_Event *eventList = NULL;
    esxVI_ManagedObjectReference *task = NULL;
    esxVI_TaskInfoState taskInfoState;

M
Matthias Bolte 已提交
3156
    if (priv->vCenter == NULL) {
3157 3158
        ESX_ERROR(VIR_ERR_INVALID_ARG, "%s",
                  _("Migration not possible without a vCenter"));
M
Matthias Bolte 已提交
3159
        return -1;
3160 3161 3162
    }

    if (dname != NULL) {
3163 3164
        ESX_ERROR(VIR_ERR_INVALID_ARG, "%s",
                  _("Renaming domains on migration not supported"));
M
Matthias Bolte 已提交
3165
        return -1;
3166 3167
    }

3168
    if (esxVI_EnsureSession(priv->vCenter) < 0) {
M
Matthias Bolte 已提交
3169
        return -1;
3170 3171 3172 3173 3174 3175
    }

    /* Parse the destination URI and resolve the hostname */
    xmlUri = xmlParseURI(uri);

    if (xmlUri == NULL) {
3176
        virReportOOMError();
M
Matthias Bolte 已提交
3177
        return -1;
3178 3179
    }

3180
    if (esxUtil_ResolveHostname(xmlUri->server, hostIpAddress,
3181
                                NI_MAXHOST) < 0) {
M
Matthias Bolte 已提交
3182
        goto cleanup;
3183 3184 3185
    }

    /* Lookup VirtualMachine, HostSystem and ResourcePool */
3186
    if (esxVI_LookupVirtualMachineByUuidAndPrepareForTask
3187
          (priv->vCenter, domain->uuid, NULL, &virtualMachine,
3188
           priv->autoAnswer) < 0 ||
3189 3190
        esxVI_String_AppendValueToList(&propertyNameList, "parent") < 0 ||
        esxVI_LookupHostSystemByIp(priv->vCenter, hostIpAddress,
M
Matthias Bolte 已提交
3191
                                   propertyNameList, &hostSystem) < 0) {
M
Matthias Bolte 已提交
3192
        goto cleanup;
3193 3194
    }

3195 3196
    if (esxVI_LookupResourcePoolByHostSystem(priv->vCenter, hostSystem,
                                             &resourcePool) < 0) {
M
Matthias Bolte 已提交
3197
        goto cleanup;
3198 3199 3200
    }

    /* Validate the purposed migration */
3201
    if (esxVI_ValidateMigration(priv->vCenter, virtualMachine->obj,
3202 3203 3204
                                esxVI_VirtualMachinePowerState_Undefined,
                                NULL, resourcePool, hostSystem->obj,
                                &eventList) < 0) {
M
Matthias Bolte 已提交
3205
        goto cleanup;
3206 3207 3208 3209 3210 3211 3212 3213
    }

    if (eventList != NULL) {
        /*
         * FIXME: Need to report the complete list of events. Limit reporting
         *        to the first event for now.
         */
        if (eventList->fullFormattedMessage != NULL) {
3214
            ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
3215 3216
                      _("Could not migrate domain, validation reported a "
                        "problem: %s"), eventList->fullFormattedMessage);
3217
        } else {
3218 3219 3220
            ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                      _("Could not migrate domain, validation reported a "
                        "problem"));
3221 3222
        }

M
Matthias Bolte 已提交
3223
        goto cleanup;
3224 3225 3226
    }

    /* Perform the purposed migration */
3227
    if (esxVI_MigrateVM_Task(priv->vCenter, virtualMachine->obj, resourcePool,
3228 3229 3230 3231
                             hostSystem->obj,
                             esxVI_VirtualMachineMovePriority_DefaultPriority,
                             esxVI_VirtualMachinePowerState_Undefined,
                             &task) < 0 ||
3232
        esxVI_WaitForTaskCompletion(priv->vCenter, task, domain->uuid,
3233
                                    esxVI_Occurrence_RequiredItem,
3234
                                    priv->autoAnswer, &taskInfoState) < 0) {
M
Matthias Bolte 已提交
3235
        goto cleanup;
3236 3237 3238
    }

    if (taskInfoState != esxVI_TaskInfoState_Success) {
3239 3240 3241
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                  _("Could not migrate domain, migration task finished with "
                    "an error"));
M
Matthias Bolte 已提交
3242
        goto cleanup;
3243 3244
    }

M
Matthias Bolte 已提交
3245 3246
    result = 0;

3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272
  cleanup:
    xmlFreeURI(xmlUri);
    esxVI_ObjectContent_Free(&virtualMachine);
    esxVI_String_Free(&propertyNameList);
    esxVI_ObjectContent_Free(&hostSystem);
    esxVI_ManagedObjectReference_Free(&resourcePool);
    esxVI_Event_Free(&eventList);
    esxVI_ManagedObjectReference_Free(&task);

    return result;
}



static virDomainPtr
esxDomainMigrateFinish(virConnectPtr dconn, const char *dname,
                       const char *cookie ATTRIBUTE_UNUSED,
                       int cookielen ATTRIBUTE_UNUSED,
                       const char *uri ATTRIBUTE_UNUSED,
                       unsigned long flags ATTRIBUTE_UNUSED)
{
    return esxDomainLookupByName(dconn, dname);
}



M
Matthias Bolte 已提交
3273 3274 3275 3276
static unsigned long long
esxNodeGetFreeMemory(virConnectPtr conn)
{
    unsigned long long result = 0;
M
Matthias Bolte 已提交
3277
    esxPrivate *priv = conn->privateData;
M
Matthias Bolte 已提交
3278 3279 3280 3281 3282 3283 3284
    esxVI_String *propertyNameList = NULL;
    esxVI_ObjectContent *hostSystem = NULL;
    esxVI_ManagedObjectReference *managedObjectReference = NULL;
    esxVI_ObjectContent *resourcePool = NULL;
    esxVI_DynamicProperty *dynamicProperty = NULL;
    esxVI_ResourcePoolResourceUsage *resourcePoolResourceUsage = NULL;

3285 3286 3287 3288 3289 3290 3291
    if (priv->host == NULL) {
        /* FIXME: Currently no host for a vpx:// connection */
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                  _("Could not retrieve free memory for a vpx:// connection"));
        return 0;
    }

3292
    if (esxVI_EnsureSession(priv->host) < 0) {
M
Matthias Bolte 已提交
3293
        return 0;
M
Matthias Bolte 已提交
3294 3295 3296
    }

    /* Lookup host system with its resource pool */
3297 3298
    if (esxVI_String_AppendValueToList(&propertyNameList, "parent") < 0 ||
        esxVI_LookupHostSystemByIp(priv->host, priv->host->ipAddress,
M
Matthias Bolte 已提交
3299
                                   propertyNameList, &hostSystem) < 0) {
M
Matthias Bolte 已提交
3300
        goto cleanup;
M
Matthias Bolte 已提交
3301 3302
    }

3303
    if (esxVI_LookupResourcePoolByHostSystem(priv->host, hostSystem,
3304
                                             &managedObjectReference) < 0) {
M
Matthias Bolte 已提交
3305
        goto cleanup;
M
Matthias Bolte 已提交
3306 3307 3308 3309 3310
    }

    esxVI_String_Free(&propertyNameList);

    /* Get memory usage of resource pool */
3311
    if (esxVI_String_AppendValueToList(&propertyNameList,
M
Matthias Bolte 已提交
3312
                                       "runtime.memory") < 0 ||
3313
        esxVI_LookupObjectContentByType(priv->host, managedObjectReference,
3314 3315 3316
                                        "ResourcePool", propertyNameList,
                                        esxVI_Boolean_False,
                                        &resourcePool) < 0) {
M
Matthias Bolte 已提交
3317
        goto cleanup;
M
Matthias Bolte 已提交
3318 3319 3320 3321 3322 3323
    }

    for (dynamicProperty = resourcePool->propSet; dynamicProperty != NULL;
         dynamicProperty = dynamicProperty->_next) {
        if (STREQ(dynamicProperty->name, "runtime.memory")) {
            if (esxVI_ResourcePoolResourceUsage_CastFromAnyType
3324
                  (dynamicProperty->val, &resourcePoolResourceUsage) < 0) {
M
Matthias Bolte 已提交
3325
                goto cleanup;
M
Matthias Bolte 已提交
3326 3327 3328 3329 3330 3331 3332 3333 3334
            }

            break;
        } else {
            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
        }
    }

    if (resourcePoolResourceUsage == NULL) {
3335 3336
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
                  _("Could not retrieve memory usage of resource pool"));
M
Matthias Bolte 已提交
3337
        goto cleanup;
M
Matthias Bolte 已提交
3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353
    }

    result = resourcePoolResourceUsage->unreservedForVm->value;

  cleanup:
    esxVI_String_Free(&propertyNameList);
    esxVI_ObjectContent_Free(&hostSystem);
    esxVI_ManagedObjectReference_Free(&managedObjectReference);
    esxVI_ObjectContent_Free(&resourcePool);
    esxVI_ResourcePoolResourceUsage_Free(&resourcePoolResourceUsage);

    return result;
}



3354 3355 3356
static int
esxIsEncrypted(virConnectPtr conn)
{
M
Matthias Bolte 已提交
3357
    esxPrivate *priv = conn->privateData;
3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370

    if (STRCASEEQ(priv->transport, "https")) {
        return 1;
    } else {
        return 0;
    }
}



static int
esxIsSecure(virConnectPtr conn)
{
M
Matthias Bolte 已提交
3371
    esxPrivate *priv = conn->privateData;
3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384

    if (STRCASEEQ(priv->transport, "https")) {
        return 1;
    } else {
        return 0;
    }
}



static int
esxDomainIsActive(virDomainPtr domain)
{
M
Matthias Bolte 已提交
3385
    int result = -1;
M
Matthias Bolte 已提交
3386
    esxPrivate *priv = domain->conn->privateData;
3387 3388 3389 3390
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_String *propertyNameList = NULL;
    esxVI_VirtualMachinePowerState powerState;

3391
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
3392
        return -1;
3393 3394
    }

3395
    if (esxVI_String_AppendValueToList(&propertyNameList,
3396
                                       "runtime.powerState") < 0 ||
3397
        esxVI_LookupVirtualMachineByUuid(priv->primary, domain->uuid,
3398
                                         propertyNameList, &virtualMachine,
M
Matthias Bolte 已提交
3399
                                         esxVI_Occurrence_RequiredItem) < 0 ||
3400
        esxVI_GetVirtualMachinePowerState(virtualMachine, &powerState) < 0) {
M
Matthias Bolte 已提交
3401
        goto cleanup;
3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427
    }

    if (powerState != esxVI_VirtualMachinePowerState_PoweredOff) {
        result = 1;
    } else {
        result = 0;
    }

  cleanup:
    esxVI_ObjectContent_Free(&virtualMachine);
    esxVI_String_Free(&propertyNameList);

    return result;
}



static int
esxDomainIsPersistent(virDomainPtr domain ATTRIBUTE_UNUSED)
{
    /* ESX has no concept of transient domains, so all of them are persistent */
    return 1;
}



3428 3429
static virDomainSnapshotPtr
esxDomainSnapshotCreateXML(virDomainPtr domain, const char *xmlDesc,
3430
                           unsigned int flags)
3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441
{
    esxPrivate *priv = domain->conn->privateData;
    virDomainSnapshotDefPtr def = NULL;
    esxVI_ObjectContent *virtualMachine = NULL;
    esxVI_VirtualMachineSnapshotTree *rootSnapshotList = NULL;
    esxVI_VirtualMachineSnapshotTree *snapshotTree = NULL;
    esxVI_VirtualMachineSnapshotTree *snapshotTreeParent = NULL;
    esxVI_ManagedObjectReference *task = NULL;
    esxVI_TaskInfoState taskInfoState;
    virDomainSnapshotPtr snapshot = NULL;

3442 3443
    virCheckFlags(0, NULL);

3444
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
3445
        return NULL;
3446 3447 3448 3449 3450
    }

    def = virDomainSnapshotDefParseString(xmlDesc, 1);

    if (def == NULL) {
M
Matthias Bolte 已提交
3451
        return NULL;
3452 3453 3454
    }

    if (esxVI_LookupVirtualMachineByUuidAndPrepareForTask
3455
          (priv->primary, domain->uuid, NULL, &virtualMachine,
3456
           priv->autoAnswer) < 0 ||
3457
        esxVI_LookupRootSnapshotTreeList(priv->primary, domain->uuid,
3458 3459 3460 3461
                                         &rootSnapshotList) < 0 ||
        esxVI_GetSnapshotTreeByName(rootSnapshotList, def->name,
                                    &snapshotTree, &snapshotTreeParent,
                                    esxVI_Occurrence_OptionalItem) < 0) {
M
Matthias Bolte 已提交
3462
        goto cleanup;
3463 3464 3465 3466 3467
    }

    if (snapshotTree != NULL) {
        ESX_ERROR(VIR_ERR_OPERATION_INVALID,
                  _("Snapshot '%s' already exists"), def->name);
M
Matthias Bolte 已提交
3468
        goto cleanup;
3469 3470
    }

3471
    if (esxVI_CreateSnapshot_Task(priv->primary, virtualMachine->obj,
3472 3473 3474
                                  def->name, def->description,
                                  esxVI_Boolean_True,
                                  esxVI_Boolean_False, &task) < 0 ||
3475
        esxVI_WaitForTaskCompletion(priv->primary, task, domain->uuid,
3476
                                    esxVI_Occurrence_RequiredItem,
3477
                                    priv->autoAnswer, &taskInfoState) < 0) {
M
Matthias Bolte 已提交
3478
        goto cleanup;
3479 3480 3481 3482
    }

    if (taskInfoState != esxVI_TaskInfoState_Success) {
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create snapshot"));
M
Matthias Bolte 已提交
3483
        goto cleanup;
3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500
    }

    snapshot = virGetDomainSnapshot(domain, def->name);

  cleanup:
    virDomainSnapshotDefFree(def);
    esxVI_ObjectContent_Free(&virtualMachine);
    esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotList);
    esxVI_ManagedObjectReference_Free(&task);

    return snapshot;
}



static char *
esxDomainSnapshotDumpXML(virDomainSnapshotPtr snapshot,
3501
                         unsigned int flags)
3502 3503 3504 3505 3506 3507 3508 3509 3510
{
    esxPrivate *priv = snapshot->domain->conn->privateData;
    esxVI_VirtualMachineSnapshotTree *rootSnapshotList = NULL;
    esxVI_VirtualMachineSnapshotTree *snapshotTree = NULL;
    esxVI_VirtualMachineSnapshotTree *snapshotTreeParent = NULL;
    virDomainSnapshotDef def;
    char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
    char *xml = NULL;

3511 3512
    virCheckFlags(0, NULL);

M
Matthias Bolte 已提交
3513
    memset(&def, 0, sizeof (def));
3514

3515
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
3516
        return NULL;
3517 3518
    }

3519
    if (esxVI_LookupRootSnapshotTreeList(priv->primary, snapshot->domain->uuid,
3520 3521 3522 3523
                                         &rootSnapshotList) < 0 ||
        esxVI_GetSnapshotTreeByName(rootSnapshotList, snapshot->name,
                                    &snapshotTree, &snapshotTreeParent,
                                    esxVI_Occurrence_RequiredItem) < 0) {
M
Matthias Bolte 已提交
3524
        goto cleanup;
3525 3526 3527 3528 3529 3530 3531 3532
    }

    def.name = snapshot->name;
    def.description = snapshotTree->description;
    def.parent = snapshotTreeParent != NULL ? snapshotTreeParent->name : NULL;

    if (esxVI_DateTime_ConvertToCalendarTime(snapshotTree->createTime,
                                             &def.creationTime) < 0) {
M
Matthias Bolte 已提交
3533
        goto cleanup;
3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551
    }

    def.state = esxVI_VirtualMachinePowerState_ConvertToLibvirt
                  (snapshotTree->state);

    virUUIDFormat(snapshot->domain->uuid, uuid_string);

    xml = virDomainSnapshotDefFormat(uuid_string, &def, 0);

  cleanup:
    esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotList);

    return xml;
}



static int
3552
esxDomainSnapshotNum(virDomainPtr domain, unsigned int flags)
3553
{
M
Matthias Bolte 已提交
3554
    int count;
3555 3556 3557
    esxPrivate *priv = domain->conn->privateData;
    esxVI_VirtualMachineSnapshotTree *rootSnapshotTreeList = NULL;

3558 3559
    virCheckFlags(0, -1);

3560
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
3561
        return -1;
3562 3563
    }

3564
    if (esxVI_LookupRootSnapshotTreeList(priv->primary, domain->uuid,
3565
                                         &rootSnapshotTreeList) < 0) {
M
Matthias Bolte 已提交
3566
        return -1;
3567 3568
    }

M
Matthias Bolte 已提交
3569
    count = esxVI_GetNumberOfSnapshotTrees(rootSnapshotTreeList);
3570 3571 3572

    esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotTreeList);

M
Matthias Bolte 已提交
3573
    return count;
3574 3575 3576 3577 3578 3579
}



static int
esxDomainSnapshotListNames(virDomainPtr domain, char **names, int nameslen,
3580
                           unsigned int flags)
3581
{
M
Matthias Bolte 已提交
3582
    int result;
3583 3584 3585
    esxPrivate *priv = domain->conn->privateData;
    esxVI_VirtualMachineSnapshotTree *rootSnapshotTreeList = NULL;

3586 3587
    virCheckFlags(0, -1);

3588 3589 3590 3591 3592 3593 3594 3595 3596
    if (names == NULL || nameslen < 0) {
        ESX_ERROR(VIR_ERR_INVALID_ARG, "%s", _("Invalid argument"));
        return -1;
    }

    if (nameslen == 0) {
        return 0;
    }

3597
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
3598
        return -1;
3599 3600
    }

3601
    if (esxVI_LookupRootSnapshotTreeList(priv->primary, domain->uuid,
3602
                                         &rootSnapshotTreeList) < 0) {
M
Matthias Bolte 已提交
3603
        return -1;
3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616
    }

    result = esxVI_GetSnapshotTreeNames(rootSnapshotTreeList, names, nameslen);

    esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotTreeList);

    return result;
}



static virDomainSnapshotPtr
esxDomainSnapshotLookupByName(virDomainPtr domain, const char *name,
3617
                              unsigned int flags)
3618 3619 3620 3621 3622 3623 3624
{
    esxPrivate *priv = domain->conn->privateData;
    esxVI_VirtualMachineSnapshotTree *rootSnapshotTreeList = NULL;
    esxVI_VirtualMachineSnapshotTree *snapshotTree = NULL;
    esxVI_VirtualMachineSnapshotTree *snapshotTreeParent = NULL;
    virDomainSnapshotPtr snapshot = NULL;

3625 3626
    virCheckFlags(0, NULL);

3627
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
3628
        return NULL;
3629 3630
    }

3631
    if (esxVI_LookupRootSnapshotTreeList(priv->primary, domain->uuid,
3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654
                                         &rootSnapshotTreeList) < 0 ||
        esxVI_GetSnapshotTreeByName(rootSnapshotTreeList, name, &snapshotTree,
                                    &snapshotTreeParent,
                                    esxVI_Occurrence_RequiredItem) < 0) {
        goto cleanup;
    }

    snapshot = virGetDomainSnapshot(domain, name);

  cleanup:
    esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotTreeList);

    return snapshot;
}



static int
esxDomainHasCurrentSnapshot(virDomainPtr domain, unsigned int flags)
{
    esxPrivate *priv = domain->conn->privateData;
    esxVI_VirtualMachineSnapshotTree *currentSnapshotTree = NULL;

3655
    virCheckFlags(0, -1);
3656

3657
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
3658
        return -1;
3659 3660
    }

3661
    if (esxVI_LookupCurrentSnapshotTree(priv->primary, domain->uuid,
3662 3663
                                        &currentSnapshotTree,
                                        esxVI_Occurrence_OptionalItem) < 0) {
M
Matthias Bolte 已提交
3664
        return -1;
3665 3666 3667
    }

    if (currentSnapshotTree != NULL) {
M
Matthias Bolte 已提交
3668 3669
        esxVI_VirtualMachineSnapshotTree_Free(&currentSnapshotTree);
        return 1;
3670 3671
    }

M
Matthias Bolte 已提交
3672
    return 0;
3673 3674 3675 3676 3677 3678 3679 3680 3681
}



static virDomainSnapshotPtr
esxDomainSnapshotCurrent(virDomainPtr domain, unsigned int flags)
{
    esxPrivate *priv = domain->conn->privateData;
    esxVI_VirtualMachineSnapshotTree *currentSnapshotTree = NULL;
M
Matthias Bolte 已提交
3682
    virDomainSnapshotPtr snapshot = NULL;
3683

3684
    virCheckFlags(0, NULL);
3685

3686
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
3687
        return NULL;
3688 3689
    }

3690
    if (esxVI_LookupCurrentSnapshotTree(priv->primary, domain->uuid,
3691 3692
                                        &currentSnapshotTree,
                                        esxVI_Occurrence_RequiredItem) < 0) {
M
Matthias Bolte 已提交
3693
        return NULL;
3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707
    }

    snapshot = virGetDomainSnapshot(domain, currentSnapshotTree->name);

    esxVI_VirtualMachineSnapshotTree_Free(&currentSnapshotTree);

    return snapshot;
}



static int
esxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, unsigned int flags)
{
M
Matthias Bolte 已提交
3708
    int result = -1;
3709 3710 3711 3712 3713 3714 3715
    esxPrivate *priv = snapshot->domain->conn->privateData;
    esxVI_VirtualMachineSnapshotTree *rootSnapshotList = NULL;
    esxVI_VirtualMachineSnapshotTree *snapshotTree = NULL;
    esxVI_VirtualMachineSnapshotTree *snapshotTreeParent = NULL;
    esxVI_ManagedObjectReference *task = NULL;
    esxVI_TaskInfoState taskInfoState;

3716
    virCheckFlags(0, -1);
3717

3718
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
3719
        return -1;
3720 3721
    }

3722
    if (esxVI_LookupRootSnapshotTreeList(priv->primary, snapshot->domain->uuid,
3723 3724 3725 3726
                                         &rootSnapshotList) < 0 ||
        esxVI_GetSnapshotTreeByName(rootSnapshotList, snapshot->name,
                                    &snapshotTree, &snapshotTreeParent,
                                    esxVI_Occurrence_RequiredItem) < 0) {
M
Matthias Bolte 已提交
3727
        goto cleanup;
3728 3729
    }

3730
    if (esxVI_RevertToSnapshot_Task(priv->primary, snapshotTree->snapshot, NULL,
3731
                                    &task) < 0 ||
3732
        esxVI_WaitForTaskCompletion(priv->primary, task, snapshot->domain->uuid,
3733
                                    esxVI_Occurrence_RequiredItem,
3734
                                    priv->autoAnswer, &taskInfoState) < 0) {
M
Matthias Bolte 已提交
3735
        goto cleanup;
3736 3737 3738 3739 3740
    }

    if (taskInfoState != esxVI_TaskInfoState_Success) {
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
                  _("Could not revert to snapshot '%s'"), snapshot->name);
M
Matthias Bolte 已提交
3741
        goto cleanup;
3742 3743
    }

M
Matthias Bolte 已提交
3744 3745
    result = 0;

3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757
  cleanup:
    esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotList);
    esxVI_ManagedObjectReference_Free(&task);

    return result;
}



static int
esxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, unsigned int flags)
{
M
Matthias Bolte 已提交
3758
    int result = -1;
3759 3760 3761 3762 3763 3764 3765 3766
    esxPrivate *priv = snapshot->domain->conn->privateData;
    esxVI_VirtualMachineSnapshotTree *rootSnapshotList = NULL;
    esxVI_VirtualMachineSnapshotTree *snapshotTree = NULL;
    esxVI_VirtualMachineSnapshotTree *snapshotTreeParent = NULL;
    esxVI_Boolean removeChildren = esxVI_Boolean_False;
    esxVI_ManagedObjectReference *task = NULL;
    esxVI_TaskInfoState taskInfoState;

3767 3768
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN, -1);

3769
    if (esxVI_EnsureSession(priv->primary) < 0) {
M
Matthias Bolte 已提交
3770
        return -1;
3771 3772 3773 3774 3775 3776
    }

    if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN) {
        removeChildren = esxVI_Boolean_True;
    }

3777
    if (esxVI_LookupRootSnapshotTreeList(priv->primary, snapshot->domain->uuid,
3778 3779 3780 3781
                                         &rootSnapshotList) < 0 ||
        esxVI_GetSnapshotTreeByName(rootSnapshotList, snapshot->name,
                                    &snapshotTree, &snapshotTreeParent,
                                    esxVI_Occurrence_RequiredItem) < 0) {
M
Matthias Bolte 已提交
3782
        goto cleanup;
3783 3784
    }

3785
    if (esxVI_RemoveSnapshot_Task(priv->primary, snapshotTree->snapshot,
3786
                                  removeChildren, &task) < 0 ||
3787
        esxVI_WaitForTaskCompletion(priv->primary, task, snapshot->domain->uuid,
3788
                                    esxVI_Occurrence_RequiredItem,
3789
                                    priv->autoAnswer, &taskInfoState) < 0) {
M
Matthias Bolte 已提交
3790
        goto cleanup;
3791 3792 3793 3794 3795
    }

    if (taskInfoState != esxVI_TaskInfoState_Success) {
        ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
                  _("Could not delete snapshot '%s'"), snapshot->name);
M
Matthias Bolte 已提交
3796
        goto cleanup;
3797 3798
    }

M
Matthias Bolte 已提交
3799 3800
    result = 0;

3801 3802 3803 3804 3805 3806 3807 3808 3809
  cleanup:
    esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotList);
    esxVI_ManagedObjectReference_Free(&task);

    return result;
}



3810 3811 3812 3813 3814 3815 3816 3817
static virDriver esxDriver = {
    VIR_DRV_ESX,
    "ESX",
    esxOpen,                         /* open */
    esxClose,                        /* close */
    esxSupportsFeature,              /* supports_feature */
    esxGetType,                      /* type */
    esxGetVersion,                   /* version */
3818
    NULL,                            /* libvirtVersion (impl. in libvirt.c) */
3819 3820 3821
    esxGetHostname,                  /* hostname */
    NULL,                            /* getMaxVcpus */
    esxNodeGetInfo,                  /* nodeGetInfo */
3822
    esxGetCapabilities,              /* getCapabilities */
3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848
    esxListDomains,                  /* listDomains */
    esxNumberOfDomains,              /* numOfDomains */
    NULL,                            /* domainCreateXML */
    esxDomainLookupByID,             /* domainLookupByID */
    esxDomainLookupByUUID,           /* domainLookupByUUID */
    esxDomainLookupByName,           /* domainLookupByName */
    esxDomainSuspend,                /* domainSuspend */
    esxDomainResume,                 /* domainResume */
    esxDomainShutdown,               /* domainShutdown */
    esxDomainReboot,                 /* domainReboot */
    esxDomainDestroy,                /* domainDestroy */
    esxDomainGetOSType,              /* domainGetOSType */
    esxDomainGetMaxMemory,           /* domainGetMaxMemory */
    esxDomainSetMaxMemory,           /* domainSetMaxMemory */
    esxDomainSetMemory,              /* domainSetMemory */
    esxDomainGetInfo,                /* domainGetInfo */
    NULL,                            /* domainSave */
    NULL,                            /* domainRestore */
    NULL,                            /* domainCoreDump */
    esxDomainSetVcpus,               /* domainSetVcpus */
    NULL,                            /* domainPinVcpu */
    NULL,                            /* domainGetVcpus */
    esxDomainGetMaxVcpus,            /* domainGetMaxVcpus */
    NULL,                            /* domainGetSecurityLabel */
    NULL,                            /* nodeGetSecurityModel */
    esxDomainDumpXML,                /* domainDumpXML */
3849
    esxDomainXMLFromNative,          /* domainXMLFromNative */
M
Matthias Bolte 已提交
3850
    esxDomainXMLToNative,            /* domainXMLToNative */
3851 3852 3853
    esxListDefinedDomains,           /* listDefinedDomains */
    esxNumberOfDefinedDomains,       /* numOfDefinedDomains */
    esxDomainCreate,                 /* domainCreate */
3854
    esxDomainCreateWithFlags,        /* domainCreateWithFlags */
M
Matthias Bolte 已提交
3855
    esxDomainDefineXML,              /* domainDefineXML */
3856
    esxDomainUndefine,               /* domainUndefine */
3857
    NULL,                            /* domainAttachDevice */
3858
    NULL,                            /* domainAttachDeviceFlags */
3859
    NULL,                            /* domainDetachDevice */
3860
    NULL,                            /* domainDetachDeviceFlags */
3861
    NULL,                            /* domainUpdateDeviceFlags */
3862 3863 3864 3865 3866 3867 3868 3869 3870 3871
    NULL,                            /* domainGetAutostart */
    NULL,                            /* domainSetAutostart */
    esxDomainGetSchedulerType,       /* domainGetSchedulerType */
    esxDomainGetSchedulerParameters, /* domainGetSchedulerParameters */
    esxDomainSetSchedulerParameters, /* domainSetSchedulerParameters */
    esxDomainMigratePrepare,         /* domainMigratePrepare */
    esxDomainMigratePerform,         /* domainMigratePerform */
    esxDomainMigrateFinish,          /* domainMigrateFinish */
    NULL,                            /* domainBlockStats */
    NULL,                            /* domainInterfaceStats */
3872
    NULL,                            /* domainMemoryStats */
3873 3874
    NULL,                            /* domainBlockPeek */
    NULL,                            /* domainMemoryPeek */
3875
    NULL,                            /* domainGetBlockInfo */
3876
    NULL,                            /* nodeGetCellsFreeMemory */
M
Matthias Bolte 已提交
3877
    esxNodeGetFreeMemory,            /* nodeGetFreeMemory */
3878 3879 3880 3881 3882 3883 3884
    NULL,                            /* domainEventRegister */
    NULL,                            /* domainEventDeregister */
    NULL,                            /* domainMigratePrepare2 */
    NULL,                            /* domainMigrateFinish2 */
    NULL,                            /* nodeDeviceDettach */
    NULL,                            /* nodeDeviceReAttach */
    NULL,                            /* nodeDeviceReset */
C
Chris Lalancette 已提交
3885
    NULL,                            /* domainMigratePrepareTunnel */
3886 3887 3888 3889
    esxIsEncrypted,                  /* isEncrypted */
    esxIsSecure,                     /* isSecure */
    esxDomainIsActive,               /* domainIsActive */
    esxDomainIsPersistent,           /* domainIsPersistent */
J
Jiri Denemark 已提交
3890
    NULL,                            /* cpuCompare */
3891
    NULL,                            /* cpuBaseline */
3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908
    NULL,                            /* domainGetJobInfo */
    NULL,                            /* domainAbortJob */
    NULL,                            /* domainMigrateSetMaxDowntime */
    NULL,                            /* domainEventRegisterAny */
    NULL,                            /* domainEventDeregisterAny */
    NULL,                            /* domainManagedSave */
    NULL,                            /* domainHasManagedSaveImage */
    NULL,                            /* domainManagedSaveRemove */
    esxDomainSnapshotCreateXML,      /* domainSnapshotCreateXML */
    esxDomainSnapshotDumpXML,        /* domainSnapshotDumpXML */
    esxDomainSnapshotNum,            /* domainSnapshotNum */
    esxDomainSnapshotListNames,      /* domainSnapshotListNames */
    esxDomainSnapshotLookupByName,   /* domainSnapshotLookupByName */
    esxDomainHasCurrentSnapshot,     /* domainHasCurrentSnapshot */
    esxDomainSnapshotCurrent,        /* domainSnapshotCurrent */
    esxDomainRevertToSnapshot,       /* domainRevertToSnapshot */
    esxDomainSnapshotDelete,         /* domainSnapshotDelete */
C
Chris Lalancette 已提交
3909
    NULL,                            /* qemuDomainMonitorCommand */
3910 3911 3912 3913 3914 3915 3916
};



int
esxRegister(void)
{
3917 3918 3919 3920 3921
    if (virRegisterDriver(&esxDriver) < 0 ||
        esxInterfaceRegister() < 0 ||
        esxNetworkRegister() < 0 ||
        esxStorageRegister() < 0 ||
        esxDeviceRegister() < 0 ||
M
Matthias Bolte 已提交
3922 3923
        esxSecretRegister() < 0 ||
        esxNWFilterRegister() < 0) {
3924 3925
        return -1;
    }
3926 3927 3928

    return 0;
}