~serge-hallyn/ubuntu/raring/libvirt/libvirt-hugepages

« back to all changes in this revision

Viewing changes to src/esx/esx_vmx.c

  • Committer: James Westby
  • Author(s): Jamie Strandboge
  • Date: 2009-12-02 14:22:21 UTC
  • mfrom: (1.2.3 upstream) (3.4.9 squeeze)
  • Revision ID: james.westby@canonical.com-20091202142221-ltkr0to6h52mla1y
Tags: 0.7.2-4ubuntu1
* Merge from debian testing. Remaining changes:
  - debian/control:
    + Don't build-depend on QEmu
    + Bump bridge-utils, dnsmasq-base, netcat-openbsd, and iptables
      to Depends of libvirt-bin
    + Recommends qemu-kvm (>= 0.11.0-0ubuntu6)
    + Add versioned Conflicts/Replaces to libvirt0 for libvirt0-dbg,
      since we used to ship them as such
    + We call libxen-dev libxen3-dev, so change all references
    + Build-Depends on libxml2-utils
    + Build-Depends on open-iscsi-utils instead of open-iscsi due to
      LP: #414986
  - debian/postinst:
    + rename the libvirt group to libvirtd
    + add each admin user to the libvirtd group
  - debian/libvirt-bin.postrm: rename the libvirt group to libvirtd
  - debian/rules: add DEB_MAKE_CHECK_TARGET := check
  - debian/patches/900[0-7]: updated/refreshed for new paths in 0.7.2
  - debian/patches/series: don't apply 0002-qemu-disable-network.diff.patch
  - AppArmor integration:
    + debian/control: Build-Depends on libapparmor-dev and Suggests
      apparmor (>= 2.3+1289-0ubuntu14)
    + debian/libvirt-bin.dirs: add /etc/apparmor.d/abstractions,
      /etc/apparmor.d/force-complain, /etc/apparmor.d/libvirt,
      /etc/cron.daily and /usr/share/apport/package-hooks
    + add debian/libvirt-bin.cron.daily (LP: #438165)
    + add debian/libvirt-bin.apport
    + debian/libvirt-bin.install: install apparmor profiles, abstractions
      and apport hook
    + debian/postinst: reload apparmor profiles
    + debian/libvirt-bin.postrm: remove apparmor symlinks on purge
    + debian/libvirt-bin.preinst: added to force complain on certain
      upgrades
    + debian/README.Debian: add AppArmor section based on the upstream
      documentation
    + debian/rules: use --with-apparmor and copy apparmor and apport hook to
      debian/tmp
  - Dropped the following patches now included upstream:
    + 0005-Close-logfile-fd-after-spawning-qemu.patch
    + 9090-reenable-nonfile-labels.patch
    + 9091-apparmor.patch
    + 9092-apparmor-autoreconf.patch
* AppArmor integration updates:
  - debian/apparmor/usr.sbin.libvirtd: allow libvirtd access to
    /usr/lib/libvirt/* (LP: #480478)
  - debian/apparmor/libvirt-qemu: allow guests access to
    /etc/pki/libvirt-vnc/** (LP: #484562)
  - debian/libvirt-bin.postinst: 0.7.2 moved /usr/bin/virt-aa-helper to
    /usr/lib/libvirt, so the profile changed from usr.bin.virt-aa-helper
    to usr.lib.libvirt.virt-aa-helper and needs to be migrated. If the user
    made no changes to the old profile, remove it, otherwise, update the
    paths, preserving the shipped usr.lib.libvirt.virt-aa-helper
  - update to 0.7.4 version of the sVirt AppArmor driver (can be dropped in
    0.7.4):
    + debian/patches/9008-apparmor-caps-mockup.patch
    + debian/patches/9009-apparmor-lp453335.patch
    + debian/patches/9010-apparmor-lp460271.patch
    + debian/patches/9011-apparmor-code-cleanups.patch
  - add virt-aa-helper-test and examples/apparmor that were omitted from the
    upstream tarball (can be dropped in 0.7.5):
    + debian/patches/9012-apparmor-add-virt-aa-helper-test.patch
    + debian/patches/9013-apparmor-examples.patch
    + debian/rules: add post-patches target to make virt-aa-helper-test
      executable
* debian/patches/0005-Fix-SELinux-linking-issues.patch: updated to work
  when both apparmor and selinux are available. This patch should be
  dropped in 0.7.4.
* debian/patches/9007-default-config-test-case.patch: updated to not fail
  if building in a deep directory
* debian/patches/9014-event-fuzz.patch: add a little fuzz to not be quite
  so precise with expected expiry time. Fixes FTBFS with HZ=100 kernels.
  Can be dropped in 0.7.5.
* debian/patches/9015-hal-startup-failure-is-nonfatal.patch: disable hal
  driver if hald is not running instead of dying. Can be dropped in
  0.7.4.
* debian/control: temporarily remove Build-Depends on libcap-ng-dev, which
  isn't available in Ubuntu main yet
* revert change to new source format 3.0 (quilt) since Launchpad can't
  handle it yet (see LP: #293106)

Show diffs side-by-side

added added

removed removed

Lines of Context:
58
58
def->os
59
59
 
60
60
->type = "hvm"
61
 
->arch
 
61
->arch = <arch>                   <=>   guestOS = "<value>"                     # if <value> ends with -64 than <arch> is x86_64, otherwise <arch> is i686
62
62
->machine
63
63
->nBootDevs
64
64
->bootDevs
98
98
->device = _DISK_DEVICE_DISK      <=>   scsi0:0.deviceType = "scsi-hardDisk"    # defaults to ?
99
99
->bus = _DISK_BUS_SCSI
100
100
->src = <value>.vmdk              <=>   scsi0:0.fileName = "<value>.vmdk"
101
 
->dst = sd[<controller> * 16 + <id> mapped to [a-z]+]
 
101
->dst = sd[<controller> * 15 + <id> mapped to [a-z]+]
102
102
->driverName = <driver>           <=>   scsi0.virtualDev = "<driver>"           # default depends on guestOS value
103
103
->driverType
104
104
->cachemode                       <=>   scsi0:0.writeThrough = "<value>"        # defaults to false, true -> _DISK_CACHE_WRITETHRU, false _DISK_CACHE_DEFAULT
109
109
 
110
110
## disks: ide hard drive from .vmdk image ######################################
111
111
 
112
 
                                        ide0.present = "true"                   # defaults to "false"
113
112
                                        ide0:0.present = "true"                 # defaults to "false"
114
113
                                        ide0:0.startConnected = "true"          # defaults to "true"
115
114
 
143
142
->device = _DISK_DEVICE_CDROM     <=>   scsi0:0.deviceType = "cdrom-image"      # defaults to ?
144
143
->bus = _DISK_BUS_SCSI
145
144
->src = <value>.iso               <=>   scsi0:0.fileName = "<value>.iso"
146
 
->dst = sd[<controller> * 16 + <id> mapped to [a-z]+]
 
145
->dst = sd[<controller> * 15 + <id> mapped to [a-z]+]
147
146
->driverName = <driver>           <=>   scsi0.virtualDev = "<driver>"           # default depends on guestOS value
148
147
->driverType
149
148
->cachemode
154
153
 
155
154
## disks: ide cdrom from .iso image ############################################
156
155
 
157
 
                                        ide0.present = "true"                   # defaults to "false"
158
156
                                        ide0:0.present = "true"                 # defaults to "false"
159
157
                                        ide0:0.startConnected = "true"          # defaults to "true"
160
158
 
194
192
 
195
193
## disks: ide cdrom from host device ###########################################
196
194
 
197
 
                                        ide0.present = "true"                   # defaults to "false"
198
195
                                        ide0:0.present = "true"                 # defaults to "false"
199
196
                                        ide0:0.startConnected = "true"          # defaults to "true"
200
197
                                        ide0:0.clientDevice = "false"           # defaults to "false"
276
273
                                        ethernet0.addressType = "static"        # default to "generated"
277
274
->mac = <value>                   <=>   ethernet0.address = "<value>"
278
275
 
 
276
 
 
277
                                        ethernet0.addressType = "vpx"           # default to "generated"
 
278
->mac = <value>                   <=>   ethernet0.generatedAddress = "<value>"
 
279
 
279
280
                                                                                # 00:0c:29 prefix for autogenerated mac's
280
281
                                                                                # 00:50:56 prefix for manual configured mac's
281
282
                                                                                # 00:05:69 old prefix from esx 1.5
285
286
 
286
287
...
287
288
->type = _NET_TYPE_BRIDGE         <=>   ethernet0.connectionType = "bridged"    # defaults to "bridged"
 
289
->data.bridge.brname = <value>    <=>   ethernet0.networkName = "<value>"
288
290
 
289
291
 
290
292
## nets: hostonly ##############################################################
291
293
 
292
 
...                                                                             # FIXME: maybe not supported by ESX?
 
294
...                                                                             # FIXME: Investigate if ESX supports this
293
295
->type = _NET_TYPE_NETWORK        <=>   ethernet0.connectionType = "hostonly"   # defaults to "bridged"
294
296
 
295
297
 
296
298
## nets: nat ###################################################################
297
299
 
298
 
...                                                                             # FIXME: maybe not supported by ESX?
 
300
...                                                                             # FIXME: Investigate if ESX supports this
299
301
->type = _NET_TYPE_USER           <=>   ethernet0.connectionType = "nat"        # defaults to "bridged"
300
302
 
301
303
 
303
305
 
304
306
...
305
307
->type = _NET_TYPE_BRIDGE         <=>   ethernet0.connectionType = "custom"     # defaults to "bridged"
306
 
->data.bridge.brname = <value>    <=>   ethernet0.vnet = "<value>"
 
308
->data.bridge.brname = <value>    <=>   ethernet0.networkName = "<value>"
 
309
->ifname = <value>                <=>   ethernet0.vnet = "<value>"
307
310
 
308
311
 
309
312
 
324
327
->type = _CHR_TYPE_DEV            <=>   serial0.fileType = "device"
325
328
->data.file.path = <value>        <=>   serial0.fileName = "<value>"            # e.g. "/dev/ttyS0"
326
329
???                               <=>   serial0.tryNoRxLoss = "false"           # defaults to "false", FIXME: not representable
 
330
???                               <=>   serial0.yieldOnMsrRead = "true"         # defaults to "false", FIXME: not representable
327
331
 
328
332
 
329
333
## serials: file ###############################################################
331
335
->type = _CHR_TYPE_FILE           <=>   serial0.fileType = "file"
332
336
->data.file.path = <value>        <=>   serial0.fileName = "<value>"            # e.g. "serial0.file"
333
337
???                               <=>   serial0.tryNoRxLoss = "false"           # defaults to "false", FIXME: not representable
 
338
???                               <=>   serial0.yieldOnMsrRead = "true"         # defaults to "false", FIXME: not representable
334
339
 
335
340
 
336
341
## serials: pipe, far end -> app ###############################################
337
342
 
338
343
->type = _CHR_TYPE_PIPE           <=>   serial0.fileType = "pipe"
339
344
->data.file.path = <value>        <=>   serial0.fileName = "<value>"            # e.g. "serial0.pipe"
340
 
???                               <=>   serial0.pipe.endPoint = "client"        # defaults to "server", FIXME: not representable
 
345
???                               <=>   serial0.pipe.endPoint = "client"        # defaults to ?, FIXME: not representable
341
346
???                               <=>   serial0.tryNoRxLoss = "true"            # defaults to "false", FIXME: not representable
 
347
???                               <=>   serial0.yieldOnMsrRead = "true"         # defaults to "false", FIXME: not representable
342
348
 
343
349
->type = _CHR_TYPE_PIPE           <=>   serial0.fileType = "pipe"
344
350
->data.file.path = <value>        <=>   serial0.fileName = "<value>"            # e.g. "serial0.pipe"
345
 
???                               <=>   serial0.pipe.endPoint = "server"        # defaults to "server", FIXME: not representable
 
351
???                               <=>   serial0.pipe.endPoint = "server"        # defaults to ?, FIXME: not representable
346
352
???                               <=>   serial0.tryNoRxLoss = "true"            # defaults to "false", FIXME: not representable
 
353
???                               <=>   serial0.yieldOnMsrRead = "true"         # defaults to "false", FIXME: not representable
347
354
 
348
355
 
349
356
## serials: pipe, far end -> vm ################################################
350
357
 
351
358
->type = _CHR_TYPE_PIPE           <=>   serial0.fileType = "pipe"
352
359
->data.file.path = <value>        <=>   serial0.fileName = "<value>"            # e.g. "serial0.pipe"
353
 
???                               <=>   serial0.pipe.endPoint = "client"        # defaults to "server", FIXME: not representable
 
360
???                               <=>   serial0.pipe.endPoint = "client"        # defaults to ?, FIXME: not representable
354
361
???                               <=>   serial0.tryNoRxLoss = "false"           # defaults to "false", FIXME: not representable
 
362
???                               <=>   serial0.yieldOnMsrRead = "true"         # defaults to "false", FIXME: not representable
355
363
 
356
364
->type = _CHR_TYPE_PIPE           <=>   serial0.fileType = "pipe"
357
365
->data.file.path = <value>        <=>   serial0.fileName = "<value>"            # e.g. "serial0.pipe"
358
 
???                               <=>   serial0.pipe.endPoint = "server"        # defaults to "server", FIXME: not representable
 
366
???                               <=>   serial0.pipe.endPoint = "server"        # defaults to ?, FIXME: not representable
359
367
???                               <=>   serial0.tryNoRxLoss = "false"           # defaults to "false", FIXME: not representable
 
368
???                               <=>   serial0.yieldOnMsrRead = "true"         # defaults to "false", FIXME: not representable
360
369
 
361
370
 
362
371
 
385
394
->data.file.path = <value>        <=>   parallel0.fileName = "<value>"          # e.g. "parallel0.file"
386
395
???                               <=>   parallel0.bidirectional = "<value>"     # must be "false" for fileType = "file", FIXME: not representable
387
396
 
 
397
 
 
398
 
 
399
################################################################################
 
400
## sound #######################################################################
 
401
 
 
402
                                        sound.present = "true"                  # defaults to "false"
 
403
                                        sound.startConnected = "true"           # defaults to "true"
 
404
                                        sound.autodetect = "true"
 
405
                                        sound.fileName = "-1"
 
406
 
 
407
                                        FIXME: Investigate if ESX supports this,
 
408
                                               at least the VI Client GUI has no
 
409
                                               options to add a sound device, but
 
410
                                               the VI API contains a VirtualSoundCard
 
411
 
388
412
*/
389
413
 
390
414
#define VIR_FROM_THIS VIR_FROM_ESX
391
415
 
392
416
#define ESX_ERROR(conn, code, fmt...)                                         \
393
 
    virReportErrorHelper (conn, VIR_FROM_ESX, code, __FILE__, __FUNCTION__,   \
394
 
                          __LINE__, fmt)
 
417
    virReportErrorHelper(conn, VIR_FROM_ESX, code, __FILE__, __FUNCTION__,    \
 
418
                         __LINE__, fmt)
395
419
 
396
420
 
397
421
 
398
422
#define ESX_BUILD_VMX_NAME(_suffix)                                           \
399
 
    do {                                                                      \
400
 
        strncpy(_suffix##_name, prefix, sizeof (_suffix##_name) - 1);         \
401
 
        _suffix##_name[sizeof (_suffix##_name) - 1] = '\0';                   \
402
 
        strncat(_suffix##_name, "."#_suffix,                                  \
403
 
                sizeof (_suffix##_name) - 1 - strlen(_suffix##_name));        \
404
 
    } while (0)
 
423
    snprintf(_suffix##_name, sizeof(_suffix##_name), "%s."#_suffix, prefix);
 
424
 
 
425
 
 
426
 
 
427
int
 
428
esxVMX_SCSIDiskNameToControllerAndID(virConnectPtr conn, const char *name,
 
429
                                     int *controller, int *id)
 
430
{
 
431
    int idx;
 
432
 
 
433
    if (! STRPREFIX(name, "sd")) {
 
434
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
435
                  "Expecting domain XML attribute 'dev' of entry "
 
436
                  "'devices/disk/target' to start with 'sd'");
 
437
        return -1;
 
438
    }
 
439
 
 
440
    idx = virDiskNameToIndex(name);
 
441
 
 
442
    if (idx < 0) {
 
443
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
444
                  "Could not parse valid disk index from '%s'", name);
 
445
        return -1;
 
446
    }
 
447
 
 
448
    /* Each of the 4 SCSI controllers offers 15 IDs for devices */
 
449
    if (idx >= (4 * 15)) {
 
450
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
451
                  "SCSI disk index (parsed from '%s') is too large", name);
 
452
        return -1;
 
453
    }
 
454
 
 
455
    *controller = idx / 15;
 
456
    *id = idx % 15;
 
457
 
 
458
    /* Skip the controller ifself with ID 7 */
 
459
    if (*id >= 7) {
 
460
        ++(*id);
 
461
    }
 
462
 
 
463
    return 0;
 
464
}
 
465
 
 
466
 
 
467
 
 
468
int
 
469
esxVMX_IDEDiskNameToControllerAndID(virConnectPtr conn, const char *name,
 
470
                                    int *controller, int *id)
 
471
{
 
472
    int idx;
 
473
 
 
474
    if (! STRPREFIX(name, "hd")) {
 
475
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
476
                  "Expecting domain XML attribute 'dev' of entry "
 
477
                  "'devices/disk/target' to start with 'hd'");
 
478
        return -1;
 
479
    }
 
480
 
 
481
    idx = virDiskNameToIndex(name);
 
482
 
 
483
    if (idx < 0) {
 
484
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
485
                  "Could not parse valid disk index from '%s'", name);
 
486
        return -1;
 
487
    }
 
488
 
 
489
    /* Each of the 2 IDE controllers offers 2 IDs for devices */
 
490
    if (idx >= (2 * 2)) {
 
491
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
492
                  "IDE disk index (parsed from '%s') is too large", name);
 
493
        return -1;
 
494
    }
 
