Package com.vmware.aurora.composition

Source Code of com.vmware.aurora.composition.CreateVmSP

/***************************************************************************
* Copyright (c) 2012-2014 VMware, Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/

package com.vmware.aurora.composition;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Callable;

import com.vmware.aurora.composition.DiskSchema.Disk;
import com.vmware.aurora.exception.VcException;
import com.vmware.aurora.global.DiskSize;
import com.vmware.aurora.vc.DeviceId;
import com.vmware.aurora.vc.DiskType;
import com.vmware.aurora.vc.VcCache;
import com.vmware.aurora.vc.VcDatastore;
import com.vmware.aurora.vc.VcHost;
import com.vmware.aurora.vc.VcResourcePool;
import com.vmware.aurora.vc.VcSnapshot;
import com.vmware.aurora.vc.VcVirtualMachine;
import com.vmware.aurora.vc.VcVirtualMachine.DiskCreateSpec;
import com.vmware.aurora.vc.VmConfigUtil;
import com.vmware.aurora.vc.vcservice.VcContext;
import com.vmware.aurora.vc.vcservice.VcSession;
import com.vmware.vim.binding.impl.vim.vApp.ProductSpecImpl;
import com.vmware.vim.binding.impl.vim.vApp.VmConfigSpecImpl;
import com.vmware.vim.binding.impl.vim.vm.ConfigSpecImpl;
import com.vmware.vim.binding.impl.vim.vm.device.VirtualDiskImpl;
import com.vmware.vim.binding.vim.Folder;
import com.vmware.vim.binding.vim.option.ArrayUpdateSpec.Operation;
import com.vmware.vim.binding.vim.vApp.ProductInfo;
import com.vmware.vim.binding.vim.vApp.ProductSpec;
import com.vmware.vim.binding.vim.vApp.VmConfigInfo;
import com.vmware.vim.binding.vim.vApp.VmConfigSpec;
import com.vmware.vim.binding.vim.vm.ConfigSpec;
import com.vmware.vim.binding.vim.vm.device.VirtualDeviceSpec;
import com.vmware.vim.binding.vim.vm.device.VirtualDisk;

/**
* Stored Procedure for Creating a VM from a template
*
* @author sridharr
*
*/
public class CreateVmSP implements Callable<Void> {
   final String newVmName;
   final VmSchema vmSchema;
   final VcResourcePool targetRp;
   final VcDatastore targetDs;
   final IPrePostPowerOn prePowerOn;
   final IPrePostPowerOn postPowerOn;
   final Map<String, String> bootupConfigs;
   final boolean linkedClone;
   final Folder vmFolder; /* optional */
   final VcHost host; /* optinal */

   private VcVirtualMachine vcVm = null;

   public CreateVmSP(String newVmName, VmSchema vmSchema,
         VcResourcePool targetRp, VcDatastore targetDs,
         IPrePostPowerOn prePowerOn, IPrePostPowerOn postPowerOn,
         Map<String, String> bootupConfigs, boolean linkedClone, Folder vmFolder) {
      this(newVmName, vmSchema, targetRp, targetDs, prePowerOn, postPowerOn,
            bootupConfigs, linkedClone, vmFolder, null);
   }

   public CreateVmSP(String newVmName, VmSchema vmSchema,
         VcResourcePool targetRp, VcDatastore targetDs,
         IPrePostPowerOn prePowerOn, IPrePostPowerOn postPowerOn,
         Map<String, String> bootupConfigs, boolean linkedClone,
         Folder vmFolder, VcHost host) {
      this.newVmName = newVmName;
      this.vmSchema = vmSchema;
      this.targetRp = targetRp;
      this.targetDs = targetDs;
      this.prePowerOn = prePowerOn;
      this.postPowerOn = postPowerOn;
      this.bootupConfigs = bootupConfigs;
      this.linkedClone = linkedClone;
      this.vmFolder = vmFolder;
      this.host = host;
   }