495
 
 
496
    *controller = idx / 2;
 
497
    *id = idx % 2;
 
498
 
 
499
    return 0;
 
500
}
 
501
 
 
502
 
 
503
 
 
504
int
 
505
esxVMX_FloppyDiskNameToController(virConnectPtr conn, const char *name,
 
506
                                  int *controller)
 
507
{
 
508
    int idx;
 
509
 
 
510
    if (! STRPREFIX(name, "fd")) {
 
511
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
512
                  "Expecting domain XML attribute 'dev' of entry "
 
513
                  "'devices/disk/target' to start with 'fd'");
 
514
        return -1;
 
515
    }
 
516
 
 
517
    idx = virDiskNameToIndex(name);
 
518
 
 
519
    if (idx < 0) {
 
520
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
521
                  "Could not parse valid disk index from '%s'", name);
 
522
        return -1;
 
523
    }
 
524
 
 
525
    if (idx >= 2) {
 
526
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
527
                  "Floppy disk index (parsed from '%s') is too large", name);
 
528
        return -1;
 
529
    }
 
530
 
 
531
    *controller = idx;
 
532
 
 
533
    return 0;
 
534
}
 
535
 
 
536
 
 
537
 
 
538
int
 
539
esxVMX_GatherSCSIControllers(virConnectPtr conn, virDomainDefPtr def,
 
540
                             char *virtualDev[4], int present[4])
 
541
{
 
542
    virDomainDiskDefPtr disk;
 
543
    int i, controller, id;
 
544
 
 
545
    /* Check for continuous use of the same virtualDev per SCSI controller */
 
546
    for (i = 0; i < def->ndisks; ++i) {
 
547
        disk = def->disks[i];
 
548
 
 
549
        if (disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
 
550
            continue;
 
551
        }
 
552
 
 
553
        if (disk->driverName != NULL &&
 
554
            STRCASENEQ(disk->driverName, "buslogic") &&
 
555
            STRCASENEQ(disk->driverName, "lsilogic")) {
 
556
            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
557
                      "Expecting domain XML entry 'devices/disk/target' to be "
 
558
                      "'buslogic' or 'lsilogic' but found '%s'",
 
559
                      disk->driverName);
 
560
            return -1;
 
561
        }
 
562
 
 
563
        if (esxVMX_SCSIDiskNameToControllerAndID(conn, disk->dst,
 
564
                                                 &controller, &id) < 0) {
 
565
            return -1;
 
566
        }
 
567
 
 
568
        present[controller] = 1;
 
569
 
 
570
        if (virtualDev[controller] == NULL) {
 
571
            virtualDev[controller] = disk->driverName;
 
572
        } else if (STRCASENEQ(virtualDev[controller], disk->driverName)) {
 
573
            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
574
                      "Inconsistent driver usage ('%s' is not '%s') on SCSI "
 
575
                      "controller index %d", virtualDev[controller],
 
576
                      disk->driverName, controller);
 
577
            return -1;
 
578
        }
 
579
    }
 
580
 
 
581
    return 0;
 
582
}
 
583
 
 
584
 
 
585
 
 
586
char *
 
587
esxVMX_AbsolutePathToDatastoreRelatedPath(virConnectPtr conn,
 
588
                                          esxVI_Context *ctx,
 
589
                                          const char *absolutePath)
 
590
{
 
591
    char *datastoreRelatedPath = NULL;
 
592
    char *preliminaryDatastoreName = NULL;
 
593
    char *directoryAndFileName = NULL;
 
594
    esxVI_DynamicProperty *dynamicProperty = NULL;
 
595
    esxVI_ObjectContent *datastore = NULL;
 
596
    const char *datastoreName = NULL;
 
597
 
 
598
    if (sscanf(absolutePath, "/vmfs/volumes/%a[^/]/%a[^\n]",
 
599
               &preliminaryDatastoreName, &directoryAndFileName) != 2) {
 
600
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
601
                  "Absolute path '%s' doesn't have expected format "
 
602
                  "'/vmfs/volumes/<datastore>/<path>'", absolutePath);
 
603
        goto failure;
 
604
    }
 
605
 
 
606
    if (ctx != NULL) {
 
607
        if (esxVI_LookupDatastoreByName(conn, ctx, preliminaryDatastoreName,
 
608
                                        NULL, &datastore,
 
609
                                        esxVI_Occurence_RequiredItem) < 0) {
 
610
            goto failure;
 
611
        }
 
612
 
 
613
        for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
 
614
             dynamicProperty = dynamicProperty->_next) {
 
615
            if (STREQ(dynamicProperty->name, "summary.accessible")) {
 
616
                /* Ignore it */
 
617
            } else if (STREQ(dynamicProperty->name, "summary.name")) {
 
618
                if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val,
 
619
                                             esxVI_Type_String) < 0) {
 
620
                    goto failure;
 
621
                }
 