   public CreateVmSP(VcVirtualMachine vcVm, VmSchema vmSchema,
         VcResourcePool targetRp, VcDatastore targetDs,
         IPrePostPowerOn prePowerOn, IPrePostPowerOn postPowerOn,
         Map<String, String> bootupConfigs, boolean linkedClone,
         Folder vmFolder, VcHost host) {
      this.vcVm = vcVm;
      this.newVmName = vcVm.getName();
      this.vmSchema = vmSchema;
      this.targetRp = targetRp;
      this.targetDs = targetDs;
      this.prePowerOn = prePowerOn;
      this.postPowerOn = postPowerOn;
      this.bootupConfigs = bootupConfigs;
      this.linkedClone = linkedClone;
      this.vmFolder = vmFolder;
      this.host = host;
   }

   @Override
   public Void call() throws Exception {
      VcContext.inVcSessionDo(new VcSession<Void>() {
         @Override
         protected boolean isTaskSession() {
            return true;
         }

         @Override
         protected Void body() throws Exception {
            callInternal();
            return null;
         }
      });
      return null;
   }

   private boolean requireClone() {
      for (Disk disk : vmSchema.diskSchema.getDisks()) {
         // if the system disk is already exist, skip clone
         if (DiskType.OS.getTypeName().equals(disk.type)
               && disk.vmdkPath != null && !disk.vmdkPath.isEmpty()) {
            return false;
         }
      }
      return true;
   }

   /**
    * copy parent vm's configurations, includes vApp configs, hardware version
    * info
    */
   private void copyParentVmSettings(VcVirtualMachine template,
         ConfigSpec configSpec) {
      configSpec.setName(newVmName);

      // copy guest OS info
      configSpec.setGuestId(template.getConfig().getGuestId());

      // copy hardware version
      configSpec.setVersion(template.getConfig().getVersion());


      // copy vApp config info
      VmConfigInfo configInfo = template.getConfig().getVAppConfig();

      // the parent vm might not have vApp option enabled. This is possible when user
      // used customized template.
      if (configInfo != null) {
         VmConfigSpec vAppSpec = new VmConfigSpecImpl();
         vAppSpec.setOvfEnvironmentTransport(configInfo
               .getOvfEnvironmentTransport());

         // product info
         List<ProductSpec> productSpecs = new ArrayList<ProductSpec>();
         for (ProductInfo info : configInfo.getProduct()) {
            ProductSpec spec = new ProductSpecImpl();
            spec.setInfo(info);
            spec.setOperation(Operation.add);
            productSpecs.add(spec);
         }
         vAppSpec.setProduct(productSpecs.toArray(new ProductSpec[productSpecs
               .size()]));

         configSpec.setVAppConfig(vAppSpec);
      }
   }

   public void callInternal() throws Exception {
      HashMap<String, Disk.Operation> diskMap = null;
      try {
         diskMap = createVm();
      } catch (Exception e) {
         throw VcException.CREATE_VM_FAILED(e, newVmName, e.getMessage());
      }

      try {
         configureVm(diskMap);
      } catch (Exception e) {
         throw VcException.CONFIG_VM_FAILED(e, newVmName, e.getMessage());
      }

      if (prePowerOn != null) {
         prePowerOn.setVm(vcVm);
         prePowerOn.call();
      }

      vcVm.powerOn(host);

      if (postPowerOn != null) {
         postPowerOn.setVm(vcVm);
         postPowerOn.call();
      }
   }