622
 
 
623
                datastoreName = dynamicProperty->val->string;
 
624
                break;
 
625
            } else if (STREQ(dynamicProperty->name, "summary.url")) {
 
626
                /* Ignore it */
 
627
            } else {
 
628
                VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
 
629
            }
 
630
        }
 
631
 
 
632
        if (datastoreName == NULL) {
 
633
            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
634
                      "Could not retrieve datastore name for absolute path '%s'",
 
635
                      absolutePath);
 
636
            goto failure;
 
637
        }
 
638
    } else {
 
639
        datastoreName = preliminaryDatastoreName;
 
640
    }
 
641
 
 
642
    if (virAsprintf(&datastoreRelatedPath, "[%s] %s", datastoreName,
 
643
                    directoryAndFileName) < 0) {
 
644
        virReportOOMError(conn);
 
645
        goto failure;
 
646
    }
 
647
 
 
648
    /* FIXME: Check if referenced path/file really exists */
 
649
 
 
650
  cleanup:
 
651
    VIR_FREE(preliminaryDatastoreName);
 
652
    VIR_FREE(directoryAndFileName);
 
653
    esxVI_ObjectContent_Free(&datastore);
 
654
 
 
655
    return datastoreRelatedPath;
 
656
 
 
657
  failure:
 
658
    VIR_FREE(datastoreRelatedPath);
 
659
 
 
660
    goto cleanup;
 
661
}
 
662
 
 
663
 
 
664
 
 
665
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
666
 * VMX -> Domain XML
 
667
 */
 
668
 
 
669
char *
 
670
esxVMX_ParseFileName(virConnectPtr conn, esxVI_Context *ctx,
 
671
                     const char *fileName, const char *datastoreName,
 
672
                     const char *directoryName)
 
673
{
 
674
    char *src = NULL;
 
675
 
 
676
    if (STRPREFIX(fileName, "/vmfs/volumes/")) {
 
677
        /* Found absolute path referencing a file inside a datastore */
 
678
        return esxVMX_AbsolutePathToDatastoreRelatedPath(conn, ctx, fileName);
 
679
    } else if (STRPREFIX(fileName, "/")) {
 
680
        /* Found absolute path referencing a file outside a datastore */
 
681
        src = strdup(fileName);
 
682
 
 
683
        if (src == NULL) {
 
684
            virReportOOMError(conn);
 
685
            return NULL;
 
686
        }
 
687
 
 
688
        /* FIXME: Check if referenced path/file really exists */
 
689
 
 
690
        return src;
 
691
    } else if (strchr(fileName, '/') != NULL) {
 
692
        /* Found relative path, this is not supported */
 
693
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
694
                  "Found relative path '%s' in VMX file, this is not "
 
695
                  "supported", fileName);
 
696
        return NULL;
 
697
    } else {
 
698
        /* Found single file name referencing a file inside a datastore */
 
699
        if (virAsprintf(&src, "[%s] %s/%s", datastoreName, directoryName,
 
700
                        fileName) < 0) {
 
701
            virReportOOMError(conn);
 
702
            return NULL;
 
703
        }
 
704
 
 
705
        /* FIXME: Check if referenced path/file really exists */
 
706
 
 
707
        return src;
 
708
    }
 
709
}
405
710
 
406
711
 
407
712
 
408
713
virDomainDefPtr
409
 
esxVMX_ParseConfig(virConnectPtr conn, const char *vmx,
 
714
esxVMX_ParseConfig(virConnectPtr conn, esxVI_Context *ctx, const char *vmx,
 
715
                   const char *datastoreName, const char *directoryName,
410
716
                   esxVI_APIVersion apiVersion)
411
717
{
412
718
    virConfPtr conf = NULL;
417
723
    long long memory = 0;
418
724
    long long numvcpus = 0;
419
725
    char *sched_cpu_affinity = NULL;
 
726
    char *guestOS = NULL;
420
727
    int controller;
421
728
    int port;
422
729
    int present;
437
744
    def->virtType = VIR_DOMAIN_VIRT_VMWARE; /* FIXME: maybe add VIR_DOMAIN_VIRT_ESX ? */
438
745
    def->id = -1;
439
746
 
 
747
    /* vmx:config.version */
440
748
    if (esxUtil_GetConfigLong(conn, conf, "config.version",
441
749
                              &config_version, 0, 0) < 0) {
442
750
        goto failure;
449
757
        goto failure;
450
758
    }
451
759
 
 
760
    /* vmx:virtualHW.version */
452
761
    if (esxUtil_GetConfigLong(conn, conf, "virtualHW.version",
453
762
                              &virtualHW_version, 0, 0) < 0) {
454
763
        goto failure;
491
800
        goto failure;
492
801
    }
493
802
 
494
 
    /* def:uuid */
 
803
    /* vmx:uuid.bios -> def:uuid */
495
804
    /* FIXME: Need to handle 'uuid.action = "create"' */
496
805
    if (esxUtil_GetConfigUUID(conn, conf, "uuid.bios", def->uuid, 1) < 0) {
497
806
        goto failure;
498
807
    }
499
808
 
500
 
    /* def:name */
 
809
    /* vmx:displayName -> def:name */
501
810
    if (esxUtil_GetConfigString(conn, conf, "displayName",
502
811
                                &def->name, 1) < 0) {
503
812
        goto failure;
504
813
    }
505
814
 
506
 
    /* def:maxmem */
 
815
    /* vmx:memsize -> def:maxmem */
507
816
    if (esxUtil_GetConfigLong(conn, conf, "memsize", &memsize, 32, 1) < 0) {
508
817
        goto failure;
509
818
    }
517
826
 
518
827
    def->maxmem = memsize * 1024; /* Scale from megabytes to kilobytes */
519
828
 
520
 
    /* def:memory */
 
829
    /* vmx:sched.mem.max -> def:memory */
521
830
    if (esxUtil_GetConfigLong(conn, conf, "sched.mem.max", &memory,
522
831
                              memsize, 1) < 0) {
523
832
        goto failure;
533
842
        def->memory = def->maxmem;
534
843
    }
535
844
 
536
 
    /* def:vcpus */
 
845
    /* vmx:numvcpus -> def:vcpus */
537
846
    if (esxUtil_GetConfigLong(conn, conf, "numvcpus", &numvcpus, 1, 1) < 0) {
538
847
        goto failure;
539
848
    }
547
856
 
548
857
    def->vcpus = numvcpus;
549
858
 
550
 
    /* def:cpumask */
 
859
    /* vmx:sched.cpu.affinity -> def:cpumask */
551
860
    // VirtualMachine:config.cpuAffinity.affinitySet
552
861
    if (esxUtil_GetConfigString(conn, conf, "sched.cpu.affinity",
553
862
                                &sched_cpu_affinity, 1) < 0) {
631
940
        goto failure;
632
941
    }
633
942
 
 
943
    /* vmx:guestOS -> def:os.arch */
 
944
    if (esxUtil_GetConfigString(conn, conf, "guestOS", &guestOS, 1) < 0) {
 
945
        goto failure;
 
946
    }
 
947
 
 
948
    if (guestOS != NULL && virFileHasSuffix(guestOS, "-64")) {
 
949
        def->os.arch = strdup("x86_64");
 
950
    } else {
 
951
        def->os.arch = strdup("i686");
 
952
    }
 
953
 
 
954
    if (def->os.arch == NULL) {
 
955
        virReportOOMError(conn);
 
956
        goto failure;
 
957
    }
 
958
 
634
959
/*
635
960
    def->emulator
636
961
    def->features*/
641
966
    /* def:graphics */
642
967
    /* FIXME */
643
968
 
644
 
    /* def:disks: 4 * 16 scsi + 2 * 2 ide + 2 floppy = 70 */
645
 
    if (VIR_ALLOC_N(def->disks, 72) < 0) {
 
969
    /* def:disks: 4 * 15 scsi + 2 * 2 ide + 2 floppy = 66 */
 
970
    if (VIR_ALLOC_N(def->disks, 66) < 0) {
646
971
        virReportOOMError(conn);
647
972
        goto failure;
648
973
    }
671
996
                continue;
672
997
            }
673
998
 
674
 
            if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_DISK,
 
999
            if (esxVMX_ParseDisk(conn, ctx, conf, VIR_DOMAIN_DISK_DEVICE_DISK,
675
1000
                                 VIR_DOMAIN_DISK_BUS_SCSI, controller, id,
676
 
                                 scsi_virtualDev,
 
1001
                                 scsi_virtualDev, datastoreName, directoryName,
677
1002
                                 &def->disks[def->ndisks]) < 0) {
678
1003
                goto failure;
679
1004
            }
683
1008
                continue;
684
1009
            }
685
1010
 
686
 
            if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_CDROM,
 
1011
            if (esxVMX_ParseDisk(conn, ctx, conf, VIR_DOMAIN_DISK_DEVICE_CDROM,
687
1012
                                 VIR_DOMAIN_DISK_BUS_SCSI, controller, id,
688
 
                                 scsi_virtualDev,
 
1013
                                 scsi_virtualDev, datastoreName, directoryName,
689
1014
                                 &def->disks[def->ndisks]) < 0) {
690
1015
                goto failure;
691
1016
            }
699
1024
    /* def:disks (ide) */
700
1025
    for (controller = 0; controller < 2; ++controller) {
701
1026
        for (id = 0; id < 2; ++id) {
702
 
            if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_DISK,
 
1027
            if (esxVMX_ParseDisk(conn, ctx, conf, VIR_DOMAIN_DISK_DEVICE_DISK,
703
1028
                                 VIR_DOMAIN_DISK_BUS_IDE, controller, id,
704
 
                                 NULL, &def->disks[def->ndisks]) < 0) {
 
1029
                                 NULL, datastoreName, directoryName,
 
1030
                                 &def->disks[def->ndisks]) < 0) {
705
1031
                goto failure;
706
1032
            }
707
1033
 
710
1036
                continue;
711
1037
            }
712
1038
 
713
 
            if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_CDROM,
 
1039
            if (esxVMX_ParseDisk(conn, ctx, conf, VIR_DOMAIN_DISK_DEVICE_CDROM,
714
1040
                                 VIR_DOMAIN_DISK_BUS_IDE, controller, id,
715
 
                                 NULL, &def->disks[def->ndisks]) < 0) {
 
1041
                                 NULL, datastoreName, directoryName,
 
1042
                                 &def->disks[def->ndisks]) < 0) {
716
1043
                goto failure;
717
1044
            }
718
1045
 
724
1051
 
725
1052
    /* def:disks (floppy) */
726
1053
    for (controller = 0; controller < 2; ++controller) {
727
 
        if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_FLOPPY,
 
1054
        if (esxVMX_ParseDisk(conn, ctx, conf, VIR_DOMAIN_DISK_DEVICE_FLOPPY,
728
1055
                             VIR_DOMAIN_DISK_BUS_FDC, controller, -1, NULL,
 
1056
                             datastoreName, directoryName,
729
1057
                             &def->disks[def->ndisks]) < 0) {
730
1058
            goto failure;
731
1059
        }
775
1103
    def->nserials = 0;
776
1104
 
777
1105
    for (port = 0; port < 4; ++port) {
778
 
        if (esxVMX_ParseSerial(conn, conf, port,
 
1106
        if (esxVMX_ParseSerial(conn, ctx, conf, port,
 
1107
                               datastoreName, directoryName,
779
1108
                               &def->serials[def->nserials]) < 0) {
780
1109
            goto failure;
781
1110
        }
794
1123
    def->nparallels = 0;
795
1124
 
796
1125
    for (port = 0; port < 3; ++port) {
797
 
        if (esxVMX_ParseParallel(conn, conf, port,
 
1126
        if (esxVMX_ParseParallel(conn, ctx, conf, port,
 
1127
                                 datastoreName, directoryName,
798
1128
                                 &def->parallels[def->nparallels]) < 0) {
799
1129
            goto failure;
800
1130
        }
804
1134
        }
805
1135
    }
806
1136
 
807
 
cleanup:
 
1137
  cleanup:
808
1138
    virConfFree(conf);
809
1139
    VIR_FREE(sched_cpu_affinity);
 
1140
    VIR_FREE(guestOS);
810
1141
    VIR_FREE(scsi_virtualDev);
811
1142
 
812
1143
    return def;
813
1144
 
814
 
failure:
 
1145
  failure:
815
1146
    virDomainDefFree(def);
816
1147
    def = NULL;
817
1148
 
839
1170
        goto failure;
840
1171
    }
841
1172
 
842
 
    strncpy(present_name, "scsiX.present", sizeof (virtualDev_name));
843
 
    strncpy(virtualDev_name, "scsiX.virtualDev", sizeof (virtualDev_name));
844
 
 
845
 
    present_name[4] = '0' + controller;
846
 
    virtualDev_name[4] = '0' + controller;
 
1173
    snprintf(present_name, sizeof(present_name), "scsi%d.present", controller);
 
1174
    snprintf(virtualDev_name, sizeof(virtualDev_name), "scsi%d.virtualDev",
 
1175
             controller);
847
1176
 
848
1177
    if (esxUtil_GetConfigBoolean(conn, conf, present_name, present, 0, 1) < 0) {
849
1178
        goto failure;
854
1183
    }
855
1184
 
856
1185
    if (esxUtil_GetConfigString(conn, conf, virtualDev_name,
857
 
                                virtualDev, 0) < 0) {
 
1186
                                virtualDev, 1) < 0) {
858
1187
        goto failure;
859
1188
    }
860
1189
 
869
1198
 
870
1199
    return 0;
871
1200
 
872
 
failure:
 
1201
  failure:
873
1202
    VIR_FREE(*virtualDev);
874
1203
 
875
1204
    return -1;
880
1209
char *
881
1210
esxVMX_IndexToDiskName(virConnectPtr conn, int idx, const char *prefix)
882
1211
{
883
 
    char buffer[32] = "";
884
1212
    char *name = NULL;
885
 
    size_t length = strlen(prefix);
886
1213
 
887
 
    if (length > sizeof (buffer) - 2 - 1) {
 
1214
    if (idx < 0) {
888
1215
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
889
 
                  "Disk name prefix '%s' is too long", prefix);
890
 
        return NULL;
891
 
    }
892
 
 
893
 
    strncpy(buffer, prefix, sizeof (buffer) - 1);
894
 
    buffer[sizeof (buffer) - 1] = '\0';
895
 
 
896
 
    if (idx < 26) {
897
 
        buffer[length] = 'a' + idx;
 
1216
                  "Disk index %d is negative", idx);
 
1217
    } else if (idx < 26) {
 
1218
        if (virAsprintf(&name, "%s%c", prefix, 'a' + idx) < 0)
 
1219
            virReportOOMError(conn);
898
1220
    } else if (idx < 702) {
899
 
        buffer[length] = 'a' + idx / 26 - 1;
900
 
        buffer[length + 1] = 'a' + idx % 26;
 
1221
        if (virAsprintf(&name, "%s%c%c", prefix, 'a' + idx / 26 - 1,
 
1222
                        'a' + (idx % 26)) < 0)
 
1223
            virReportOOMError(conn);
901
1224
    } else {
902
1225
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
903
1226
                  "Disk index %d is too large", idx);
904
 
        return NULL;
905
 
    }
906
 
 
907
 
    name = strdup(buffer);
908
 
 
909
 
    if (name == NULL) {
910
 
        virReportOOMError(conn);
911
 
        return NULL;
912
1227
    }
913
1228
 
914
1229
    return name;
932
1247
};*/
933
1248
 
934
1249
int
935
 
esxVMX_ParseDisk(virConnectPtr conn, virConfPtr conf, int device, int bus,
936
 
                 int controller, int id, const char *virtualDev,
937
 
                 virDomainDiskDefPtr *def)
 
1250
esxVMX_ParseDisk(virConnectPtr conn, esxVI_Context *ctx, virConfPtr conf,
 
1251
                 int device, int bus, int controller, int id,
 
1252
                 const char *virtualDev, const char *datastoreName,
 
1253
                 const char *directoryName, virDomainDiskDefPtr *def)
938
1254
{
939
1255
    /*
940
1256
     *     device = {VIR_DOMAIN_DISK_DEVICE_DISK, VIR_DOMAIN_DISK_DEVICE_CDROM}
1015
1331
                goto failure;
1016
1332
            }
1017
1333
 
1018
 
            (*def)->dst = esxVMX_IndexToDiskName(conn, controller * 16 + id,
1019
 
                                                 "sd");
 
1334
            (*def)->dst =
 
1335
               esxVMX_IndexToDiskName
 
1336
                 (conn, controller * 15 + (id < 7 ? id : id - 1), "sd");
1020
1337
 
1021
1338
            if ((*def)->dst == NULL) {
1022
1339
                goto failure;
1057
1374
            }
1058
1375
        } else {
1059
1376
            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
1060
 
                      "Unsupported bus type '%s' for '%s' device type",
1061
 
                      virDomainDiskBusTypeToString (bus),
1062
 
                      virDomainDiskDeviceTypeToString (device));
 
1377
                      "Unsupported bus type '%s' for device type '%s'",
 
1378
                      virDomainDiskBusTypeToString(bus),
 
1379
                      virDomainDiskDeviceTypeToString(device));
1063
1380
            goto failure;
1064
1381
        }
1065
1382
    } else if (device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
1083
1400
            }
1084
1401
        } else {
1085
1402
            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
1086
 
                      "Unsupported bus type '%s' for '%s' device type",
1087
 
                      virDomainDiskBusTypeToString (bus),
1088
 
                      virDomainDiskDeviceTypeToString (device));
 
1403
                      "Unsupported bus type '%s' for device type '%s'",
 
1404
                      virDomainDiskBusTypeToString(bus),
 
1405
                      virDomainDiskDeviceTypeToString(device));
1089
1406
            goto failure;
1090
1407
        }
1091
1408
    } else {
1092
1409
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
1093
1410
                  "Unsupported device type '%s'",
1094
 
                  virDomainDiskDeviceTypeToString (device));
 
1411
                  virDomainDiskDeviceTypeToString(device));
1095
1412
        goto failure;
1096
1413
    }
1097
1414
 
1135
1452
    if (clientDevice) {
1136
1453
        /*
1137
1454
         * Just ignore devices in client mode, because I have no clue how to
1138
 
         * handle them (e.g. assign an image) without the VI client GUI.
 
1455
         * handle them (e.g. assign an image) without the VI Client GUI.
1139
1456
         */
1140
1457
        goto ignore;
1141
1458
    }
1158
1475
    }
1159
1476
 
1160
1477
    /* Setup virDomainDiskDef */
1161
 
    /* FIXME: Need the datastore name for fileName */
1162
1478
    if (device == VIR_DOMAIN_DISK_DEVICE_DISK) {
1163
 
        if (esxUtil_EqualSuffix(fileName, ".vmdk")) {
 
1479
        if (virFileHasSuffix(fileName, ".vmdk")) {
1164
1480
            if (deviceType != NULL) {
1165
1481
                if (bus == VIR_DOMAIN_DISK_BUS_SCSI &&
1166
1482
                    STRCASENEQ(deviceType, "scsi-hardDisk")) {
1177
1493
                }
1178
1494
            }
1179
1495
 
 
1496
            if (writeThrough && virtualDev == NULL) {
 
1497
                /*
 
1498
                 * FIXME: If no virtualDev is explicit specified need to get
 
1499
                 *        the default based on the guestOS. The mechanism to
 
1500
                 *        obtain the default is currently missing
 
1501
                 */
 
1502
                VIR_WARN0("No explicit SCSI driver specified in VMX config, "
 
1503
                          "cannot represent explicit specified cachemode");
 
1504
            }
 
1505
 
1180
1506
            (*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
1181
 
            (*def)->src = fileName;
 
1507
            (*def)->src = esxVMX_ParseFileName(conn, ctx, fileName,
 
1508
                                               datastoreName, directoryName);
1182
1509
            (*def)->cachemode = writeThrough ? VIR_DOMAIN_DISK_CACHE_WRITETHRU
1183
1510
                                             : VIR_DOMAIN_DISK_CACHE_DEFAULT;
1184
1511
 
1185
 
            fileName = NULL;
1186
 
        } else if (esxUtil_EqualSuffix(fileName, ".iso") ||
 
1512
            if ((*def)->src == NULL) {
 
1513
                goto failure;
 
1514
            }
 
1515
        } else if (virFileHasSuffix(fileName, ".iso") ||
1187
1516
                   STREQ(deviceType, "atapi-cdrom")) {
1188
1517
            /*
1189
1518
             * This function was called in order to parse a harddisk device,
1199
1528
            goto failure;
1200
1529
        }
1201
1530
    } else if (device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
1202
 
        if (esxUtil_EqualSuffix(fileName, ".iso")) {
 
1531
        if (virFileHasSuffix(fileName, ".iso")) {
1203
1532
            if (deviceType != NULL) {
1204
1533
                if (STRCASENEQ(deviceType, "cdrom-image")) {
1205
1534
                    ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
1210
1539
            }
1211
1540
 
1212
1541
            (*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
1213
 
            (*def)->src = fileName;
 
1542
            (*def)->src = esxVMX_ParseFileName(conn, ctx, fileName,
 
1543
                                               datastoreName, directoryName);
1214
1544
 
1215
 
            fileName = NULL;
1216
 
        } else if (esxUtil_EqualSuffix(fileName, ".vmdk")) {
 
1545
            if ((*def)->src == NULL) {
 
1546
                goto failure;
 
1547
            }
 
1548
        } else if (virFileHasSuffix(fileName, ".vmdk")) {
1217
1549
            /*
1218
1550
             * This function was called in order to parse a CDROM device, but
1219
1551
             * .vmdk files are for harddisk devices only. Just ignore it,
1233
1565
            goto failure;
1234
1566
        }
1235
1567
    } else if (device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
1236
 
        if (esxUtil_EqualSuffix(fileName, ".flp")) {
 
1568
        if (virFileHasSuffix(fileName, ".flp")) {
1237
1569
            if (fileType != NULL) {
1238
1570
                if (STRCASENEQ(fileType, "file")) {
1239
1571
                    ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
1244
1576
            }
1245
1577
 
1246
1578
            (*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
1247
 
            (*def)->src = fileName;
 
1579
            (*def)->src = esxVMX_ParseFileName(conn, ctx, fileName,
 
1580
                                               datastoreName, directoryName);
1248
1581
 
1249
 
            fileName = NULL;
 
1582
            if ((*def)->src == NULL) {
 
1583
                goto failure;
 
1584
            }
1250
1585
        } else if (fileType != NULL && STREQ(fileType, "device")) {
1251
1586
            (*def)->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
1252
1587
            (*def)->src = fileName;
1261
1596
    } else {
1262
1597
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
1263
1598
                  "Unsupported device type '%s'",
1264
 
                  virDomainDiskDeviceTypeToString (device));
 
1599
                  virDomainDiskDeviceTypeToString(device));
1265
1600
        goto failure;
1266
1601
    }
1267
1602
 
1268
 
cleanup:
 
1603
  cleanup:
1269
1604
    VIR_FREE(prefix);
1270
1605
    VIR_FREE(deviceType);
1271
1606
    VIR_FREE(fileType);
1273
1608
 
1274
1609
    return result;
1275
1610
 
1276
 
failure:
 
1611
  failure:
1277
1612
    result = -1;
1278
1613
 
1279
 
ignore:
 
1614
  ignore:
1280
1615
    virDomainDiskDefFree(*def);
1281
1616
    *def = NULL;
1282
1617
 
1316
1651
    char vnet_name[48] = "";
1317
1652
    char *vnet = NULL;
1318
1653
 
 
1654
    char networkName_name[48] = "";
 
1655
    char *networkName = NULL;
 
1656
 
1319
1657
    if (def == NULL || *def != NULL) {
1320
1658
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
1321
1659
        return -1;
1333
1671
        goto failure;
1334
1672
    }
1335
1673
 
1336
 
    strncpy(prefix, "ethernetX", sizeof (prefix));
1337
 
    prefix[8] = '0' + controller;
 
1674
    snprintf(prefix, sizeof(prefix), "ethernet%d", controller);
1338
1675
 
1339
1676
    ESX_BUILD_VMX_NAME(present);
1340
1677
    ESX_BUILD_VMX_NAME(startConnected);
1343
1680
    ESX_BUILD_VMX_NAME(generatedAddress);
1344
1681
    ESX_BUILD_VMX_NAME(address);
1345
1682
    ESX_BUILD_VMX_NAME(virtualDev);
 
1683
    ESX_BUILD_VMX_NAME(networkName);
1346
1684
    ESX_BUILD_VMX_NAME(vnet);
1347
1685
 
1348
1686
    /* vmx:present */
1377
1715
        goto failure;
1378
1716
    }
1379
1717
 
1380
 
    if (addressType == NULL || STRCASEEQ(addressType, "generated")) {
 
1718
    if (addressType == NULL || STRCASEEQ(addressType, "generated") ||
 
1719
        STRCASEEQ(addressType, "vpx")) {
1381
1720
        if (generatedAddress != NULL) {
1382
1721
            if (virParseMacAddr(generatedAddress, (*def)->mac) < 0) {
1383
1722
                ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
1398
1737
        }
1399
1738
    } else {
1400
1739
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
1401
 
                  "Expecting VMX entry '%s' to be 'generated' or 'static' but "
1402
 
                  "found '%s'", addressType_name, addressType);
 
1740
                  "Expecting VMX entry '%s' to be 'generated' or 'static' or "
 
1741
                  "'vpx' but found '%s'", addressType_name, addressType);
1403
1742
        goto failure;
1404
1743
    }
1405
1744
 
1412
1751
    if (virtualDev != NULL &&
1413
1752
        STRCASENEQ(virtualDev, "vlance") &&
1414
1753
        STRCASENEQ(virtualDev, "vmxnet") &&
 
1754
        STRCASENEQ(virtualDev, "vmxnet3") &&
1415
1755
        STRCASENEQ(virtualDev, "e1000")) {
1416
1756
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
1417
1757
                  "Expecting VMX entry '%s' to be 'vlance' or 'vmxnet' or "
1418
 
                  "'e1000' but found '%s'", virtualDev_name, virtualDev);
1419
 
        goto failure;
1420
 
    }
1421
 
 
1422
 
    /* vmx:vnet -> def:data.bridge.brname */
 
1758
                  "'vmxnet3' or 'e1000' but found '%s'", virtualDev_name, virtualDev);
 
1759
        goto failure;
 
1760
    }
 