   private void configureVm(HashMap<String, Disk.Operation> diskMap)
         throws Exception {
      ConfigSpecImpl configSpec;
      configSpec = new ConfigSpecImpl();
      // Network changes
      NetworkSchemaUtil.setNetworkSchema(configSpec, targetRp.getVcCluster(),
            vmSchema.networkSchema, vcVm);

      vcVm.reconfigure(configSpec);

      if (host != null) {
         vcVm.disableDrs();
      }

      // Get list of disks to add
      List<VcHost> hostList = new ArrayList<VcHost>();
      List<DiskCreateSpec> addDisks =
            DiskSchemaUtil.getDisksToAdd(hostList, targetRp, targetDs,
                  vmSchema.diskSchema, diskMap);

      DiskCreateSpec[] tmpAddDisks =
            addDisks.toArray(new DiskCreateSpec[addDisks.size()]);

      // If current host of VM is not in the list of hosts with access to the
      // datastore(s) for the new disk(s), then migrate the VM first
      if (hostList.size() > 0 && !hostList.contains(vcVm.getHost())) {
         vcVm.migrate(hostList.get(0));
      }
      // add the new disks
      vcVm.changeDisks(null, tmpAddDisks);

      // attach existed disks
      List<VirtualDeviceSpec> deviceChange = new ArrayList<VirtualDeviceSpec>();
      for (Disk disk : vmSchema.diskSchema.getDisks()) {
         if (disk.vmdkPath == null || disk.vmdkPath.isEmpty())
            continue;

         VirtualDisk.FlatVer2BackingInfo backing =
               new VirtualDiskImpl.FlatVer2BackingInfoImpl();
         backing.setFileName(disk.vmdkPath);
         backing.setDiskMode(disk.mode.toString());

         deviceChange.add(vcVm.attachVirtualDiskSpec(new DeviceId(
               disk.externalAddress), backing, false, DiskSize
               .sizeFromMB(disk.initialSizeMB)));
      }

      if (!deviceChange.isEmpty()) {
         vcVm.reconfigure(VmConfigUtil.createConfigSpec(deviceChange));
      }

      if (linkedClone) {
         // Promote necessary disks
         ArrayList<DeviceId> disksToPromote = new ArrayList<DeviceId>();
         for (Entry<String, Disk.Operation> entry : diskMap.entrySet()) {
            if (entry.getValue() == Disk.Operation.PROMOTE) {
               disksToPromote.add(new DeviceId(entry.getKey()));
            }
         }
         if (disksToPromote.size() >= 1) {
            vcVm.promoteDisks(disksToPromote.toArray(new DeviceId[0]));
         }
      }

      // set the bootup configs
      if (bootupConfigs != null) {
         vcVm.setGuestConfigs(bootupConfigs);
      }
   }

   private HashMap<String, Disk.Operation> createVm() throws Exception {
      // Find the template and template snapshot to clone from
      final VcVirtualMachine template =
            VcCache.get(vmSchema.diskSchema.getParent());
      VcSnapshot snap =
            template.getSnapshotByName(vmSchema.diskSchema.getParentSnap());
      if (snap == null) {
         // this is a blocking call
         snap = template.createSnapshot(vmSchema.diskSchema.getParentSnap(),
               "Serengeti template Root Snapshot");
      }
      ConfigSpecImpl configSpec = new ConfigSpecImpl();

      // Resource schema
      ResourceSchemaUtil.setResourceSchema(configSpec, vmSchema.resourceSchema);

      // Add managed-by information
      // VmConfigUtil.addManagedByToConfigSpec(
      //      newConfigSpec, VcContext.getService().getExtensionKey(), "dbvm");

      HashMap<String, Disk.Operation> diskMap =
            new HashMap<String, Disk.Operation>();
      if (requireClone()) {
         VcVirtualMachine.CreateSpec vmSpec =
               new VcVirtualMachine.CreateSpec(newVmName, snap, targetRp,
                     targetDs, vmFolder, host, linkedClone, configSpec);
         // Clone from the template
         vcVm = template.cloneVm(vmSpec, null);
      } else {
         // copy parent vm's version/product info/vapp options
         copyParentVmSettings(template, configSpec);

         vcVm = targetRp.createVm(configSpec, targetDs, vmFolder);
      }
      return diskMap;
   }

   public VcVirtualMachine getVM() {
      return vcVm;
   }
}
TOP

Related Classes of com.vmware.aurora.composition.CreateVmSP

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.