1761
 
 
1762
    /* vmx:networkName -> def:data.bridge.brname */
 
1763
    if ((connectionType == NULL ||
 
1764
         STRCASEEQ(connectionType, "bridged") ||
 
1765
         STRCASEEQ(connectionType, "custom")) &&
 
1766
        esxUtil_GetConfigString(conn, conf, networkName_name,
 
1767
                                &networkName, 0) < 0) {
 
1768
        goto failure;
 
1769
    }
 
1770
 
 
1771
    /* vmx:vnet -> def:data.ifname */
1423
1772
    if (connectionType != NULL && STRCASEEQ(connectionType, "custom") &&
1424
1773
        esxUtil_GetConfigString(conn, conf, vnet_name, &vnet, 0) < 0) {
1425
1774
        goto failure;
1429
1778
    if (connectionType == NULL || STRCASEEQ(connectionType, "bridged")) {
1430
1779
        (*def)->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
1431
1780
        (*def)->model = virtualDev;
 
1781
        (*def)->data.bridge.brname = networkName;
1432
1782
 
1433
1783
        virtualDev = NULL;
 
1784
        networkName = NULL;
1434
1785
    } else if (STRCASEEQ(connectionType, "hostonly")) {
1435
1786
        /* FIXME */
1436
1787
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
1446
1797
    } else if (STRCASEEQ(connectionType, "custom")) {
1447
1798
        (*def)->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
1448
1799
        (*def)->model = virtualDev;
1449
 
        (*def)->data.bridge.brname = vnet;
 
1800
        (*def)->data.bridge.brname = networkName;
 
1801
        (*def)->ifname = vnet;
1450
1802
 
1451
1803
        virtualDev = NULL;
 
1804
        networkName = NULL;
1452
1805
        vnet = NULL;
1453
1806
    } else {
1454
1807
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
1457
1810
        goto failure;
1458
1811
    }
1459
1812
 
1460
 
cleanup:
 
1813
  cleanup:
1461
1814
    VIR_FREE(connectionType);
1462
1815
    VIR_FREE(addressType);
1463
1816
    VIR_FREE(generatedAddress);
1467
1820
 
1468
1821
    return result;
1469
1822
 
1470
 
failure:
 
1823
  failure:
1471
1824
    result = -1;
1472
1825
 
1473
 
ignore:
 
1826
  ignore:
1474
1827
    virDomainNetDefFree(*def);
1475
1828
    *def = NULL;
1476
1829
 
1480
1833
 
1481
1834
 
1482
1835
int
1483
 
esxVMX_ParseSerial(virConnectPtr conn, virConfPtr conf, int port,
1484
 
                   virDomainChrDefPtr *def)
 
1836
esxVMX_ParseSerial(virConnectPtr conn, esxVI_Context *ctx, virConfPtr conf,
 
1837
                   int port, const char *datastoreName,
 
1838
                   const char *directoryName, virDomainChrDefPtr *def)
1485
1839
{
1486
1840
    int result = 0;
1487
1841
    char prefix[48] = "";
1514
1868
        goto failure;
1515
1869
    }
1516
1870
 
1517
 
    strncpy(prefix, "serialX", sizeof (prefix));
1518
 
    prefix[6] = '0' + port;
 
1871
    snprintf(prefix, sizeof(prefix), "serial%d", port);
1519
1872
 
1520
1873
    ESX_BUILD_VMX_NAME(present);
1521
1874
    ESX_BUILD_VMX_NAME(startConnected);
1559
1912
    } else if (STRCASEEQ(fileType, "file")) {
1560
1913
        (*def)->dstPort = port;
1561
1914
        (*def)->type = VIR_DOMAIN_CHR_TYPE_FILE;
1562
 
        (*def)->data.file.path = fileName;
 
1915
        (*def)->data.file.path = esxVMX_ParseFileName(conn, ctx, fileName,
 
1916
                                                      datastoreName,
 
1917
                                                      directoryName);
1563
1918
 
1564
 
        fileName = NULL;
 
1919
        if ((*def)->data.file.path == NULL) {
 
1920
            goto failure;
 
1921
        }
1565
1922
    } else if (STRCASEEQ(fileType, "pipe")) {
1566
 
        /* FIXME */
1567
 
        VIR_WARN("Serial port %d has currently unsupported type '%s', "
1568
 
                 "ignoring it", port, fileType);
1569
 
        goto ignore;
 
1923
        /*
 
1924
         * FIXME: Differences between client/server and VM/application pipes
 
1925
         *        not representable in domain XML form
 
1926
         */
 
1927
        (*def)->dstPort = port;
 
1928
        (*def)->type = VIR_DOMAIN_CHR_TYPE_PIPE;
 
1929
        (*def)->data.file.path = fileName;
 
1930
 
 
1931
        fileName = NULL;
1570
1932
    } else {
1571
1933
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
1572
1934
                  "Expecting VMX entry '%s' to be 'device', 'file' or 'pipe' "
1574
1936
        goto failure;
1575
1937
    }
1576
1938
 
1577
 
cleanup:
 
1939
  cleanup:
1578
1940
    VIR_FREE(fileType);
1579
1941
    VIR_FREE(fileName);
1580
1942
 
1581
1943
    return result;
1582
1944
 
1583
 
failure:
 
1945
  failure:
1584
1946
    result = -1;
1585
1947
 
1586
 
ignore:
 
1948
  ignore:
1587
1949
    virDomainChrDefFree(*def);
1588
1950
    *def = NULL;
1589
1951
 
1593
1955
 
1594
1956
 
1595
1957
int
1596
 
esxVMX_ParseParallel(virConnectPtr conn, virConfPtr conf, int port,
1597
 
                     virDomainChrDefPtr *def)
 
1958
esxVMX_ParseParallel(virConnectPtr conn, esxVI_Context *ctx, virConfPtr conf,
 
1959
                     int port, const char *datastoreName,
 
1960
                     const char *directoryName, virDomainChrDefPtr *def)
1598
1961
{
1599
1962
    int result = 0;
1600
1963
    char prefix[48] = "";
1627
1990
        goto failure;
1628
1991
    }
1629
1992
 
1630
 
    strncpy(prefix, "parallelX", sizeof (prefix));
1631
 
    prefix[8] = '0' + port;
 
1993
    snprintf(prefix, sizeof(prefix), "parallel%d", port);
1632
1994
 
1633
1995
    ESX_BUILD_VMX_NAME(present);
1634
1996
    ESX_BUILD_VMX_NAME(startConnected);
1672
2034
    } else if (STRCASEEQ(fileType, "file")) {
1673
2035
        (*def)->dstPort = port;
1674
2036
        (*def)->type = VIR_DOMAIN_CHR_TYPE_FILE;
1675
 
        (*def)->data.file.path = fileName;
 
2037
        (*def)->data.file.path = esxVMX_ParseFileName(conn, ctx, fileName,
 
2038
                                                      datastoreName,
 
2039
                                                      directoryName);
1676
2040
 
1677
 
        fileName = NULL;
 
2041
        if ((*def)->data.file.path == NULL) {
 
2042
            goto failure;
 
2043
        }
1678
2044
    } else {
1679
2045
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
1680
2046
                  "Expecting VMX entry '%s' to be 'device' or 'file' but "
1682
2048
        goto failure;
1683
2049
    }
1684
2050
 
1685
 
cleanup:
 
2051
  cleanup:
1686
2052
    VIR_FREE(fileType);
1687
2053
    VIR_FREE(fileName);
1688
2054
 
1689
2055
    return result;
1690
2056
 
1691
 
failure:
 
2057
  failure:
1692
2058
    result = -1;
1693
2059
 
1694
 
ignore:
 
2060
  ignore:
1695
2061
    virDomainChrDefFree(*def);
1696
2062
    *def = NULL;
1697
2063
 
1698
2064
    goto cleanup;
1699
2065
}
 
2066
 
 
2067
 
 
2068
 
 
2069
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
2070
 * Domain XML -> VMX
 
2071
 */
 
2072
 
 
2073
char *
 
2074
esxVMX_FormatFileName(virConnectPtr conn, esxVI_Context *ctx ATTRIBUTE_UNUSED,
 
2075
                      const char *src)
 
2076
{
 
2077
    char *datastoreName = NULL;
 
2078
    char *directoryName = NULL;
 
2079
    char *fileName = NULL;
 
2080
    char *absolutePath = NULL;
 
2081
 
 
2082
    if (STRPREFIX(src, "[")) {
 
2083
        /* Found potential datastore related path */
 
2084
        if (esxUtil_ParseDatastoreRelatedPath(conn, src, &datastoreName,
 
2085
                                              &directoryName, &fileName) < 0) {
 
2086
            goto failure;
 
2087
        }
 
2088
 
 
2089
        if (directoryName == NULL) {
 
2090
            if (virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s",
 
2091
                            datastoreName, fileName) < 0) {
 
2092
                virReportOOMError(conn);
 
2093
                goto failure;
 
2094
            }
 
2095
        } else {
 
2096
            if (virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s/%s",
 
2097
                            datastoreName, directoryName, fileName) < 0) {
 
2098
                virReportOOMError(conn);
 
2099
                goto failure;
 
2100
            }
 
2101
        }
 
2102
    } else if (STRPREFIX(src, "/")) {
 
2103
        /* Found absolute path */
 
2104
        absolutePath = strdup(src);
 
2105
 
 
2106
        if (absolutePath == NULL) {
 
2107
            virReportOOMError(conn);
 
2108
            goto failure;
 
2109
        }
 
2110
    } else {
 
2111
        /* Found relative path, this is not supported */
 
2112
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2113
                  "Found relative path '%s' in domain XML, this is not "
 
2114
                  "supported", src);
 
2115
        goto failure;
 
2116
    }
 
2117
 
 
2118
    /* FIXME: Check if referenced path/file really exists */
 
2119
 
 
2120
  cleanup:
 
2121
    VIR_FREE(datastoreName);
 
2122
    VIR_FREE(directoryName);
 
2123
    VIR_FREE(fileName);
 
2124
 
 
2125
    return absolutePath;
 
2126
 
 
2127
  failure:
 
2128
    VIR_FREE(absolutePath);
 
2129
 
 
2130
    goto cleanup;
 
2131
}
 
2132
 
 
2133
 
 
2134
 
 
2135
char *
 
2136
esxVMX_FormatConfig(virConnectPtr conn, esxVI_Context *ctx,
 
2137
                    virDomainDefPtr def, esxVI_APIVersion apiVersion)
 
2138
{
 
2139
    int i;
 
2140
    int sched_cpu_affinity_length;
 
2141
    unsigned char zero[VIR_UUID_BUFLEN];
 
2142
    virBuffer buffer = VIR_BUFFER_INITIALIZER;
 
2143
    char *vmx = NULL;
 
2144
 
 
2145
    memset(zero, 0, VIR_UUID_BUFLEN);
 
2146
 
 
2147
    if (def->virtType != VIR_DOMAIN_VIRT_VMWARE) { /* FIXME: maybe add VIR_DOMAIN_VIRT_ESX ? */
 
2148
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2149
                  "Expecting virt type to be '%s' but found '%s'",
 
2150
                  virDomainVirtTypeToString(VIR_DOMAIN_VIRT_VMWARE),
 
2151
                  virDomainVirtTypeToString(def->virtType));
 
2152
        return NULL;
 
2153
    }
 
2154
 
 
2155
    /* vmx:config.version */
 
2156
    virBufferAddLit(&buffer, "config.version = \"8\"\n");
 
2157
 
 
2158
    /* vmx:virtualHW.version */
 
2159
    switch (apiVersion) {
 
2160
      case esxVI_APIVersion_25:
 
2161
        virBufferAddLit(&buffer, "virtualHW.version = \"4\"\n");
 
2162
        break;
 
2163
 
 
2164
      case esxVI_APIVersion_40:
 
2165
        virBufferAddLit(&buffer, "virtualHW.version = \"7\"\n");
 
2166
        break;
 
2167
 
 
2168
      default:
 
2169
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2170
                  "Expecting VI API version 2.5 or 4.0");
 
2171
        goto failure;
 
2172
    }
 
2173
 
 
2174
    /* def:arch -> vmx:guestOS */
 
2175
    if (def->os.arch == NULL || STRCASEEQ(def->os.arch, "i686")) {
 
2176
        virBufferAddLit(&buffer, "guestOS = \"other\"\n");
 
2177
    } else if (STRCASEEQ(def->os.arch, "x86_64")) {
 
2178
        virBufferAddLit(&buffer, "guestOS = \"other-64\"\n");
 
2179
    } else {
 
2180
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2181
                  "Expecting domain XML attribute 'arch' of entry 'os/type' "
 
2182
                  "to be 'i686' or 'x86_64' but found '%s'", def->os.arch);
 
2183
        goto failure;
 
2184
    }
 
2185
 
 
2186
    /* def:uuid -> vmx:uuid.action, vmx:uuid.bios */
 
2187
    if (memcmp(def->uuid, zero, VIR_UUID_BUFLEN) == 0) {
 
2188
        virBufferAddLit(&buffer, "uuid.action = \"create\"\n");
 
2189
    } else {
 
2190
        virBufferVSprintf(&buffer, "uuid.bios = \"%02x %02x %02x %02x %02x %02x "
 
2191
                          "%02x %02x-%02x %02x %02x %02x %02x %02x %02x %02x\"\n",
 
2192
                          def->uuid[0], def->uuid[1], def->uuid[2], def->uuid[3],
 
2193
                          def->uuid[4], def->uuid[5], def->uuid[6], def->uuid[7],
 
2194
                          def->uuid[8], def->uuid[9], def->uuid[10], def->uuid[11],
 
2195
                          def->uuid[12], def->uuid[13], def->uuid[14],
 
2196
                          def->uuid[15]);
 
2197
    }
 
2198
 
 
2199
    /* def:name -> vmx:displayName */
 
2200
    virBufferVSprintf(&buffer, "displayName = \"%s\"\n", def->name);
 
2201
 
 
2202
    /* def:maxmem -> vmx:memsize */
 
2203
    if (def->maxmem <= 0 || def->maxmem % 4096 != 0) {
 
2204
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2205
                  "Expecting domain XML entry 'memory' to be an unsigned "
 
2206
                  "integer (multiple of 4096) but found %lld",
 
2207
                  (unsigned long long)def->maxmem);
 
2208
        goto failure;
 
2209
    }
 
2210
 
 
2211
    /* Scale from kilobytes to megabytes */
 
2212
    virBufferVSprintf(&buffer, "memsize = \"%d\"\n",
 
2213
                      (int)(def->maxmem / 1024));
 
2214
 
 
2215
    /* def:memory -> vmx:sched.mem.max */
 
2216
    if (def->memory < def->maxmem) {
 
2217
        if (def->memory <= 0 || def->memory % 1024 != 0) {
 
2218
            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2219
                      "Expecting domain XML entry 'currentMemory' to be an "
 
2220
                      "unsigned integer (multiple of 1024) but found %lld",
 
2221
                      (unsigned long long)def->memory);
 
2222
            goto failure;
 
2223
        }
 
2224
 
 
2225
        /* Scale from kilobytes to megabytes */
 
2226
        virBufferVSprintf(&buffer, "sched.mem.max = \"%d\"\n",
 
2227
                          (int)(def->memory / 1024));
 
2228
    }
 
2229
 
 
2230
    /* vmx:numvcpus -> def:vcpus */
 
2231
    if (def->vcpus <= 0 || (def->vcpus % 2 != 0 && def->vcpus != 1)) {
 
2232
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2233
                  "Expecting domain XML entry 'vcpu' to be an unsigned "
 
2234
                  "integer (1 or a multiple of 2) but found %d",
 
2235
                  (int)def->vcpus);
 
2236
        goto failure;
 
2237
    }
 
2238
 
 
2239
    virBufferVSprintf(&buffer, "numvcpus = \"%d\"\n", (int)def->vcpus);
 
2240
 
 
2241
    /* def:cpumask -> vmx:sched.cpu.affinity */
 
2242
    if (def->cpumasklen > 0) {
 
2243
        virBufferAddLit(&buffer, "sched.cpu.affinity = \"");
 
2244
 
 
2245
        sched_cpu_affinity_length = 0;
 
2246
 
 
2247
        for (i = 0; i < def->cpumasklen; ++i) {
 
2248
            if (def->cpumask[i]) {
 
2249
                ++sched_cpu_affinity_length;
 
2250
            }
 
2251
        }
 
2252
 
 
2253
        if (sched_cpu_affinity_length < def->vcpus) {
 
2254
            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2255
                      "Expecting domain XML attribute 'cpuset' of entry "
 
2256
                      "'vcpu' to contains at least %d CPU(s)",
 
2257
                      (int)def->vcpus);
 
2258
            goto failure;
 
2259
        }
 
2260
 
 
2261
        for (i = 0; i < def->cpumasklen; ++i) {
 
2262
            if (def->cpumask[i]) {
 
2263
                virBufferVSprintf(&buffer, "%d", i);
 
2264
 
 
2265
                if (sched_cpu_affinity_length > 1) {
 
2266
                    virBufferAddChar(&buffer, ',');
 
2267
                }
 
2268
 
 
2269
                --sched_cpu_affinity_length;
 
2270
            }
 
2271
        }
 
2272
 
 
2273
        virBufferAddLit(&buffer, "\"\n");
 
2274
    }
 
2275
 
 
2276
    /* def:disks */
 
2277
    int scsi_present[4] = { 0, 0, 0, 0 };
 
2278
    char *scsi_virtualDev[4] = { NULL, NULL, NULL, NULL };
 
2279
 
 
2280
    if (esxVMX_GatherSCSIControllers(conn, def, scsi_virtualDev,
 
2281
                                     scsi_present) < 0) {
 
2282
        goto failure;
 
2283
    }
 
2284
 
 
2285
    for (i = 0; i < 4; ++i) {
 
2286
        if (scsi_present[i]) {
 
2287
            virBufferVSprintf(&buffer, "scsi%d.present = \"true\"\n", i);
 
2288
 
 
2289
            if (scsi_virtualDev[i] != NULL) {
 
2290
                virBufferVSprintf(&buffer, "scsi%d.virtualDev = \"%s\"\n", i,
 
2291
                                  scsi_virtualDev[i]);
 
2292
            }
 
2293
        }
 
2294
    }
 
2295
 
 
2296
    for (i = 0; i < def->ndisks; ++i) {
 
2297
        switch (def->disks[i]->device) {
 
2298
          case VIR_DOMAIN_DISK_DEVICE_DISK:
 
2299
            if (esxVMX_FormatHardDisk(conn, ctx, def->disks[i], &buffer) < 0) {
 
2300
                goto failure;
 
2301
            }
 
2302
 
 
2303
            break;
 
2304
 
 
2305
          case VIR_DOMAIN_DISK_DEVICE_CDROM:
 
2306
            if (esxVMX_FormatCDROM(conn, ctx, def->disks[i], &buffer) < 0) {
 
2307
                goto failure;
 
2308
            }
 
2309
 
 
2310
            break;
 
2311
 
 
2312
          case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
 
2313
            if (esxVMX_FormatFloppy(conn, ctx, def->disks[i], &buffer) < 0) {
 
2314
                goto failure;
 
2315
            }
 
2316
 
 
2317
            break;
 
2318
 
 
2319
          default:
 
2320
            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2321
                      "Unsuppotred disk device type '%s'",
 
2322
                      virDomainDiskDeviceTypeToString(def->disks[i]->device));
 
2323
            goto failure;
 
2324
        }
 
2325
    }
 
2326
 
 
2327
    /* def:fss */
 
2328
    /* FIXME */
 
2329
 
 
2330
    /* def:nets */
 
2331
    for (i = 0; i < def->nnets; ++i) {
 
2332
        if (esxVMX_FormatEthernet(conn, def->nets[i], i, &buffer) < 0) {
 
2333
            goto failure;
 
2334
        }
 
2335
    }
 
2336
 
 
2337
    /* def:inputs */
 
2338
    /* FIXME */
 
2339
 
 
2340
    /* def:sounds */
 
2341
    /* FIXME */
 
2342
 
 
2343
    /* def:hostdevs */
 
2344
    /* FIXME */
 
2345
 
 
2346
    /* def:serials */
 
2347
    for (i = 0; i < def->nserials; ++i) {
 
2348
        if (esxVMX_FormatSerial(conn, ctx, def->serials[i], &buffer) < 0) {
 
2349
            goto failure;
 
2350
        }
 
2351
    }
 
2352
 
 
2353
    /* def:parallels */
 
2354
    for (i = 0; i < def->nparallels; ++i) {
 
2355
        if (esxVMX_FormatParallel(conn, ctx, def->parallels[i], &buffer) < 0) {
 
2356
            goto failure;
 
2357
        }
 
2358
    }
 
2359
 
 
2360
    /* Get final VMX output */
 
2361
    if (virBufferError(&buffer)) {
 
2362
        virReportOOMError(conn);
 
2363
        goto failure;
 
2364
    }
 
2365
 
 
2366
    vmx = virBufferContentAndReset(&buffer);
 
2367
 
 
2368
    return vmx;
 
2369
 
 
2370
  failure:
 
2371
    if (vmx == NULL) {
 
2372
        vmx = virBufferContentAndReset(&buffer);
 
2373
    }
 
2374
 
 
2375
    VIR_FREE(vmx);
 
2376
 
 
2377
    return NULL;
 
2378
}
 
2379
 
 
2380
 
 
2381
 
 
2382
int
 
2383
esxVMX_FormatHardDisk(virConnectPtr conn, esxVI_Context *ctx,
 
2384
                      virDomainDiskDefPtr def, virBufferPtr buffer)
 
2385
{
 
2386
    int controller, id;
 
2387
    const char *busName = NULL;
 
2388
    const char *entryPrefix = NULL;
 
2389
    const char *deviceTypePrefix = NULL;
 
2390
    char *fileName = NULL;
 
2391
 
 
2392
    if (def->device != VIR_DOMAIN_DISK_DEVICE_DISK) {
 
2393
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
 
2394
        return -1;
 
2395
    }
 
2396
 
 
2397
    if (def->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
 
2398
        busName = "SCSI";
 
2399
        entryPrefix = "scsi";
 
2400
        deviceTypePrefix = "scsi";
 
2401
 
 
2402
        if (esxVMX_SCSIDiskNameToControllerAndID(conn, def->dst,
 
2403
                                                 &controller, &id) < 0) {
 
2404
            return -1;
 
2405
        }
 
2406
    } else if (def->bus == VIR_DOMAIN_DISK_BUS_IDE) {
 
2407
        busName = "IDE";
 
2408
        entryPrefix = "ide";
 
2409
        deviceTypePrefix = "ata";
 
2410
 
 
2411
        if (esxVMX_IDEDiskNameToControllerAndID(conn, def->dst,
 
2412
                                                 &controller, &id) < 0) {
 
2413
            return -1;
 
2414
        }
 
2415
    } else {
 
2416
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2417
                  "Unsupported bus type '%s' for harddisk",
 
2418
                  virDomainDiskBusTypeToString(def->bus));
 
2419
        return -1;
 
2420
    }
 
2421
 
 
2422
    if (def->type != VIR_DOMAIN_DISK_TYPE_FILE) {
 
2423
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2424
                  "%s harddisk '%s' has unsupported type '%s', expecting '%s'",
 
2425
                  busName, def->dst, virDomainDiskTypeToString(def->type),
 
2426
                  virDomainDiskTypeToString(VIR_DOMAIN_DISK_TYPE_FILE));
 
2427
        return -1;
 
2428
    }
 
2429
 
 
2430
    virBufferVSprintf(buffer, "%s%d:%d.present = \"true\"\n",
 
2431
                      entryPrefix, controller, id);
 
2432
    virBufferVSprintf(buffer, "%s%d:%d.deviceType = \"%s-hardDisk\"\n",
 
2433
                      entryPrefix, controller, id, deviceTypePrefix);
 
2434
 
 
2435
    if (def->src != NULL) {
 
2436
        if (! virFileHasSuffix(def->src, ".vmdk")) {
 
2437
            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2438
                      "Image file for %s harddisk '%s' has unsupported suffix, "
 
2439
                      "expecting '.vmdk'", busName, def->dst);
 
2440
            return -1;
 
2441
        }
 
2442
 
 
2443
        fileName = esxVMX_FormatFileName(conn, ctx, def->src);
 
2444
 
 
2445
        if (fileName == NULL) {
 
2446
            return -1;
 
2447
        }
 
2448
 
 
2449
        virBufferVSprintf(buffer, "%s%d:%d.fileName = \"%s\"\n",
 
2450
                          entryPrefix, controller, id, fileName);
 
2451
 
 
2452
        VIR_FREE(fileName);
 
2453
    }
 
2454
 
 
2455
    if (def->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
 
2456
        if (def->cachemode == VIR_DOMAIN_DISK_CACHE_WRITETHRU) {
 
2457
            virBufferVSprintf(buffer, "%s%d:%d.writeThrough = \"true\"\n",
 
2458
                              entryPrefix, controller, id);
 
2459
        } else if (def->cachemode != VIR_DOMAIN_DISK_CACHE_DEFAULT) {
 
2460
            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2461
                      "%s harddisk '%s' has unsupported cache mode '%s'",
 
2462
                      busName, def->dst,
 
2463
                      virDomainDiskCacheTypeToString(def->cachemode));
 
2464
            return -1;
 
2465
        }
 
2466
    }
 
2467
 
 
2468
    return 0;
 
2469
}
 
2470
 
 
2471
 
 
2472
 
 
2473
int
 
2474
esxVMX_FormatCDROM(virConnectPtr conn, esxVI_Context *ctx,
 
2475
                   virDomainDiskDefPtr def, virBufferPtr buffer)
 
2476
{
 
2477
    int controller, id;
 
2478
    const char *busName = NULL;
 
2479
    const char *entryPrefix = NULL;
 
2480
    char *fileName = NULL;
 
2481
 
 
2482
    if (def->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
 
2483
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
 
2484
        return -1;
 
2485
    }
 
2486
 
 
2487
    if (def->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
 
2488
        busName = "SCSI";
 
2489
        entryPrefix = "scsi";
 
2490
 
 
2491
        if (esxVMX_SCSIDiskNameToControllerAndID(conn, def->dst,
 
2492
                                                 &controller, &id) < 0) {
 
2493
            return -1;
 
2494
        }
 
2495
    } else if (def->bus == VIR_DOMAIN_DISK_BUS_IDE) {
 
2496
        busName = "IDE";
 
2497
        entryPrefix = "ide";
 
2498
 
 
2499
        if (esxVMX_IDEDiskNameToControllerAndID(conn, def->dst,
 
2500
                                                 &controller, &id) < 0) {
 
2501
            return -1;
 
2502
        }
 
2503
    } else {
 
2504
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2505
                  "Unsupported bus type '%s' for cdrom",
 
2506
                  virDomainDiskBusTypeToString(def->bus));
 
2507
        return -1;
 
2508
    }
 
2509
 
 
2510
    virBufferVSprintf(buffer, "%s%d:%d.present = \"true\"\n",
 
2511
                      entryPrefix, controller, id);
 
2512
 
 
2513
    if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) {
 
2514
        virBufferVSprintf(buffer, "%s%d:%d.deviceType = \"cdrom-image\"\n",
 
2515
                          entryPrefix, controller, id);
 
2516
 
 
2517
        if (def->src != NULL) {
 
2518
            if (! virFileHasSuffix(def->src, ".iso")) {
 
2519
                ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2520
                          "Image file for %s cdrom '%s' has unsupported "
 
2521
                          "suffix, expecting '.iso'", busName, def->dst);
 
2522
                return -1;
 
2523
            }
 
2524
 
 
2525
            fileName = esxVMX_FormatFileName(conn, ctx, def->src);
 
2526
 
 
2527
            if (fileName == NULL) {
 
2528
                return -1;
 
2529
            }
 
2530
 
 
2531
            virBufferVSprintf(buffer, "%s%d:%d.fileName = \"%s\"\n",
 
2532
                              entryPrefix, controller, id, fileName);
 
2533
 
 
2534
            VIR_FREE(fileName);
 
2535
        }
 
2536
    } else if (def->type == VIR_DOMAIN_DISK_TYPE_BLOCK) {
 
2537
        virBufferVSprintf(buffer, "%s%d:%d.deviceType = \"atapi-cdrom\"\n",
 
2538
                          entryPrefix, controller, id);
 
2539
 
 
2540
        if (def->src != NULL) {
 
2541
            virBufferVSprintf(buffer, "%s%d:%d.fileName = \"%s\"\n",
 
2542
                              entryPrefix, controller, id, def->src);
 
2543
        }
 
2544
    } else {
 
2545
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2546
                  "%s cdrom '%s' has unsupported type '%s', expecting '%s' "
 
2547
                  "or '%s'", busName, def->dst,
 
2548
                  virDomainDiskTypeToString(def->type),
 
2549
                  virDomainDiskTypeToString(VIR_DOMAIN_DISK_TYPE_FILE),
 
2550
                  virDomainDiskTypeToString(VIR_DOMAIN_DISK_TYPE_BLOCK));
 
2551
        return -1;
 
2552
    }
 
2553
 
 
2554
    return 0;
 
2555
}
 
2556
 
 
2557
 
 
2558
 
 
2559
int
 
2560
esxVMX_FormatFloppy(virConnectPtr conn, esxVI_Context *ctx,
 
2561
                    virDomainDiskDefPtr def, virBufferPtr buffer)
 
2562
{
 
2563
    int controller;
 
2564
    char *fileName = NULL;
 
2565
 
 
2566
    if (def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
 
2567
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
 
2568
        return -1;
 
2569
    }
 
2570
 
 
2571
    if (esxVMX_FloppyDiskNameToController(conn, def->dst, &controller) < 0) {
 
2572
        return -1;
 
2573
    }
 
2574
 
 
2575
    virBufferVSprintf(buffer, "floppy%d.present = \"true\"\n", controller);
 
2576
 
 
2577
    if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) {
 
2578
        virBufferVSprintf(buffer, "floppy%d.fileType = \"file\"\n",
 
2579
                          controller);
 
2580
 
 
2581
        if (def->src != NULL) {
 
2582
            if (! virFileHasSuffix(def->src, ".flp")) {
 
2583
                ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2584
                          "Image file for floppy '%s' has unsupported suffix, "
 
2585
                          "expecting '.flp'", def->dst);
 
2586
                return -1;
 
2587
            }
 
2588
 
 
2589
            fileName = esxVMX_FormatFileName(conn, ctx, def->src);
 
2590
 
 
2591
            if (fileName == NULL) {
 
2592
                return -1;
 
2593
            }
 
2594
 
 
2595
            virBufferVSprintf(buffer, "floppy%d.fileName = \"%s\"\n",
 
2596
                              controller, fileName);
 
2597
 
 
2598
            VIR_FREE(fileName);
 
2599
        }
 
2600
    } else if (def->type == VIR_DOMAIN_DISK_TYPE_BLOCK) {
 
2601
        virBufferVSprintf(buffer, "floppy%d.fileType = \"device\"\n",
 
2602
                          controller);
 
2603
 
 
2604
        if (def->src != NULL) {
 
2605
            virBufferVSprintf(buffer, "floppy%d.fileName = \"%s\"\n",
 
2606
                              controller, def->src);
 
2607
        }
 
2608
    } else {
 
2609
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2610
                  "Floppy '%s' has unsupported type '%s', expecting '%s' "
 
2611
                  "or '%s'", def->dst,
 
2612
                  virDomainDiskTypeToString(def->type),
 
2613
                  virDomainDiskTypeToString(VIR_DOMAIN_DISK_TYPE_FILE),
 
2614
                  virDomainDiskTypeToString(VIR_DOMAIN_DISK_TYPE_BLOCK));
 
2615
        return -1;
 
2616
    }
 
2617
 
 
2618
    return 0;
 
2619
}
 
2620
 
 
2621
 
 
2622
 
 
2623
int
 
2624
esxVMX_FormatEthernet(virConnectPtr conn, virDomainNetDefPtr def,
 
2625
                      int controller, virBufferPtr buffer)
 
2626
{
 
2627
    char mac_string[VIR_MAC_STRING_BUFLEN];
 
2628
 
 
2629
    if (controller < 0 || controller > 3) {
 
2630
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2631
                  "Ethernet controller index %d out of [0..3] range",
 
2632
                  controller);
 
2633
        return -1;
 
2634
    }
 
2635
 
 
2636
    virBufferVSprintf(buffer, "ethernet%d.present = \"true\"\n", controller);
 
2637
 
 
2638
    /* def:model -> vmx:virtualDev */
 
2639
    if (def->model != NULL) {
 
2640
        if (STRCASENEQ(def->model, "vlance") &&
 
2641
            STRCASENEQ(def->model, "vmxnet") &&
 
2642
            STRCASENEQ(def->model, "e1000")) {
 
2643
            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2644
                      "Expecting domain XML entry 'devices/interfase/model' "
 
2645
                      "to be 'vlance' or 'vmxnet' or 'e1000' but found '%s'",
 
2646
                      def->model);
 
2647
            return -1;
 
2648
        }
 
2649
 
 
2650
        virBufferVSprintf(buffer, "ethernet%d.virtualDev = \"%s\"\n",
 
2651
                          controller, def->model);
 
2652
    }
 
2653
 
 
2654
    /* def:type, def:ifname -> vmx:connectionType */
 
2655
    switch (def->type) {
 
2656
      case VIR_DOMAIN_NET_TYPE_BRIDGE:
 
2657
        virBufferVSprintf(buffer, "ethernet%d.networkName = \"%s\"\n",
 
2658
                          controller, def->data.bridge.brname);
 
2659
 
 
2660
        if (def->ifname != NULL) {
 
2661
            virBufferVSprintf(buffer, "ethernet%d.connectionType = \"custom\"\n",
 
2662
                              controller);
 
2663
            virBufferVSprintf(buffer, "ethernet%d.vnet = \"%s\"\n",
 
2664
                              controller, def->ifname);
 
2665
        } else {
 
2666
            virBufferVSprintf(buffer, "ethernet%d.connectionType = \"bridged\"\n",
 
2667
                              controller);
 
2668
        }
 
2669
 
 
2670
        break;
 
2671
 
 
2672
      default:
 
2673
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2674
                  "Unsupported net type '%s'",
 
2675
                  virDomainNetTypeToString(def->type));
 
2676
        return -1;
 
2677
    }
 
2678
 
 
2679
    virFormatMacAddr(def->mac, mac_string);
 
2680
 
 
2681
    if ((def->mac[0] == 0x00 && def->mac[1] == 0x0c && def->mac[2] == 0x29) ||
 
2682
        (def->mac[0] == 0x00 && def->mac[1] == 0x50 && def->mac[2] == 0x56)) {
 
2683
        virBufferVSprintf(buffer, "ethernet%d.addressType = \"generated\"\n",
 
2684
                          controller);
 
2685
        virBufferVSprintf(buffer, "ethernet%d.generatedAddress = \"%s\"\n",
 
2686
                          controller, mac_string);
 
2687
    } else {
 
2688
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2689
                  "Unsupported MAC address prefix '%02X:%02X:%02X', expecting "
 
2690
                  "'00:0c:29' or '00:50:56'",
 
2691
                  def->mac[0], def->mac[1], def->mac[2]);
 
2692
        return -1;
 
2693
    }
 
2694
 
 
2695
    return 0;
 
2696
}
 
2697
 
 
2698
 
 
2699
 
 
2700
int
 
2701
esxVMX_FormatSerial(virConnectPtr conn, esxVI_Context *ctx,
 
2702
                    virDomainChrDefPtr def, virBufferPtr buffer)
 
2703
{
 
2704
    char *fileName = NULL;
 
2705
 
 
2706
    if (def->dstPort < 0 || def->dstPort > 3) {
 
2707
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2708
                  "Serial port index %d out of [0..3] range", def->dstPort);
 
2709
        return -1;
 
2710
    }
 
2711
 
 
2712
    if (def->data.file.path == NULL) {
 
2713
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2714
                  "Expecting domain XML attribute 'path' of entry "
 
2715
                  "'devices/serial/source' to be present");
 
2716
        return -1;
 
2717
    }
 
2718
 
 
2719
    virBufferVSprintf(buffer, "serial%d.present = \"true\"\n", def->dstPort);
 
2720
 
 
2721
    /* def:type -> vmx:fileType and def:data.file.path -> vmx:fileName */
 
2722
    switch (def->type) {
 
2723
      case VIR_DOMAIN_CHR_TYPE_DEV:
 
2724
        virBufferVSprintf(buffer, "serial%d.fileType = \"device\"\n",
 
2725
                          def->dstPort);
 
2726
        virBufferVSprintf(buffer, "serial%d.fileName = \"%s\"\n",
 
2727
                          def->dstPort, def->data.file.path);
 
2728
        break;
 
2729
 
 
2730
      case VIR_DOMAIN_CHR_TYPE_FILE:
 
2731
        virBufferVSprintf(buffer, "serial%d.fileType = \"file\"\n",
 
2732
                          def->dstPort);
 
2733
 
 
2734
        fileName = esxVMX_FormatFileName(conn, ctx, def->data.file.path);
 
2735
 
 
2736
        if (fileName == NULL) {
 
2737
            return -1;
 
2738
        }
 
2739
 
 
2740
        virBufferVSprintf(buffer, "serial%d.fileName = \"%s\"\n",
 
2741
                          def->dstPort, fileName);
 
2742
 
 
2743
        VIR_FREE(fileName);
 
2744
        break;
 
2745
 
 
2746
      case VIR_DOMAIN_CHR_TYPE_PIPE:
 
2747
        virBufferVSprintf(buffer, "serial%d.fileType = \"pipe\"\n",
 
2748
                          def->dstPort);
 
2749
        /* FIXME: Based on VI Client GUI default */
 
2750
        virBufferVSprintf(buffer, "serial%d.pipe.endPoint = \"client\"\n",
 
2751
                          def->dstPort);
 
2752
        /* FIXME: Based on VI Client GUI default */
 
2753
        virBufferVSprintf(buffer, "serial%d.tryNoRxLoss = \"false\"\n",
 
2754
                          def->dstPort);
 
2755
        virBufferVSprintf(buffer, "serial%d.fileName = \"%s\"\n",
 
2756
                          def->dstPort, def->data.file.path);
 
2757
        break;
 
2758
 
 
2759
      default:
 
2760
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2761
                  "Unsupported character device type '%s'",
 
2762
                  virDomainChrTypeToString(def->type));
 
2763
        return -1;
 
2764
    }
 
2765
 
 
2766
    /* vmx:yieldOnMsrRead */
 
2767
    /* FIXME: Based on VI Client GUI default */
 
2768
    virBufferVSprintf(buffer, "serial%d.yieldOnMsrRead = \"true\"\n",
 
2769
                      def->dstPort);
 
2770
 
 
2771
    return 0;
 
2772
}
 
2773
 
 
2774
 
 
2775
 
 
2776
int
 
2777
esxVMX_FormatParallel(virConnectPtr conn, esxVI_Context *ctx,
 
2778
                      virDomainChrDefPtr def, virBufferPtr buffer)
 
2779
{
 
2780
    char *fileName = NULL;
 
2781
 
 
2782
    if (def->dstPort < 0 || def->dstPort > 2) {
 
2783
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2784
                  "Parallel port index %d out of [0..2] range", def->dstPort);
 
2785
        return -1;
 
2786
    }
 
2787
 
 
2788
    if (def->data.file.path == NULL) {
 
2789
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2790
                  "Expecting domain XML attribute 'path' of entry "
 
2791
                  "'devices/parallel/source' to be present");
 
2792
        return -1;
 
2793
    }
 
2794
 
 
2795
    virBufferVSprintf(buffer, "parallel%d.present = \"true\"\n", def->dstPort);
 
2796
 
 
2797
    /* def:type -> vmx:fileType and def:data.file.path -> vmx:fileName */
 
2798
    switch (def->type) {
 
2799
      case VIR_DOMAIN_CHR_TYPE_DEV:
 
2800
        virBufferVSprintf(buffer, "parallel%d.fileType = \"device\"\n",
 
2801
                          def->dstPort);
 
2802
        virBufferVSprintf(buffer, "parallel%d.fileName = \"%s\"\n",
 
2803
                          def->dstPort, def->data.file.path);
 
2804
        break;
 
2805
 
 
2806
      case VIR_DOMAIN_CHR_TYPE_FILE:
 
2807
        virBufferVSprintf(buffer, "parallel%d.fileType = \"file\"\n",
 
2808
                          def->dstPort);
 
2809
 
 
2810
        fileName = esxVMX_FormatFileName(conn, ctx, def->data.file.path);
 
2811
 
 
2812
        if (fileName == NULL) {
 
2813
            return -1;
 
2814
        }
 
2815
 
 
2816
        virBufferVSprintf(buffer, "parallel%d.fileName = \"%s\"\n",
 
2817
                          def->dstPort, fileName);
 
2818
 
 
2819
        VIR_FREE(fileName);
 
2820
        break;
 
2821
 
 
2822
      default:
 
2823
        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
 
2824
                  "Unsupported character device type '%s'",
 
2825
                  virDomainChrTypeToString(def->type));
 
2826
        return -1;
 
2827
    }
 
2828
 
 
2829
    return 0;
 
2830
}