You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ah...@apache.org on 2013/06/25 01:52:20 UTC

[44/50] [abbrv] merge is complete

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7b7db056/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
----------------------------------------------------------------------
diff --cc plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
index 87b3df3,5040443..f6fd69d
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
@@@ -31,18 -31,23 +31,69 @@@ import java.util.Comparator
  import java.util.Date;
  import java.util.GregorianCalendar;
  import java.util.HashMap;
++import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
++import java.util.Map.Entry;
  import java.util.Random;
++import java.util.Set;
  import java.util.TimeZone;
  import java.util.UUID;
  
  import javax.inject.Inject;
  import javax.naming.ConfigurationException;
  
 +import org.apache.log4j.Logger;
 +import org.apache.log4j.NDC;
 +
++import com.google.gson.Gson;
++import com.vmware.vim25.AboutInfo;
++import com.vmware.vim25.ClusterDasConfigInfo;
++import com.vmware.vim25.ComputeResourceSummary;
++import com.vmware.vim25.DatastoreSummary;
++import com.vmware.vim25.DynamicProperty;
++import com.vmware.vim25.GuestInfo;
++import com.vmware.vim25.HostCapability;
++import com.vmware.vim25.HostFirewallInfo;
++import com.vmware.vim25.HostFirewallRuleset;
++import com.vmware.vim25.HostNetworkTrafficShapingPolicy;
++import com.vmware.vim25.HostPortGroupSpec;
++import com.vmware.vim25.ManagedObjectReference;
++import com.vmware.vim25.ObjectContent;
++import com.vmware.vim25.OptionValue;
++import com.vmware.vim25.PerfCounterInfo;
++import com.vmware.vim25.PerfEntityMetric;
++import com.vmware.vim25.PerfEntityMetricBase;
++import com.vmware.vim25.PerfMetricId;
++import com.vmware.vim25.PerfMetricIntSeries;
++import com.vmware.vim25.PerfMetricSeries;
++import com.vmware.vim25.PerfQuerySpec;
++import com.vmware.vim25.PerfSampleInfo;
++import com.vmware.vim25.RuntimeFaultFaultMsg;
++import com.vmware.vim25.ToolsUnavailableFaultMsg;
++import com.vmware.vim25.VimPortType;
++import com.vmware.vim25.VirtualDevice;
++import com.vmware.vim25.VirtualDeviceConfigSpec;
++import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
++import com.vmware.vim25.VirtualDisk;
++import com.vmware.vim25.VirtualEthernetCard;
++import com.vmware.vim25.VirtualEthernetCardNetworkBackingInfo;
++import com.vmware.vim25.VirtualLsiLogicController;
++import com.vmware.vim25.VirtualMachineConfigSpec;
++import com.vmware.vim25.VirtualMachineFileInfo;
++import com.vmware.vim25.VirtualMachineGuestOsIdentifier;
++import com.vmware.vim25.VirtualMachinePowerState;
++import com.vmware.vim25.VirtualMachineRelocateSpec;
++import com.vmware.vim25.VirtualMachineRelocateSpecDiskLocator;
++import com.vmware.vim25.VirtualMachineRuntimeInfo;
++import com.vmware.vim25.VirtualSCSISharing;
++
+ import org.apache.cloudstack.storage.command.DeleteCommand;
+ import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
+ import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
+ import org.apache.cloudstack.storage.to.TemplateObjectTO;
+ import org.apache.cloudstack.storage.to.VolumeObjectTO;
 -import org.apache.log4j.Logger;
 -import org.apache.log4j.NDC;
+ 
  import com.cloud.agent.IAgentControl;
  import com.cloud.agent.api.Answer;
  import com.cloud.agent.api.AttachIsoCommand;
@@@ -74,9 -79,9 +125,6 @@@ import com.cloud.agent.api.CreateVolume
  import com.cloud.agent.api.DeleteStoragePoolCommand;
  import com.cloud.agent.api.DeleteVMSnapshotAnswer;
  import com.cloud.agent.api.DeleteVMSnapshotCommand;
--import com.cloud.agent.api.MigrateWithStorageAnswer;
--import com.cloud.agent.api.MigrateWithStorageCommand;
--import com.cloud.agent.api.UnregisterVMCommand;
  import com.cloud.agent.api.GetDomRVersionAnswer;
  import com.cloud.agent.api.GetDomRVersionCmd;
  import com.cloud.agent.api.GetHostStatsAnswer;
@@@ -94,6 -99,6 +142,8 @@@ import com.cloud.agent.api.ManageSnapsh
  import com.cloud.agent.api.ManageSnapshotCommand;
  import com.cloud.agent.api.MigrateAnswer;
  import com.cloud.agent.api.MigrateCommand;
++import com.cloud.agent.api.MigrateWithStorageAnswer;
++import com.cloud.agent.api.MigrateWithStorageCommand;
  import com.cloud.agent.api.ModifySshKeysCommand;
  import com.cloud.agent.api.ModifyStoragePoolAnswer;
  import com.cloud.agent.api.ModifyStoragePoolCommand;
@@@ -131,6 -136,6 +181,7 @@@ import com.cloud.agent.api.StopCommand
  import com.cloud.agent.api.StoragePoolInfo;
  import com.cloud.agent.api.UnPlugNicAnswer;
  import com.cloud.agent.api.UnPlugNicCommand;
++import com.cloud.agent.api.UnregisterVMCommand;
  import com.cloud.agent.api.UpgradeSnapshotCommand;
  import com.cloud.agent.api.ValidateSnapshotAnswer;
  import com.cloud.agent.api.ValidateSnapshotCommand;
@@@ -165,16 -170,16 +216,16 @@@ import com.cloud.agent.api.routing.VmDa
  import com.cloud.agent.api.routing.VpnUsersCfgCommand;
  import com.cloud.agent.api.storage.CopyVolumeAnswer;
  import com.cloud.agent.api.storage.CopyVolumeCommand;
--import com.cloud.agent.api.storage.CreateVolumeOVACommand;
++import com.cloud.agent.api.storage.CreateAnswer;
++import com.cloud.agent.api.storage.CreateCommand;
++import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
  import com.cloud.agent.api.storage.CreateVolumeOVAAnswer;
++import com.cloud.agent.api.storage.CreateVolumeOVACommand;
++import com.cloud.agent.api.storage.DestroyCommand;
  import com.cloud.agent.api.storage.MigrateVolumeAnswer;
  import com.cloud.agent.api.storage.MigrateVolumeCommand;
  import com.cloud.agent.api.storage.PrepareOVAPackingAnswer;
  import com.cloud.agent.api.storage.PrepareOVAPackingCommand;
--import com.cloud.agent.api.storage.CreateAnswer;
--import com.cloud.agent.api.storage.CreateCommand;
--import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
--import com.cloud.agent.api.storage.DestroyCommand;
  import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
  import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
  import com.cloud.agent.api.storage.ResizeVolumeAnswer;
@@@ -247,51 -259,51 +306,6 @@@ import com.cloud.vm.VirtualMachine.Powe
  import com.cloud.vm.VirtualMachine.State;
  import com.cloud.vm.VirtualMachineName;
  import com.cloud.vm.VmDetailConstants;
--import com.google.gson.Gson;
--import com.vmware.vim25.AboutInfo;
--import com.vmware.vim25.ClusterDasConfigInfo;
--import com.vmware.vim25.ComputeResourceSummary;
--import com.vmware.vim25.DatastoreSummary;
--import com.vmware.vim25.DynamicProperty;
--import com.vmware.vim25.GuestInfo;
--import com.vmware.vim25.HostCapability;
--import com.vmware.vim25.HostFirewallInfo;
--import com.vmware.vim25.HostFirewallRuleset;
--import com.vmware.vim25.HostNetworkTrafficShapingPolicy;
--import com.vmware.vim25.HostPortGroupSpec;
--import com.vmware.vim25.ManagedObjectReference;
--import com.vmware.vim25.ObjectContent;
--import com.vmware.vim25.OptionValue;
--import com.vmware.vim25.PerfCounterInfo;
--import com.vmware.vim25.PerfEntityMetric;
--import com.vmware.vim25.PerfEntityMetricBase;
--import com.vmware.vim25.PerfMetricId;
--import com.vmware.vim25.PerfMetricIntSeries;
--import com.vmware.vim25.PerfMetricSeries;
--import com.vmware.vim25.PerfQuerySpec;
--import com.vmware.vim25.PerfSampleInfo;
--import com.vmware.vim25.RuntimeFaultFaultMsg;
--import com.vmware.vim25.ToolsUnavailableFaultMsg;
--import com.vmware.vim25.VimPortType;
--import com.vmware.vim25.VirtualDevice;
--import com.vmware.vim25.VirtualDeviceConfigSpec;
--import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
--import com.vmware.vim25.VirtualDisk;
--import com.vmware.vim25.VirtualEthernetCard;
--import com.vmware.vim25.VirtualEthernetCardNetworkBackingInfo;
--import com.vmware.vim25.VirtualLsiLogicController;
--import com.vmware.vim25.VirtualMachineConfigSpec;
--import com.vmware.vim25.VirtualMachineFileInfo;
--import com.vmware.vim25.VirtualMachineGuestOsIdentifier;
--import com.vmware.vim25.VirtualMachinePowerState;
--import com.vmware.vim25.VirtualMachineRelocateSpec;
--import com.vmware.vim25.VirtualMachineRelocateSpecDiskLocator;
--import com.vmware.vim25.VirtualMachineRuntimeInfo;
--import com.vmware.vim25.VirtualSCSISharing;
--
--import java.util.HashSet;
--import java.util.Set;
--import java.util.Map.Entry;
  
  public class VmwareResource implements StoragePoolResource, ServerResource, VmwareHostService {
      private static final Logger s_logger = Logger.getLogger(VmwareResource.class);
@@@ -343,14 -355,20 +357,20 @@@
  
      protected volatile long _cmdSequence = 1;
  
+     protected StorageSubsystemCommandHandler storageHandler;
+ 
 -    protected static HashMap<VirtualMachinePowerState, State> s_statesTable;
 +    protected static HashMap<VirtualMachinePowerState, PowerState> s_statesTable;
      static {
 -        s_statesTable = new HashMap<VirtualMachinePowerState, State>();
 -        s_statesTable.put(VirtualMachinePowerState.POWERED_ON, State.Running);
 -        s_statesTable.put(VirtualMachinePowerState.POWERED_OFF, State.Stopped);
 -        s_statesTable.put(VirtualMachinePowerState.SUSPENDED, State.Stopped);
 +        s_statesTable = new HashMap<VirtualMachinePowerState, PowerState>();
 +        s_statesTable.put(VirtualMachinePowerState.POWERED_ON, PowerState.PowerOn);
 +        s_statesTable.put(VirtualMachinePowerState.POWERED_OFF, PowerState.PowerOff);
 +        s_statesTable.put(VirtualMachinePowerState.SUSPENDED, PowerState.PowerOn);
      }
  
+     public Gson getGson() {
+     	return _gson;
+     }
+ 
      public VmwareResource() {
          _gson = GsonHelper.getGsonLogger();
      }
@@@ -1710,11 -1738,11 +1740,11 @@@
              vSwitchType = _publicTrafficInfo.getVirtualSwitchType();
          }
          if (VirtualSwitchType.StandardVirtualSwitch == vSwitchType) {
-             networkInfo = HypervisorHostHelper.prepareNetwork(this._publicTrafficInfo.getVirtualSwitchName(), "cloud.public",
-                     vmMo.getRunningHost(), vlanId, null, null, this._ops_timeout, true);
+             networkInfo = HypervisorHostHelper.prepareNetwork(_publicTrafficInfo.getVirtualSwitchName(), "cloud.public",
+                     vmMo.getRunningHost(), vlanId, null, null, _ops_timeout, true);
          } else {
--            networkInfo = HypervisorHostHelper.prepareNetwork(this._publicTrafficInfo.getVirtualSwitchName(), "cloud.public",
--                    vmMo.getRunningHost(), vlanId, null, null, null, this._ops_timeout, vSwitchType, _portsPerDvPortGroup, null, false);
++            networkInfo = HypervisorHostHelper.prepareNetwork(_publicTrafficInfo.getVirtualSwitchName(), "cloud.public",
++                    vmMo.getRunningHost(), vlanId, null, null, null, _ops_timeout, vSwitchType, _portsPerDvPortGroup, null, false);
          }
  
          int nicIndex = allocPublicNicIndex(vmMo);
@@@ -2305,14 -2333,21 +2335,21 @@@
          return new CheckSshAnswer(cmd);
      }
  
-     private VolumeTO[] validateDisks(VolumeTO[] disks) {
-         List<VolumeTO> validatedDisks = new ArrayList<VolumeTO>();
+     private DiskTO[] validateDisks(DiskTO[] disks) {
+         List<DiskTO> validatedDisks = new ArrayList<DiskTO>();
  
-         for (VolumeTO vol : disks) {
-             if (vol.getPoolUuid() != null && !vol.getPoolUuid().isEmpty()) {
+         for (DiskTO vol : disks) {
+             if (vol.getType() != Volume.Type.ISO) {
+             	VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData();
+             	PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
+             	if (primaryStore.getUuid() != null && !primaryStore.getUuid().isEmpty()) {
 -            		validatedDisks.add(vol);
 +                validatedDisks.add(vol);
-             } else if (vol.getPoolType() == StoragePoolType.ISO && (vol.getPath() != null && !vol.getPath().isEmpty())) {
+             	}
+             } else if (vol.getType() == Volume.Type.ISO) {
+             	TemplateObjectTO templateTO = (TemplateObjectTO)vol.getData();
+             	if (templateTO.getPath() != null && !templateTO.getPath().isEmpty()) {
 -            		validatedDisks.add(vol);
 +                validatedDisks.add(vol);
+             	}
              } else {
                  if (s_logger.isDebugEnabled()) {
                      s_logger.debug("Drop invalid disk option, volumeTO: " + _gson.toJson(vol));
@@@ -2511,23 -2547,35 +2549,35 @@@
                  }
              } else {
                  // we will always plugin a CDROM device
-                 if (volIso != null && volIso.getPath() != null && !volIso.getPath().isEmpty()) {
-                     Pair<String, ManagedObjectReference> isoDatastoreInfo = getIsoDatastoreInfo(hyperHost, volIso.getPath());
+ 
+                 if (volIso != null) {
+                 	TemplateObjectTO iso = (TemplateObjectTO)volIso.getData();
+ 
+                 	if (iso.getPath() != null && !iso.getPath().isEmpty()) {
+                 		DataStoreTO imageStore = iso.getDataStore();
+                 		if (!(imageStore instanceof NfsTO)) {
+                 			s_logger.debug("unsupported protocol");
+                 			throw new Exception("unsupported protocol");
+                 		}
+                 		NfsTO nfsImageStore = (NfsTO)imageStore;
+                 		String isoPath = nfsImageStore.getUrl() + File.separator + iso.getPath();
+                 		Pair<String, ManagedObjectReference> isoDatastoreInfo = getIsoDatastoreInfo(hyperHost, isoPath);
 -                		assert (isoDatastoreInfo != null);
 -                		assert (isoDatastoreInfo.second() != null);
 +                    assert (isoDatastoreInfo != null);
 +                    assert (isoDatastoreInfo.second() != null);
  
 -                		deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
 +                    deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
                      Pair<VirtualDevice, Boolean> isoInfo = VmwareHelper.prepareIsoDevice(vmMo, isoDatastoreInfo.first(), isoDatastoreInfo.second(), true, true, ideUnitNumber++, i + 1);
 -                		deviceConfigSpecArray[i].setDevice(isoInfo.first());
 -                		if (isoInfo.second()) {
 -                			if(s_logger.isDebugEnabled())
 -                				s_logger.debug("Prepare ISO volume at new device " + _gson.toJson(isoInfo.first()));
 -                			deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD);
 -                		} else {
 -                			if(s_logger.isDebugEnabled())
 -                				s_logger.debug("Prepare ISO volume at existing device " + _gson.toJson(isoInfo.first()));
 -                			deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.EDIT);
 -                		}
 +                    deviceConfigSpecArray[i].setDevice(isoInfo.first());
 +                    if (isoInfo.second()) {
 +                        if(s_logger.isDebugEnabled())
 +                            s_logger.debug("Prepare ISO volume at new device " + _gson.toJson(isoInfo.first()));
 +                        deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD);
 +                    } else {
 +                        if(s_logger.isDebugEnabled())
 +                            s_logger.debug("Prepare ISO volume at existing device " + _gson.toJson(isoInfo.first()));
 +                        deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.EDIT);
 +                    }
+                 	}
                  } else {
                      deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
                      Pair<VirtualDevice, Boolean> isoInfo = VmwareHelper.prepareIsoDevice(vmMo, null, null, true, true, ideUnitNumber++, i + 1);
@@@ -5019,16 -5070,7 +5071,16 @@@
              details.put("NativeHA", "true");
          }
      }
 +    
 +    protected HashMap<String, PowerState> sync() {
 +    	try {
-     		return this.getVmStates();
++    		return getVmStates();
 +    	} catch(Exception e) {
 +    		return new HashMap<String, PowerState>();
 +    	}
 +    }
  
 +/*
      protected HashMap<String, State> sync() {
          HashMap<String, State> changes = new HashMap<String, State>();
          HashMap<String, State> oldStates = null;
@@@ -5543,7 -5589,7 +5595,7 @@@
          return s_statesTable.get(powerState);
      }
  
-     private static PowerState getVmState(VirtualMachineMO vmMo) throws Exception {
 -    public static State getVmState(VirtualMachineMO vmMo) throws Exception {
++    public static PowerState getVmState(VirtualMachineMO vmMo) throws Exception {
          VirtualMachineRuntimeInfo runtimeInfo = vmMo.getRuntimeInfo();
          return convertState(runtimeInfo.getPowerState());
      }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7b7db056/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
----------------------------------------------------------------------
diff --cc plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
index 0000000,d3df0f5..cc83998
mode 000000,100644..100644
--- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
@@@ -1,0 -1,1288 +1,1283 @@@
+ // Licensed to the Apache Software Foundation (ASF) under one
+ // or more contributor license agreements.  See the NOTICE file
+ // distributed with this work for additional information
+ // regarding copyright ownership.  The ASF licenses this file
+ // to you 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 
++// KIND, either express or implied.  See the License for the
+ // specific language governing permissions and limitations
+ // under the License.
+ package com.cloud.storage.resource;
+ 
+ import java.io.BufferedWriter;
+ import java.io.File;
+ import java.io.FileOutputStream;
+ import java.io.OutputStreamWriter;
+ import java.net.URI;
+ import java.rmi.RemoteException;
+ import java.util.HashMap;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.UUID;
+ 
++import org.apache.log4j.Logger;
++
++import com.google.gson.Gson;
++import com.vmware.vim25.ManagedObjectReference;
++import com.vmware.vim25.VirtualDeviceConfigSpec;
++import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
++import com.vmware.vim25.VirtualDisk;
++import com.vmware.vim25.VirtualEthernetCard;
++import com.vmware.vim25.VirtualLsiLogicController;
++import com.vmware.vim25.VirtualMachineConfigSpec;
++import com.vmware.vim25.VirtualMachineFileInfo;
++import com.vmware.vim25.VirtualMachineGuestOsIdentifier;
++import com.vmware.vim25.VirtualSCSISharing;
++
+ import org.apache.cloudstack.storage.command.AttachAnswer;
+ import org.apache.cloudstack.storage.command.AttachCommand;
+ import org.apache.cloudstack.storage.command.CopyCmdAnswer;
+ import org.apache.cloudstack.storage.command.CopyCommand;
+ import org.apache.cloudstack.storage.command.CreateObjectAnswer;
+ import org.apache.cloudstack.storage.command.CreateObjectCommand;
+ import org.apache.cloudstack.storage.command.DeleteCommand;
+ import org.apache.cloudstack.storage.command.DettachCommand;
+ import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
+ import org.apache.cloudstack.storage.to.SnapshotObjectTO;
+ import org.apache.cloudstack.storage.to.TemplateObjectTO;
+ import org.apache.cloudstack.storage.to.VolumeObjectTO;
 -import org.apache.log4j.Logger;
+ 
+ import com.cloud.agent.api.Answer;
 -import com.cloud.agent.api.BackupSnapshotAnswer;
+ import com.cloud.agent.api.Command;
 -import com.cloud.agent.api.CreateVolumeFromSnapshotAnswer;
 -import com.cloud.agent.api.ManageSnapshotAnswer;
 -import com.cloud.agent.api.ManageSnapshotCommand;
 -import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
 -import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
+ import com.cloud.agent.api.to.DataStoreTO;
+ import com.cloud.agent.api.to.DataTO;
+ import com.cloud.agent.api.to.DiskTO;
+ import com.cloud.agent.api.to.NfsTO;
 -import com.cloud.agent.api.to.VolumeTO;
+ import com.cloud.hypervisor.vmware.manager.VmwareHostService;
+ import com.cloud.hypervisor.vmware.manager.VmwareStorageMount;
+ import com.cloud.hypervisor.vmware.mo.ClusterMO;
+ import com.cloud.hypervisor.vmware.mo.CustomFieldConstants;
+ import com.cloud.hypervisor.vmware.mo.DatacenterMO;
+ import com.cloud.hypervisor.vmware.mo.DatastoreMO;
+ import com.cloud.hypervisor.vmware.mo.HostMO;
+ import com.cloud.hypervisor.vmware.mo.HypervisorHostHelper;
+ import com.cloud.hypervisor.vmware.mo.NetworkDetails;
+ import com.cloud.hypervisor.vmware.mo.VirtualMachineMO;
+ import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
+ import com.cloud.hypervisor.vmware.resource.VmwareResource;
+ import com.cloud.hypervisor.vmware.util.VmwareContext;
+ import com.cloud.hypervisor.vmware.util.VmwareHelper;
+ import com.cloud.serializer.GsonHelper;
+ import com.cloud.storage.DataStoreRole;
+ import com.cloud.storage.JavaStorageLayer;
++import com.cloud.storage.Storage.ImageFormat;
+ import com.cloud.storage.StorageLayer;
+ import com.cloud.storage.Volume;
 -import com.cloud.storage.Storage.ImageFormat;
+ import com.cloud.storage.template.VmdkProcessor;
+ import com.cloud.utils.Pair;
+ import com.cloud.utils.StringUtils;
+ import com.cloud.utils.Ternary;
+ import com.cloud.utils.script.Script;
 -import com.cloud.vm.VirtualMachine.State;
 -import com.google.gson.Gson;
 -import com.vmware.vim25.ManagedObjectReference;
 -import com.vmware.vim25.VirtualDeviceConfigSpec;
 -import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
 -import com.vmware.vim25.VirtualDisk;
 -import com.vmware.vim25.VirtualEthernetCard;
 -import com.vmware.vim25.VirtualLsiLogicController;
 -import com.vmware.vim25.VirtualMachineConfigSpec;
 -import com.vmware.vim25.VirtualMachineFileInfo;
 -import com.vmware.vim25.VirtualMachineGuestOsIdentifier;
 -import com.vmware.vim25.VirtualSCSISharing;
++import com.cloud.vm.VirtualMachine.PowerState;
+ 
+ public class VmwareStorageProcessor implements StorageProcessor {
+ 	private static final Logger s_logger = Logger.getLogger(VmwareStorageProcessor.class);
 -	private VmwareHostService hostService;
 -	private boolean _fullCloneFlag;
 -	private VmwareStorageMount mountService;
 -	private VmwareResource resource;
 -	private Integer _timeout;
++	private final VmwareHostService hostService;
++	private final boolean _fullCloneFlag;
++	private final VmwareStorageMount mountService;
++	private final VmwareResource resource;
++	private final Integer _timeout;
+ 	protected Integer _shutdown_waitMs;
+ 	private final Gson _gson;
+ 	private final StorageLayer _storage = new JavaStorageLayer();
+ 	public VmwareStorageProcessor(VmwareHostService hostService, boolean fullCloneFlag, VmwareStorageMount mountService,
+ 			Integer timeout,
+ 			VmwareResource resource,
+ 			Integer shutdownWaitMs) {
+ 		this.hostService = hostService;
 -		this._fullCloneFlag = fullCloneFlag;
++		_fullCloneFlag = fullCloneFlag;
+ 		this.mountService = mountService;
 -		this._timeout = timeout;
++		_timeout = timeout;
+ 		this.resource = resource;
 -		this._shutdown_waitMs = shutdownWaitMs;
++		_shutdown_waitMs = shutdownWaitMs;
+ 		_gson = GsonHelper.getGsonLogger();
+ 	}
+ 	
+ 	private String getOVFFilePath(String srcOVAFileName) {
+         File file = new File(srcOVAFileName);
+         assert(_storage != null);
+         String[] files = _storage.listFiles(file.getParent());
+         if(files != null) {
+             for(String fileName : files) {
+                 if(fileName.toLowerCase().endsWith(".ovf")) {
+                     File ovfFile = new File(fileName);
+                     return file.getParent() + File.separator + ovfFile.getName();
+                 }
+             }
+         }
+         return null;
+     }
+ 	 private void copyTemplateFromSecondaryToPrimary(VmwareHypervisorHost hyperHost, DatastoreMO datastoreMo, String secondaryStorageUrl,
+ 		        String templatePathAtSecondaryStorage, String templateName, String templateUuid) throws Exception {
+ 
+ 		        s_logger.info("Executing copyTemplateFromSecondaryToPrimary. secondaryStorage: "
+ 		            + secondaryStorageUrl + ", templatePathAtSecondaryStorage: " + templatePathAtSecondaryStorage
+ 		            + ", templateName: " + templateName);
+ 
+ 		        String secondaryMountPoint = mountService.getMountPoint(secondaryStorageUrl);
+ 		        s_logger.info("Secondary storage mount point: " + secondaryMountPoint);
+ 
+ 		        String srcOVAFileName = secondaryMountPoint + "/" +  templatePathAtSecondaryStorage +
+ 		            templateName + "." + ImageFormat.OVA.getFileExtension();
+ 
+ 		        String srcFileName = getOVFFilePath(srcOVAFileName);
+ 		        if(srcFileName == null) {
+ 		            Script command = new Script("tar", 0, s_logger);
+ 		            command.add("--no-same-owner");
+ 		            command.add("-xf", srcOVAFileName);
+ 		            command.setWorkDir(secondaryMountPoint + "/" +  templatePathAtSecondaryStorage);
+ 		            s_logger.info("Executing command: " + command.toString());
+ 		            String result = command.execute();
+ 		            if(result != null) {
+ 		                String msg = "Unable to unpack snapshot OVA file at: " + srcOVAFileName;
+ 		                s_logger.error(msg);
+ 		                throw new Exception(msg);
+ 		            }
+ 		        }
+ 
+ 		        srcFileName = getOVFFilePath(srcOVAFileName);
+ 		        if(srcFileName == null) {
+ 		            String msg = "Unable to locate OVF file in template package directory: " + srcOVAFileName;
+ 		            s_logger.error(msg);
+ 		            throw new Exception(msg);
+ 		        }
+ 
+ 		        String vmName = templateUuid;
+ 		        hyperHost.importVmFromOVF(srcFileName, vmName, datastoreMo, "thin");
+ 
+ 		        VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
+ 		        if(vmMo == null) {
+ 		            String msg = "Failed to import OVA template. secondaryStorage: "
+ 		                + secondaryStorageUrl + ", templatePathAtSecondaryStorage: " + templatePathAtSecondaryStorage
+ 		                + ", templateName: " + templateName + ", templateUuid: " + templateUuid;
+ 		            s_logger.error(msg);
+ 		            throw new Exception(msg);
+ 		        }
+ 
+ 		        if(vmMo.createSnapshot("cloud.template.base", "Base snapshot", false, false)) {
+ 		            vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_UUID, templateUuid);
+ 		            vmMo.markAsTemplate();
+ 		        } else {
+ 		            vmMo.destroy();
+ 		            String msg = "Unable to create base snapshot for template, templateName: " + templateName + ", templateUuid: " + templateUuid;
+ 		            s_logger.error(msg);
+ 		            throw new Exception(msg);
+ 		        }
+ 		    }
+ 	
+ 	@Override
+ 	public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) {
+ 		DataTO srcData = cmd.getSrcTO();
+ 		TemplateObjectTO template = (TemplateObjectTO)srcData;
+ 		DataStoreTO srcStore = srcData.getDataStore();
+ 		if (!(srcStore instanceof NfsTO)) {
+ 			return new CopyCmdAnswer("unsupported protocol");
+ 		}
+ 		NfsTO nfsImageStore = (NfsTO)srcStore;
+ 		DataTO destData = cmd.getDestTO();
+ 		DataStoreTO destStore = destData.getDataStore();
+ 		PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)destStore;
+ 		String secondaryStorageUrl = nfsImageStore.getUrl();
+ 		assert (secondaryStorageUrl != null);
+ 
+ 		String templateUrl = secondaryStorageUrl + File.separator + srcData.getPath();
+ 
+ 		String templateName = null;
+ 		String mountPoint = null;
+ 		if (templateUrl.endsWith(".ova")) {
+ 			int index = templateUrl.lastIndexOf("/");
+ 			mountPoint = templateUrl.substring(0, index);
+ 			mountPoint = mountPoint.substring(secondaryStorageUrl.length() + 1);
+ 			if (!mountPoint.endsWith("/")) {
+ 				mountPoint = mountPoint + "/";
+ 			}
+ 
+ 			templateName = templateUrl.substring(index + 1).replace("." + ImageFormat.OVA.getFileExtension(), "");
+ 
+ 			if (templateName == null || templateName.isEmpty()) {
+ 				templateName = template.getName();
+ 			}
+ 		} else {
+ 			mountPoint = templateUrl.substring(secondaryStorageUrl.length() + 1);
+ 			if (!mountPoint.endsWith("/")) {
+ 				mountPoint = mountPoint + "/";
+ 			}
+ 			templateName = template.getName();
+ 		}
+ 
+ 		VmwareContext context = hostService.getServiceContext(cmd);
+ 		try {
+ 			VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
+ 
+ 			String templateUuidName = UUID.nameUUIDFromBytes((templateName + "@" + primaryStore.getUuid() + "-" + hyperHost.getMor().getValue()).getBytes()).toString();
+ 			// truncate template name to 32 chars to ensure they work well with vSphere API's.
+ 			templateUuidName = templateUuidName.replace("-", "");
+ 
+ 			DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
+ 			VirtualMachineMO templateMo = VmwareHelper.pickOneVmOnRunningHost(dcMo.findVmByNameAndLabel(templateUuidName), true);
+ 
+ 			if (templateMo == null) {
+ 			    if(s_logger.isInfoEnabled())
+ 			        s_logger.info("Template " + templateName + " is not setup yet, setup template from secondary storage with uuid name: " + templateUuidName);
+ 				ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid());
+ 				assert (morDs != null);
+ 				DatastoreMO primaryStorageDatastoreMo = new DatastoreMO(context, morDs);
+ 
+ 				copyTemplateFromSecondaryToPrimary(hyperHost,
+ 					primaryStorageDatastoreMo, secondaryStorageUrl,
+ 					mountPoint, templateName, templateUuidName);
+ 			} else {
+ 				s_logger.info("Template " + templateName + " has already been setup, skip the template setup process in primary storage");
+ 			}
+ 
+ 			TemplateObjectTO newTemplate = new TemplateObjectTO();
+ 			newTemplate.setPath(templateUuidName);
+ 			return new CopyCmdAnswer(newTemplate);
+ 		} catch (Throwable e) {
+ 			if (e instanceof RemoteException) {
+ 				hostService.invalidateServiceContext(context);
+ 			}
+ 
+ 			String msg = "Unable to execute PrimaryStorageDownloadCommand due to exception";
+ 			s_logger.error(msg, e);
+ 			return new CopyCmdAnswer(msg);
+ 		}
+ 	}
+ 	private boolean createVMLinkedClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo,
+             String vmdkName, ManagedObjectReference morDatastore, ManagedObjectReference morPool) throws Exception {
+ 
+         ManagedObjectReference morBaseSnapshot = vmTemplate.getSnapshotMor("cloud.template.base");
+         if (morBaseSnapshot == null) {
+             String msg = "Unable to find template base snapshot, invalid template";
+             s_logger.error(msg);
+             throw new Exception(msg);
+         }
+ 
+         if(dsMo.folderExists(String.format("[%s]", dsMo.getName()), vmdkName))
+             dsMo.deleteFile(String.format("[%s] %s/", dsMo.getName(), vmdkName), dcMo.getMor(), false);
+ 
+         s_logger.info("creating linked clone from template");
+         if (!vmTemplate.createLinkedClone(vmdkName, morBaseSnapshot, dcMo.getVmFolder(), morPool, morDatastore)) {
+             String msg = "Unable to clone from the template";
+             s_logger.error(msg);
+             throw new Exception(msg);
+         }
+ 
+         // we can't rely on un-offical API (VirtualMachineMO.moveAllVmDiskFiles() any more, use hard-coded disk names that we know
+         // to move files
+         s_logger.info("Move volume out of volume-wrapper VM ");
+         dsMo.moveDatastoreFile(String.format("[%s] %s/%s.vmdk", dsMo.getName(), vmdkName, vmdkName),
+                 dcMo.getMor(), dsMo.getMor(),
+                 String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
+ 
+         dsMo.moveDatastoreFile(String.format("[%s] %s/%s-delta.vmdk", dsMo.getName(), vmdkName, vmdkName),
+                 dcMo.getMor(), dsMo.getMor(),
+                 String.format("[%s] %s-delta.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
+ 
+         return true;
+     }
+ 
+ 	private boolean createVMFullClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo,
+             String vmdkName, ManagedObjectReference morDatastore, ManagedObjectReference morPool) throws Exception {
+ 
+         if(dsMo.folderExists(String.format("[%s]", dsMo.getName()), vmdkName))
+             dsMo.deleteFile(String.format("[%s] %s/", dsMo.getName(), vmdkName), dcMo.getMor(), false);
+ 
+         s_logger.info("creating full clone from template");
+         if (!vmTemplate.createFullClone(vmdkName, dcMo.getVmFolder(), morPool, morDatastore)) {
+             String msg = "Unable to create full clone from the template";
+             s_logger.error(msg);
+             throw new Exception(msg);
+         }
+ 
+         // we can't rely on un-offical API (VirtualMachineMO.moveAllVmDiskFiles() any more, use hard-coded disk names that we know
+         // to move files
+         s_logger.info("Move volume out of volume-wrapper VM ");
+         dsMo.moveDatastoreFile(String.format("[%s] %s/%s.vmdk", dsMo.getName(), vmdkName, vmdkName),
+                 dcMo.getMor(), dsMo.getMor(),
+                 String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
+ 
+         dsMo.moveDatastoreFile(String.format("[%s] %s/%s-flat.vmdk", dsMo.getName(), vmdkName, vmdkName),
+                 dcMo.getMor(), dsMo.getMor(),
+                 String.format("[%s] %s-flat.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
+ 
+         return true;
+     }
+ 
+ 	@Override
+ 	public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd) {
+ 		DataTO srcData = cmd.getSrcTO();
+ 		TemplateObjectTO template = (TemplateObjectTO)srcData;
+ 		DataTO destData = cmd.getDestTO();
+ 		VolumeObjectTO volume = (VolumeObjectTO)destData;
+ 		PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
+ 		PrimaryDataStoreTO srcStore = (PrimaryDataStoreTO)template.getDataStore();
+ 
+ 		
+ 		try {
 -			VmwareContext context = this.hostService.getServiceContext(null);
 -			VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(context, null);
++			VmwareContext context = hostService.getServiceContext(null);
++			VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, null);
+ 			DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
+ 			VirtualMachineMO vmMo = null;
+ 			ManagedObjectReference morDatastore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid());
+ 			if (morDatastore == null)
+ 				throw new Exception("Unable to find datastore in vSphere");
+ 
+ 			DatastoreMO dsMo = new DatastoreMO(context, morDatastore);
+ 
+ 
+ 			// attach volume id to make the name unique
+ 			String vmdkName = volume.getName() + "-" + volume.getId();
+ 			if (srcStore == null) {
+ 				// create a root volume for blank VM
 -				String dummyVmName = this.hostService.getWorkerName(context, cmd, 0);
++				String dummyVmName = hostService.getWorkerName(context, cmd, 0);
+ 
+ 				try {
+ 					vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName);
+ 					if (vmMo == null) {
+ 						throw new Exception("Unable to create a dummy VM for volume creation");
+ 					}
+ 
+ 					String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName);
+ 					synchronized (this) {
+ 						s_logger.info("Delete file if exists in datastore to clear the way for creating the volume. file: " + volumeDatastorePath);
+ 						VmwareHelper.deleteVolumeVmdkFiles(dsMo, vmdkName, dcMo);
+ 						vmMo.createDisk(volumeDatastorePath, (int) (volume.getSize() / (1024L * 1024L)), morDatastore, -1);
+ 						vmMo.detachDisk(volumeDatastorePath, false);
+ 					}
+ 
+ 					VolumeObjectTO newVol = new VolumeObjectTO();
+ 					newVol.setPath(vmdkName);
+ 					return new CopyCmdAnswer(newVol);
+ 				} finally {
+ 					vmMo.detachAllDisks();
+ 
+ 					s_logger.info("Destroy dummy VM after volume creation");
+ 					vmMo.destroy();
+ 				}
+ 			} else {
+ 				String templatePath = template.getPath();
+ 				VirtualMachineMO vmTemplate = VmwareHelper.pickOneVmOnRunningHost(dcMo.findVmByNameAndLabel(templatePath), true);
+ 				if (vmTemplate == null) {
+ 					s_logger.warn("Template host in vSphere is not in connected state, request template reload");
+ 					return new CopyCmdAnswer("Template host in vSphere is not in connected state, request template reload");
+ 				}
+ 
+ 				ManagedObjectReference morPool = hyperHost.getHyperHostOwnerResourcePool();
+ 				ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
+ 				//createVMLinkedClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
+ 				if (!_fullCloneFlag) {
+ 					createVMLinkedClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
+ 				} else {
+ 					createVMFullClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
+ 				}
+ 
+ 				vmMo = new ClusterMO(context, morCluster).findVmOnHyperHost(vmdkName);
+ 				assert (vmMo != null);
+ 
+ 				s_logger.info("detach disks from volume-wrapper VM " + vmdkName);
+ 				vmMo.detachAllDisks();
+ 
+ 				s_logger.info("destroy volume-wrapper VM " + vmdkName);
+ 				vmMo.destroy();
+ 
+ 				String srcFile = String.format("[%s] %s/", dsMo.getName(), vmdkName);
+ 				dsMo.deleteFile(srcFile, dcMo.getMor(), true);
+ 				VolumeObjectTO newVol = new VolumeObjectTO();
+ 				newVol.setPath(vmdkName);
+ 				return new CopyCmdAnswer(newVol);
+ 			}
+ 		} catch (Throwable e) {
+ 			if (e instanceof RemoteException) {
+ 				s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
 -				this.hostService.invalidateServiceContext(null);
++				hostService.invalidateServiceContext(null);
+ 			}
+ 
+ 			String msg = "CreateCommand failed due to " + VmwareHelper.getExceptionMessage(e);
+ 			s_logger.error(msg, e);
+ 			return new CopyCmdAnswer(e.toString());
+ 		}
+ 	}
+ 	
+ 
+ 	@Override
+ 	public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd) {
+ 		// TODO Auto-generated method stub
+ 		return null;
+ 	}
+ 
+ 	@Override
+ 	public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd) {
+ 		// TODO Auto-generated method stub
+ 		return null;
+ 	}
+ 	
+ 	private void postCreatePrivateTemplate(String installFullPath, long templateId,
+ 	        String templateName, long size, long virtualSize) throws Exception {
+ 
+ 	        // TODO a bit ugly here
+ 	        BufferedWriter out = null;
+ 	        try {
+ 	            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(installFullPath + "/template.properties")));
+ 	            out.write("filename=" + templateName + ".ova");
+ 	            out.newLine();
+ 	            out.write("description=");
+ 	            out.newLine();
+ 	            out.write("checksum=");
+ 	            out.newLine();
+ 	            out.write("hvm=false");
+ 	            out.newLine();
+ 	            out.write("size=" + size);
+ 	            out.newLine();
+ 	            out.write("ova=true");
+ 	            out.newLine();
+ 	            out.write("id=" + templateId);
+ 	            out.newLine();
+ 	            out.write("public=false");
+ 	            out.newLine();
+ 	            out.write("ova.filename=" + templateName + ".ova");
+ 	            out.newLine();
+ 	            out.write("uniquename=" + templateName);
+ 	            out.newLine();
+ 	            out.write("ova.virtualsize=" + virtualSize);
+ 	            out.newLine();
+ 	            out.write("virtualsize=" + virtualSize);
+ 	            out.newLine();
+ 	            out.write("ova.size=" + size);
+ 	            out.newLine();
+ 	        } finally {
+ 	            if(out != null)
+ 	                out.close();
+ 	        }
+ 	    }
+ 
+ 	private Ternary<String, Long, Long> createTemplateFromVolume(VirtualMachineMO vmMo, String installPath, long templateId, String templateUniqueName,
+ 	        String secStorageUrl, String volumePath, String workerVmName) throws Exception {
+ 
+ 	        String secondaryMountPoint = mountService.getMountPoint(secStorageUrl);
+ 	        String installFullPath = secondaryMountPoint + "/" + installPath;
+ 	        synchronized(installPath.intern()) {
+ 	            Script command = new Script(false, "mkdir", _timeout, s_logger);
+ 	            command.add("-p");
+ 	            command.add(installFullPath);
+ 
+ 	            String result = command.execute();
+ 	            if(result != null) {
+ 	                String msg = "unable to prepare template directory: "
+ 	                    + installPath + ", storage: " + secStorageUrl + ", error msg: " + result;
+ 	                s_logger.error(msg);
+ 	                throw new Exception(msg);
+ 	            }
+ 	        }
+ 
+ 	        VirtualMachineMO clonedVm = null;
+ 	        try {
+ 	            Pair<VirtualDisk, String> volumeDeviceInfo = vmMo.getDiskDevice(volumePath, false);
+ 	            if(volumeDeviceInfo == null) {
+ 	                String msg = "Unable to find related disk device for volume. volume path: " + volumePath;
+ 	                s_logger.error(msg);
+ 	                throw new Exception(msg);
+ 	            }
+ 
+ 	            if(!vmMo.createSnapshot(templateUniqueName, "Temporary snapshot for template creation", false, false)) {
+ 	                String msg = "Unable to take snapshot for creating template from volume. volume path: " + volumePath;
+ 	                s_logger.error(msg);
+ 	                throw new Exception(msg);
+ 	            }
+ 
+ 	            // 4 MB is the minimum requirement for VM memory in VMware
+ 	            vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(),
+ 	                VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()));
+ 	            clonedVm = vmMo.getRunningHost().findVmOnHyperHost(workerVmName);
+ 	            if(clonedVm == null) {
+ 	                String msg = "Unable to create dummy VM to export volume. volume path: " + volumePath;
+ 	                s_logger.error(msg);
+ 	                throw new Exception(msg);
+ 	            }
+ 
+ 	            clonedVm.exportVm(secondaryMountPoint + "/" + installPath, templateUniqueName, true, false);
+ 
+ 	            long physicalSize = new File(installFullPath + "/" + templateUniqueName + ".ova").length();
+ 	            VmdkProcessor processor = new VmdkProcessor();
+ 	            Map<String, Object> params = new HashMap<String, Object>();
+ 	            params.put(StorageLayer.InstanceConfigKey, _storage);
+ 	            processor.configure("VMDK Processor", params);
+ 	            long virtualSize = processor.getTemplateVirtualSize(installFullPath, templateUniqueName);
+ 
+ 	            postCreatePrivateTemplate(installFullPath, templateId, templateUniqueName, physicalSize, virtualSize);
+ 	            return new Ternary<String, Long, Long>(installPath + "/" + templateUniqueName + ".ova", physicalSize, virtualSize);
+ 
+ 	        } finally {
+ 	            if(clonedVm != null) {
+ 	                clonedVm.detachAllDisks();
+ 	                clonedVm.destroy();
+ 	            }
+ 
+ 	            vmMo.removeSnapshot(templateUniqueName, false);
+ 	        }
+ 	    }
+ 
+ 	@Override
+ 	public Answer createTemplateFromVolume(CopyCommand cmd) {
+ 		VolumeObjectTO volume = (VolumeObjectTO)cmd.getSrcTO();
+ 		PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
+ 		TemplateObjectTO template = (TemplateObjectTO)cmd.getDestTO();
+ 		DataStoreTO imageStore = template.getDataStore();
+ 		
+ 		if (!(imageStore instanceof NfsTO)) {
+ 			return new CopyCmdAnswer("unsupported protocol");
+ 		}
+ 		NfsTO nfsImageStore = (NfsTO)imageStore;
+ 		String secondaryStoragePoolURL = nfsImageStore.getUrl();
+ 		String volumePath = volume.getPath();
+ 
+ 		String details = null;
+ 
+ 		VmwareContext context = hostService.getServiceContext(cmd);
+ 		try {
+ 			VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
+ 
+ 			VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(volume.getVmName());
+ 			if (vmMo == null) {
+ 				if(s_logger.isDebugEnabled())
+ 					s_logger.debug("Unable to find the owner VM for CreatePrivateTemplateFromVolumeCommand on host " + hyperHost.getHyperHostName() + ", try within datacenter");
+ 				vmMo = hyperHost.findVmOnPeerHyperHost(volume.getVmName());
+ 
+ 				if(vmMo == null) {
+ 					String msg = "Unable to find the owner VM for volume operation. vm: " + volume.getVmName();
+ 					s_logger.error(msg);
+ 					throw new Exception(msg);
+ 				}
+ 			}
+ 
+ 			Ternary<String, Long, Long> result = createTemplateFromVolume(vmMo,
+ 					template.getPath(), template.getId(), template.getName(),
+ 					secondaryStoragePoolURL, volumePath,
+ 					hostService.getWorkerName(context, cmd, 0));
+ 
+ 			TemplateObjectTO newTemplate = new TemplateObjectTO();
+ 			newTemplate.setPath(template.getName());
+ 			newTemplate.setFormat(ImageFormat.OVA);
+ 			newTemplate.setSize(result.third());
+ 			return new CopyCmdAnswer(newTemplate);
+ 
+ 		} catch (Throwable e) {
+ 			if (e instanceof RemoteException) {
+ 				hostService.invalidateServiceContext(context);
+ 			}
+ 
+ 			s_logger.error("Unexpecpted exception ", e);
+ 
+ 			details = "CreatePrivateTemplateFromVolumeCommand exception: " + StringUtils.getExceptionStackInfo(e);
+ 			return new CopyCmdAnswer(details);
+ 		}
+ 	}
+ 	
+ 	private void exportVolumeToSecondaryStroage(VirtualMachineMO vmMo, String volumePath,
+ 	        String secStorageUrl, String secStorageDir, String exportName,
+ 	        String workerVmName) throws Exception {
+ 
+ 	        String secondaryMountPoint = mountService.getMountPoint(secStorageUrl);
+ 	        String exportPath =  secondaryMountPoint + "/" + secStorageDir + "/" + exportName;
+ 	        
+ 	        synchronized(exportPath.intern()) {
+ 	            if(!new File(exportPath).exists()) {
+ 	                Script command = new Script(false, "mkdir", _timeout, s_logger);
+ 	                command.add("-p");
+ 	                command.add(exportPath);
+ 	                if(command.execute() != null)
+ 	                    throw new Exception("unable to prepare snapshot backup directory");
+ 	            }
+ 	        }
+ 
+ 	        VirtualMachineMO clonedVm = null;
+ 	        try {
+ 
+ 	            Pair<VirtualDisk, String> volumeDeviceInfo = vmMo.getDiskDevice(volumePath, false);
+ 	            if(volumeDeviceInfo == null) {
+ 	                String msg = "Unable to find related disk device for volume. volume path: " + volumePath;
+ 	                s_logger.error(msg);
+ 	                throw new Exception(msg);
+ 	            }
+ 
+ 	            // 4 MB is the minimum requirement for VM memory in VMware
+ 	            vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(),
+ 	                VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()));
+ 	            clonedVm = vmMo.getRunningHost().findVmOnHyperHost(workerVmName);
+ 	            if(clonedVm == null) {
+ 	                String msg = "Unable to create dummy VM to export volume. volume path: " + volumePath;
+ 	                s_logger.error(msg);
+ 	                throw new Exception(msg);
+ 	            }
+ 
+ 	            clonedVm.exportVm(exportPath, exportName, true, true);
+ 	        } finally {
+ 	            if(clonedVm != null) {
+ 	                clonedVm.detachAllDisks();
+ 	                clonedVm.destroy();
+ 	            }
+ 	        }
+ 	    }
+ 
+ 	
+ 	private String backupSnapshotToSecondaryStorage(VirtualMachineMO vmMo, String installPath,
+ 	        String volumePath, String snapshotUuid, String secStorageUrl,
+ 	        String prevSnapshotUuid, String prevBackupUuid, String workerVmName) throws Exception {
+ 
+ 	        String backupUuid = UUID.randomUUID().toString();
+ 	        exportVolumeToSecondaryStroage(vmMo, volumePath, secStorageUrl,
+ 	        		installPath, backupUuid, workerVmName);
+ 	        return backupUuid + "/" + backupUuid;
+ 	    }
+ 	@Override
+ 	public Answer backupSnasphot(CopyCommand cmd) {
+ 		SnapshotObjectTO srcSnapshot = (SnapshotObjectTO)cmd.getSrcTO();
+ 		PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)srcSnapshot.getDataStore();
+ 		SnapshotObjectTO destSnapshot = (SnapshotObjectTO)cmd.getDestTO();
+ 		DataStoreTO destStore = destSnapshot.getDataStore();
+ 		if (!(destStore instanceof NfsTO)) {
+ 			return new CopyCmdAnswer("unsupported protocol");
+ 		}
+ 
+ 		NfsTO destNfsStore = (NfsTO)destStore;
+ 
+ 
+ 		String secondaryStorageUrl = destNfsStore.getUrl();
+ 		String snapshotUuid = srcSnapshot.getPath();
+ 		String prevSnapshotUuid = srcSnapshot.getParentSnapshotPath();
+ 		String prevBackupUuid = destSnapshot.getParentSnapshotPath();
+ 		VirtualMachineMO workerVm=null;
+ 		String workerVMName = null;
+ 		String volumePath = srcSnapshot.getVolume().getPath();
+ 		ManagedObjectReference morDs = null;
+ 		DatastoreMO dsMo=null;
+ 
+ 		// By default assume failure
+ 		String details = null;
+ 		boolean success = false;
+ 		String snapshotBackupUuid = null;
+ 
+ 		VmwareContext context = hostService.getServiceContext(cmd);
+ 		VirtualMachineMO vmMo = null;
+ 		String vmName = srcSnapshot.getVmName();
+ 		try {
+ 			VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
+ 			morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid());
+ 
+ 			try {
+ 				vmMo = hyperHost.findVmOnHyperHost(vmName);
+ 				if (vmMo == null) {
+ 					if(s_logger.isDebugEnabled())
+ 						s_logger.debug("Unable to find owner VM for BackupSnapshotCommand on host " + hyperHost.getHyperHostName() + ", will try within datacenter");
+ 
+ 					vmMo = hyperHost.findVmOnPeerHyperHost(vmName);
+ 					if(vmMo == null) {
+ 						dsMo = new DatastoreMO(hyperHost.getContext(), morDs);
+ 
+ 						workerVMName = hostService.getWorkerName(context, cmd, 0);
+ 
+ 						// attach a volume to dummay wrapper VM for taking snapshot and exporting the VM for backup
+ 						if (!hyperHost.createBlankVm(workerVMName, 1, 512, 0, false, 4, 0, VirtualMachineGuestOsIdentifier.OTHER_GUEST.value(), morDs, false)) {
+ 							String msg = "Unable to create worker VM to execute BackupSnapshotCommand";
+ 							s_logger.error(msg);
+ 							throw new Exception(msg);
+ 						}
+ 						vmMo = hyperHost.findVmOnHyperHost(workerVMName);
+ 						if (vmMo == null) {
+ 							throw new Exception("Failed to find the newly create or relocated VM. vmName: " + workerVMName);
+ 						}
+ 						workerVm = vmMo;
+ 
+ 						// attach volume to worker VM
+ 						String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumePath);
+ 						vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs);
+ 					}
+ 				}
+ 
+ 				if (!vmMo.createSnapshot(snapshotUuid, "Snapshot taken for " + srcSnapshot.getName(), false, false)) {
+ 					throw new Exception("Failed to take snapshot " + srcSnapshot.getName() + " on vm: " + vmName);
+ 				}
+ 
+ 				snapshotBackupUuid = backupSnapshotToSecondaryStorage(vmMo, destSnapshot.getPath(), srcSnapshot.getVolume().getPath(), snapshotUuid, secondaryStorageUrl, prevSnapshotUuid, prevBackupUuid,
+ 						hostService.getWorkerName(context, cmd, 1));
+ 
+ 				success = (snapshotBackupUuid != null);
+ 				if (success) {
+ 					details = "Successfully backedUp the snapshotUuid: " + snapshotUuid + " to secondary storage.";
+ 					return new CopyCmdAnswer(details);
+ 				} else {
+ 					SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
+ 					newSnapshot.setPath(snapshotBackupUuid);
+ 					return new CopyCmdAnswer(newSnapshot);
+ 				}
+ 			} finally {
+ 				if(vmMo != null){
+ 					ManagedObjectReference snapshotMor = vmMo.getSnapshotMor(snapshotUuid);
+ 					if (snapshotMor != null){
+ 						vmMo.removeSnapshot(snapshotUuid, false);
+ 					}
+ 				}
+ 
+ 				try {
+ 					if (workerVm != null) {
+ 						// detach volume and destroy worker vm
+ 						workerVm.detachAllDisks();
+ 						workerVm.destroy();
+ 					}
+ 				} catch (Throwable e) {
+ 					s_logger.warn("Failed to destroy worker VM: " + workerVMName);
+ 				}
+ 			}
+ 		} catch (Throwable e) {
+ 			if (e instanceof RemoteException) {
+ 				hostService.invalidateServiceContext(context);
+ 			}
+ 
+ 			s_logger.error("Unexpecpted exception ", e);
+ 
+ 			details = "BackupSnapshotCommand exception: " + StringUtils.getExceptionStackInfo(e);
+ 			return new CopyCmdAnswer(details);
+ 		}
+ 	}
+ 
+ 	@Override
+ 	public Answer attachIso(AttachCommand cmd) {
+ 		return this.attachIso(cmd.getDisk(), true, cmd.getVmName());
+ 	}
+ 
+ 	@Override
+ 	public Answer attachVolume(AttachCommand cmd) {
+ 		return this.attachVolume(cmd, cmd.getDisk(), true, cmd.getVmName());
+ 	}
+ 	
+ 	private Answer attachVolume(Command cmd, DiskTO disk, boolean isAttach, String vmName) {
+ 
+ 		VolumeObjectTO volumeTO = (VolumeObjectTO)disk.getData();
+ 		PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
+ 		try {
 -			VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(this.hostService.getServiceContext(null), null);
++			VmwareHypervisorHost hyperHost = hostService.getHyperHost(hostService.getServiceContext(null), null);
+ 			VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
+ 			if (vmMo == null) {
+ 				String msg = "Unable to find the VM to execute AttachVolumeCommand, vmName: " + vmName;
+ 				s_logger.error(msg);
+ 				throw new Exception(msg);
+ 			}
+ 
+ 			ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid());
+ 			if (morDs == null) {
+ 				String msg = "Unable to find the mounted datastore to execute AttachVolumeCommand, vmName: " + vmName;
+ 				s_logger.error(msg);
+ 				throw new Exception(msg);
+ 			}
+ 
 -			DatastoreMO dsMo = new DatastoreMO(this.hostService.getServiceContext(null), morDs);
++			DatastoreMO dsMo = new DatastoreMO(hostService.getServiceContext(null), morDs);
+ 			String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeTO.getPath());
+ 
+ 			AttachAnswer answer = new AttachAnswer(disk);
+ 			if (isAttach) {
+ 				vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs);
+ 			} else {
+ 				vmMo.removeAllSnapshots();
+ 				vmMo.detachDisk(datastoreVolumePath, false);
+ 			}
+ 
+ 			return answer;
+ 		} catch (Throwable e) {
+ 			if (e instanceof RemoteException) {
+ 				s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
 -				this.hostService.invalidateServiceContext(null);
++				hostService.invalidateServiceContext(null);
+ 			}
+ 
+ 			String msg = "AttachVolumeCommand failed due to " + VmwareHelper.getExceptionMessage(e);
+ 			s_logger.error(msg, e);
+ 			return new AttachAnswer(msg);
+ 		}
+ 	}
+ 	
+ 	  private static String getSecondaryDatastoreUUID(String storeUrl) {
+ 	        return UUID.nameUUIDFromBytes(storeUrl.getBytes()).toString();
+ 	    }
+ 
+ 	public synchronized ManagedObjectReference prepareSecondaryDatastoreOnHost(String storeUrl) throws Exception {
+         String storeName = getSecondaryDatastoreUUID(storeUrl);
+         URI uri = new URI(storeUrl);
+ 
 -        VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(this.hostService.getServiceContext(null), null);
++        VmwareHypervisorHost hyperHost = hostService.getHyperHost(hostService.getServiceContext(null), null);
+         ManagedObjectReference morDatastore = hyperHost.mountDatastore(false, uri.getHost(), 0, uri.getPath(), storeName.replace("-", ""));
+ 
+         if (morDatastore == null)
+             throw new Exception("Unable to mount secondary storage on host. storeUrl: " + storeUrl);
+ 
+         return morDatastore;
+     }
+ 	private Answer attachIso(DiskTO disk, boolean isAttach, String vmName) {
+ 		
+ 
+ 	        try {
 -	            VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(this.hostService.getServiceContext(null), null);
++	            VmwareHypervisorHost hyperHost = hostService.getHyperHost(hostService.getServiceContext(null), null);
+ 	            VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
+ 	            if (vmMo == null) {
+ 	                String msg = "Unable to find VM in vSphere to execute AttachIsoCommand, vmName: " + vmName;
+ 	                s_logger.error(msg);
+ 	                throw new Exception(msg);
+ 	            }
+ 	            TemplateObjectTO iso = (TemplateObjectTO)disk.getData();
+ 	            NfsTO nfsImageStore = (NfsTO)iso.getDataStore();
+ 	            String storeUrl = nfsImageStore.getUrl();
+ 	            if (storeUrl == null) {
+ 	                if (!iso.getName().equalsIgnoreCase("vmware-tools.iso")) {
+ 	                    String msg = "ISO store root url is not found in AttachIsoCommand";
+ 	                    s_logger.error(msg);
+ 	                    throw new Exception(msg);
+ 	                } else {
+ 	                    if (isAttach) {
+ 	                        vmMo.mountToolsInstaller();
+ 	                    } else {
+ 	                        try{
+ 	                            vmMo.unmountToolsInstaller();
+ 	                        }catch(Throwable e){
+ 	                            vmMo.detachIso(null);
+ 	                        }
+ 	                    }
+ 
+ 	                    return new AttachAnswer(disk);
+ 	                }
+ 	            }
+ 
+ 	            ManagedObjectReference morSecondaryDs = prepareSecondaryDatastoreOnHost(storeUrl);
+ 	            String isoPath = nfsImageStore.getUrl() + File.separator + iso.getPath();
+ 	            if (!isoPath.startsWith(storeUrl)) {
+ 	                assert (false);
+ 	                String msg = "ISO path does not start with the secondary storage root";
+ 	                s_logger.error(msg);
+ 	                throw new Exception(msg);
+ 	            }
+ 
+ 	            int isoNameStartPos = isoPath.lastIndexOf('/');
+ 	            String isoFileName = isoPath.substring(isoNameStartPos + 1);
+ 	            String isoStorePathFromRoot = isoPath.substring(storeUrl.length(), isoNameStartPos);
+ 
+ 	            // TODO, check if iso is already attached, or if there is a previous
+ 	            // attachment
 -	            DatastoreMO secondaryDsMo = new DatastoreMO(this.hostService.getServiceContext(null), morSecondaryDs);
++	            DatastoreMO secondaryDsMo = new DatastoreMO(hostService.getServiceContext(null), morSecondaryDs);
+ 	            String storeName = secondaryDsMo.getName();
+ 	            String isoDatastorePath = String.format("[%s] %s%s", storeName, isoStorePathFromRoot, isoFileName);
+ 
+ 	            if (isAttach) {
+ 	                vmMo.attachIso(isoDatastorePath, morSecondaryDs, true, false);
+ 	            } else {
+ 	                vmMo.detachIso(isoDatastorePath);
+ 	            }
+ 
+ 	            return new AttachAnswer(disk);
+ 	        } catch (Throwable e) {
+ 	            if (e instanceof RemoteException) {
+ 	                s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
 -	                this.hostService.invalidateServiceContext(null);
++	                hostService.invalidateServiceContext(null);
+ 	            }
+ 
+ 	            if(isAttach) {
+ 	                String msg = "AttachIsoCommand(attach) failed due to " + VmwareHelper.getExceptionMessage(e);
+ 	                s_logger.error(msg, e);
+ 	                return new AttachAnswer(msg);
+ 	            } else {
+ 	                String msg = "AttachIsoCommand(detach) failed due to " + VmwareHelper.getExceptionMessage(e);
+ 	                s_logger.warn(msg, e);
+ 	                return new AttachAnswer(msg);
+ 	            }
+ 	        }
+ 	}
+ 	@Override
+ 	public Answer dettachIso(DettachCommand cmd) {
+ 		return this.attachIso(cmd.getDisk(), false, cmd.getVmName());
+ 	}
+ 
+ 	@Override
+ 	public Answer dettachVolume(DettachCommand cmd) {
+ 		return this.attachVolume(cmd, cmd.getDisk(), false, cmd.getVmName());
+ 	}
+ 
+ 	protected VirtualMachineMO prepareVolumeHostDummyVm(VmwareHypervisorHost hyperHost, DatastoreMO dsMo, String vmName) throws Exception {
+         assert (hyperHost != null);
+ 
+         VirtualMachineMO vmMo = null;
+         VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
+         vmConfig.setName(vmName);
+         vmConfig.setMemoryMB((long) 4); // vmware request minimum of 4 MB
+         vmConfig.setNumCPUs(1);
+         vmConfig.setGuestId(VirtualMachineGuestOsIdentifier.OTHER_GUEST.value());
+         VirtualMachineFileInfo fileInfo = new VirtualMachineFileInfo();
+         fileInfo.setVmPathName(String.format("[%s]", dsMo.getName()));
+         vmConfig.setFiles(fileInfo);
+ 
+         // Scsi controller
+         VirtualLsiLogicController scsiController = new VirtualLsiLogicController();
+         scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
+         scsiController.setBusNumber(0);
+         scsiController.setKey(1);
+         VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
+         scsiControllerSpec.setDevice(scsiController);
+         scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
+ 
+         vmConfig.getDeviceChange().add(scsiControllerSpec );
+         hyperHost.createVm(vmConfig);
+         vmMo = hyperHost.findVmOnHyperHost(vmName);
+         return vmMo;
+     }
+ 	@Override
+ 	public Answer createVolume(CreateObjectCommand cmd) {
+ 
+ 		VolumeObjectTO volume = (VolumeObjectTO)cmd.getData();
+ 		PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
+        
+ 		try {
 -			VmwareContext context = this.hostService.getServiceContext(null);
 -			VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(context, null);
++			VmwareContext context = hostService.getServiceContext(null);
++			VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, null);
+ 			DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
+ 
+ 			ManagedObjectReference morDatastore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid());
+ 			if (morDatastore == null)
+ 				throw new Exception("Unable to find datastore in vSphere");
+ 
+ 			DatastoreMO dsMo = new DatastoreMO(context, morDatastore);
+ 			// create data volume
+ 			VirtualMachineMO vmMo = null;
+ 			String volumeUuid = UUID.randomUUID().toString().replace("-", "");
+ 			String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeUuid);
 -			String dummyVmName = this.hostService.getWorkerName(context, cmd, 0);
++			String dummyVmName = hostService.getWorkerName(context, cmd, 0);
+ 			try {
+ 				vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName);
+ 				if (vmMo == null) {
+ 					throw new Exception("Unable to create a dummy VM for volume creation");
+ 				}
+ 
+ 				synchronized (this) {
+ 					// s_logger.info("Delete file if exists in datastore to clear the way for creating the volume. file: " + volumeDatastorePath);
+ 					VmwareHelper.deleteVolumeVmdkFiles(dsMo, volumeUuid.toString(), dcMo);
+ 
+ 					vmMo.createDisk(volumeDatastorePath, (int) (volume.getSize() / (1024L * 1024L)), morDatastore, vmMo.getScsiDeviceControllerKey());
+ 					vmMo.detachDisk(volumeDatastorePath, false);
+ 				}
+ 
+ 				VolumeObjectTO newVol = new VolumeObjectTO();
+ 				newVol.setPath(volumeUuid);
+ 				newVol.setSize(volume.getSize() / (1024L * 1024L));
+ 				return new CreateObjectAnswer(newVol);
+ 			} finally {
+ 				s_logger.info("Destroy dummy VM after volume creation");
+ 				vmMo.detachAllDisks();
+ 				vmMo.destroy();
+ 			}
+ 
+ 		} catch (Throwable e) {
+ 			if (e instanceof RemoteException) {
+ 				s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
 -				this.hostService.invalidateServiceContext(null);
++				hostService.invalidateServiceContext(null);
+ 			}
+ 
+ 			String msg = "CreateCommand failed due to " + VmwareHelper.getExceptionMessage(e);
+ 			s_logger.error(msg, e);
+ 			return new CreateObjectAnswer(e.toString());
+ 		}
+ 	}
+ 
+ 	@Override
+ 	public Answer createSnapshot(CreateObjectCommand cmd) {
+ 		// snapshot operation (create or destroy) is handled inside BackupSnapshotCommand(), we just fake
+ 		// a success return here
+ 		String snapshotUUID = UUID.randomUUID().toString();
+ 		SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
+ 		newSnapshot.setPath(snapshotUUID);
+ 		return new CreateObjectAnswer(newSnapshot);
+ 	}
+ 
+ 	@Override
+ 	public Answer deleteVolume(DeleteCommand cmd) {
+ 		if (s_logger.isInfoEnabled()) {
+ 			s_logger.info("Executing resource DestroyCommand: " + _gson.toJson(cmd));
+ 		}
+ 
+ 		/*
+ 		 * DestroyCommand content example
+ 		 *
+ 		 * {"volume": {"id":5,"name":"Volume1", "mountPoint":"/export/home/kelven/vmware-test/primary",
+ 		 * "path":"6bb8762f-c34c-453c-8e03-26cc246ceec4", "size":0,"type":"DATADISK","resourceType":
+ 		 * "STORAGE_POOL","storagePoolType":"NetworkFilesystem", "poolId":0,"deviceId":0 } }
+ 		 *
+ 		 * {"volume": {"id":1, "name":"i-2-1-KY-ROOT", "mountPoint":"/export/home/kelven/vmware-test/primary",
+ 		 * "path":"i-2-1-KY-ROOT","size":0,"type":"ROOT", "resourceType":"STORAGE_POOL", "storagePoolType":"NetworkFilesystem",
+ 		 * "poolId":0,"deviceId":0 } }
+ 		 */
+ 
+ 		try {
 -			VmwareContext context = this.hostService.getServiceContext(null);
 -			VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(context, null);
++			VmwareContext context = hostService.getServiceContext(null);
++			VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, null);
+ 			VolumeObjectTO vol = (VolumeObjectTO)cmd.getData();
+ 			PrimaryDataStoreTO store = (PrimaryDataStoreTO)vol.getDataStore();
+ 
+ 			ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, store.getUuid());
+ 			if (morDs == null) {
+ 				String msg = "Unable to find datastore based on volume mount point " + store.getPath();
+ 				s_logger.error(msg);
+ 				throw new Exception(msg);
+ 			}
+ 
+ 			DatastoreMO dsMo = new DatastoreMO(context, morDs);
+ 
+ 			ManagedObjectReference morDc = hyperHost.getHyperHostDatacenter();
+ 			ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
+ 			ClusterMO clusterMo = new ClusterMO(context, morCluster);
+ 
+ 			if (vol.getVolumeType() == Volume.Type.ROOT) {
+ 				String vmName = vol.getVmName();
+ 				if (vmName != null) {
+ 					VirtualMachineMO vmMo = clusterMo.findVmOnHyperHost(vmName);
+ 					if (vmMo != null) {
+ 						if (s_logger.isInfoEnabled()) {
+ 							s_logger.info("Destroy root volume and VM itself. vmName " + vmName);
+ 						}
+ 
+ 						HostMO hostMo = vmMo.getRunningHost();
+ 						List<NetworkDetails> networks = vmMo.getNetworksWithDetails();
+ 
+ 						// tear down all devices first before we destroy the VM to avoid accidently delete disk backing files
 -						if (this.resource.getVmState(vmMo) != State.Stopped)
++                        if (resource.getVmState(vmMo) != PowerState.PowerOff)
+ 							vmMo.safePowerOff(_shutdown_waitMs);
+ 						vmMo.tearDownDevices(new Class<?>[] { VirtualDisk.class, VirtualEthernetCard.class });
+ 						vmMo.destroy();
+ 
+ 						for (NetworkDetails netDetails : networks) {
+ 							if (netDetails.getGCTag() != null && netDetails.getGCTag().equalsIgnoreCase("true")) {
+ 								if (netDetails.getVMMorsOnNetwork() == null || netDetails.getVMMorsOnNetwork().length == 1) {
 -									this.resource.cleanupNetwork(hostMo, netDetails);
++									resource.cleanupNetwork(hostMo, netDetails);
+ 								}
+ 							}
+ 						}
+ 					}
+ 
+ 					if (s_logger.isInfoEnabled())
+ 						s_logger.info("Destroy volume by original name: " + vol.getPath() + ".vmdk");
+ 					dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true);
+ 
+ 					// root volume may be created via linked-clone, delete the delta disk as well
+ 					if (_fullCloneFlag) {
+ 						if (s_logger.isInfoEnabled()) {
+ 							s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk");
+ 						}
+ 						dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true);
+ 					} else {
+ 						if (s_logger.isInfoEnabled()) {
+ 							s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-delta.vmdk");
+ 						}
+ 						dsMo.deleteFile(vol.getPath() + "-delta.vmdk", morDc, true);
+ 					}
+ 					return new Answer(cmd, true, "Success");
+ 				}
+ 
+ 				if (s_logger.isInfoEnabled()) {
+ 					s_logger.info("Destroy root volume directly from datastore");
+ 				}
+ 			} else {
+ 				// evitTemplate will be converted into DestroyCommand, test if we are running in this case
+ 				VirtualMachineMO vmMo = clusterMo.findVmOnHyperHost(vol.getPath());
+ 				if (vmMo != null) {
+ 					if (s_logger.isInfoEnabled())
+ 						s_logger.info("Destroy template volume " + vol.getPath());
+ 
+ 					vmMo.destroy();
+ 					return new Answer(cmd, true, "Success");
+ 				}
+ 			}
+ 
+ 			String chainInfo = vol.getChainInfo();
+ 			if (chainInfo != null && !chainInfo.isEmpty()) {
+ 				s_logger.info("Destroy volume by chain info: " + chainInfo);
+ 				String[] diskChain = _gson.fromJson(chainInfo, String[].class);
+ 
+ 				if (diskChain != null && diskChain.length > 0) {
+ 					for (String backingName : diskChain) {
+ 						if (s_logger.isInfoEnabled()) {
+ 							s_logger.info("Delete volume backing file: " + backingName);
+ 						}
+ 						dsMo.deleteFile(backingName, morDc, true);
+ 					}
+ 				} else {
+ 					if (s_logger.isInfoEnabled()) {
+ 						s_logger.info("Empty disk chain info, fall back to try to delete by original backing file name");
+ 					}
+ 					dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true);
+ 
+ 					if (s_logger.isInfoEnabled()) {
+ 						s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk");
+ 					}
+ 					dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true);
+ 				}
+ 			} else {
+ 				if (s_logger.isInfoEnabled()) {
+ 					s_logger.info("Destroy volume by original name: " + vol.getPath() + ".vmdk");
+ 				}
+ 				dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true);
+ 
+ 				if (s_logger.isInfoEnabled()) {
+ 					s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk");
+ 				}
+ 				dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true);
+ 			}
+ 
+ 			return new Answer(cmd, true, "Success");
+ 		} catch (Throwable e) {
+ 			if (e instanceof RemoteException) {
+ 				s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
 -				this.hostService.invalidateServiceContext(null);
++				hostService.invalidateServiceContext(null);
+ 			}
+ 
+ 			String msg = "DestroyCommand failed due to " + VmwareHelper.getExceptionMessage(e);
+ 			s_logger.error(msg, e);
+ 			return new Answer(cmd, false, msg);
+ 		}
+ 	}
+ 	
+ 	 private Long restoreVolumeFromSecStorage(VmwareHypervisorHost hyperHost, DatastoreMO primaryDsMo, String newVolumeName,
+ 		        String secStorageUrl, String secStorageDir, String backupName) throws Exception {
+ 
+ 		        String secondaryMountPoint = mountService.getMountPoint(secStorageUrl);
+ 		        String srcOVAFileName = secondaryMountPoint + "/" +  secStorageDir + "/"
+ 		            + backupName + "." + ImageFormat.OVA.getFileExtension();
+ 		        String snapshotDir = "";
+ 		        if (backupName.contains("/")){
+ 		            snapshotDir = backupName.split("/")[0];
+ 		        }
+ 
+ 		        File ovafile = new File(srcOVAFileName);
+ 		        String srcOVFFileName = secondaryMountPoint + "/" +  secStorageDir + "/"
+ 		                + backupName + ".ovf";
+ 		        File ovfFile = new File(srcOVFFileName);
+ 		        // String srcFileName = getOVFFilePath(srcOVAFileName);
+ 		        if (!ovfFile.exists()) {
+ 		            srcOVFFileName = getOVFFilePath(srcOVAFileName);
+ 		            if(srcOVFFileName == null && ovafile.exists() ) {  // volss: ova file exists; o/w can't do tar
+ 		                Script command = new Script("tar", 0, s_logger);
+ 		                command.add("--no-same-owner");
+ 		                command.add("-xf", srcOVAFileName);
+ 		                command.setWorkDir(secondaryMountPoint + "/" +  secStorageDir + "/" + snapshotDir);
+ 		                s_logger.info("Executing command: " + command.toString());
+ 		                String result = command.execute();
+ 		                if(result != null) {
+ 		                        String msg = "Unable to unpack snapshot OVA file at: " + srcOVAFileName;
+ 		                        s_logger.error(msg);
+ 		                        throw new Exception(msg);
+ 		                }
+ 		            } else {
+ 		               String msg = "Unable to find snapshot OVA file at: " + srcOVAFileName;
+ 		               s_logger.error(msg);
+ 		               throw new Exception(msg);
+ 		           }
+ 
+ 		           srcOVFFileName = getOVFFilePath(srcOVAFileName);
+ 		        }
+ 		        if(srcOVFFileName == null) {
+ 		            String msg = "Unable to locate OVF file in template package directory: " + srcOVAFileName;
+ 		            s_logger.error(msg);
+ 		            throw new Exception(msg);
+ 		        }
+ 
+ 		        VirtualMachineMO clonedVm = null;
+ 		        try {
+ 		            hyperHost.importVmFromOVF(srcOVFFileName, newVolumeName, primaryDsMo, "thin");
+ 		            clonedVm = hyperHost.findVmOnHyperHost(newVolumeName);
+ 		            if(clonedVm == null)
+ 		                throw new Exception("Unable to create container VM for volume creation");
+ 
+ 		            clonedVm.moveAllVmDiskFiles(primaryDsMo, "", false);
+ 		            clonedVm.detachAllDisks();
+ 		            return _storage.getSize(srcOVFFileName);
+ 		        } finally {
+ 		            if(clonedVm != null) {
+ 		                clonedVm.detachAllDisks();
+ 		                clonedVm.destroy();
+ 		            }
+ 		        }
+ 		    }
+ 
+ 	@Override
+ 	public Answer createVolumeFromSnapshot(CopyCommand cmd) {
+ 		DataTO srcData = cmd.getSrcTO();
+ 		SnapshotObjectTO snapshot = (SnapshotObjectTO)srcData;
+ 		DataTO destData = cmd.getDestTO();
+ 		PrimaryDataStoreTO pool = (PrimaryDataStoreTO)destData.getDataStore();
+ 		DataStoreTO imageStore = srcData.getDataStore();
+ 
+ 
+ 		if (!(imageStore instanceof NfsTO)) {
+ 			return new CopyCmdAnswer("unsupported protocol");
+ 		}
+ 
+ 		NfsTO nfsImageStore = (NfsTO)imageStore;
+ 		String primaryStorageNameLabel = pool.getUuid();
+ 	
+         String secondaryStorageUrl = nfsImageStore.getUrl();
+ 		String backedUpSnapshotUuid = snapshot.getPath();
+ 		int index = backedUpSnapshotUuid.lastIndexOf(File.separator);
+ 		String backupPath = backedUpSnapshotUuid.substring(0, index);
+ 		backedUpSnapshotUuid = backedUpSnapshotUuid.substring(index + 1);
+ 		String details = null;
+ 		String newVolumeName = UUID.randomUUID().toString().replaceAll("-", "");
+ 
+ 		VmwareContext context = hostService.getServiceContext(cmd);
+ 		try {
+ 			VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
+ 			ManagedObjectReference morPrimaryDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost,
+ 					primaryStorageNameLabel);
+ 			if (morPrimaryDs == null) {
+ 				String msg = "Unable to find datastore: " + primaryStorageNameLabel;
+ 				s_logger.error(msg);
+ 				throw new Exception(msg);
+ 			}
+ 
+ 			DatastoreMO primaryDsMo = new DatastoreMO(hyperHost.getContext(), morPrimaryDs);
+ 			Long size = restoreVolumeFromSecStorage(hyperHost, primaryDsMo,
+ 					newVolumeName, secondaryStorageUrl, backupPath, backedUpSnapshotUuid);
+ 
+ 			VolumeObjectTO newVol = new VolumeObjectTO();
+ 			newVol.setPath(newVolumeName);
+ 			newVol.setSize(size);
+ 			return new CopyCmdAnswer(newVol);
+ 		} catch (Throwable e) {
+ 			if (e instanceof RemoteException) {
+ 				hostService.invalidateServiceContext(context);
+ 			}
+ 
+ 			s_logger.error("Unexpecpted exception ", e);
+ 			details = "CreateVolumeFromSnapshotCommand exception: " + StringUtils.getExceptionStackInfo(e);
+ 		}
+ 		return new CopyCmdAnswer(details);
+ 	}
+ 
+ 	@Override
+ 	public Answer deleteSnapshot(DeleteCommand cmd) {
+ 		SnapshotObjectTO snapshot = (SnapshotObjectTO)cmd.getData();
+ 		DataStoreTO store = snapshot.getDataStore();
+ 		if (store.getRole() == DataStoreRole.Primary) {
+ 			return new Answer(cmd);
+ 		} else {
+ 			return new Answer(cmd, false, "unsupported command");
+ 		}
+ 	}
+ }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7b7db056/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/VmwareDatacenterApiUnitTest.java
----------------------------------------------------------------------
diff --cc plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/VmwareDatacenterApiUnitTest.java
index de08c93,d79d41e..cc92276
--- a/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/VmwareDatacenterApiUnitTest.java
+++ b/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/VmwareDatacenterApiUnitTest.java
@@@ -17,7 -17,7 +17,6 @@@
  
  package com.cloud.hypervisor.vmware;
  
--import static org.junit.Assert.*;
  import static org.mockito.Mockito.when;
  
  import java.io.IOException;
@@@ -28,11 -28,12 +27,6 @@@ import java.util.UUID
  import javax.inject.Inject;
  import javax.naming.ConfigurationException;
  
--import junit.framework.TestCase;
--
--import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd;
--import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd;
- import org.apache.cloudstack.test.utils.SpringUtils;
 -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
 -import org.apache.cloudstack.test.utils.SpringUtils;
  import org.junit.Before;
  import org.junit.BeforeClass;
  import org.junit.Test;
@@@ -40,7 -41,7 +34,6 @@@ import org.junit.runner.RunWith
  import org.mockito.Mock;
  import org.mockito.Mockito;
  import org.mockito.MockitoAnnotations;
--import org.mockito.Spy;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.ComponentScan;
  import org.springframework.context.annotation.ComponentScan.Filter;
@@@ -53,13 -54,13 +46,19 @@@ import org.springframework.test.context
  import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  import org.springframework.test.context.support.AnnotationConfigContextLoader;
  
++import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd;
++import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd;
++import org.apache.cloudstack.context.CallContext;
++import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
++import org.apache.cloudstack.test.utils.SpringUtils;
++
  import com.cloud.agent.AgentManager;
  import com.cloud.cluster.ClusterManager;
  import com.cloud.configuration.dao.ConfigurationDao;
  import com.cloud.dc.ClusterDetailsDao;
  import com.cloud.dc.ClusterDetailsVO;
--import com.cloud.dc.DataCenter.NetworkType;
  import com.cloud.dc.ClusterVO;
++import com.cloud.dc.DataCenter.NetworkType;
  import com.cloud.dc.DataCenterVO;
  import com.cloud.dc.HostPodVO;
  import com.cloud.dc.dao.ClusterDao;
@@@ -76,7 -77,7 +75,6 @@@ import com.cloud.hypervisor.dao.Hypervi
  import com.cloud.hypervisor.vmware.dao.LegacyZoneDao;
  import com.cloud.hypervisor.vmware.dao.VmwareDatacenterDao;
  import com.cloud.hypervisor.vmware.dao.VmwareDatacenterZoneMapDao;
--import com.cloud.hypervisor.vmware.manager.VmwareManager;
  import com.cloud.hypervisor.vmware.manager.VmwareManagerImpl;
  import com.cloud.network.NetworkModel;
  import com.cloud.network.dao.CiscoNexusVSMDeviceDao;
@@@ -89,7 -90,7 +87,6 @@@ import com.cloud.user.Account
  import com.cloud.user.AccountManager;
  import com.cloud.user.AccountService;
  import com.cloud.user.AccountVO;
--import com.cloud.user.UserContext;
  import com.cloud.user.dao.AccountDao;
  import com.cloud.utils.component.ComponentContext;
  import com.cloud.utils.exception.CloudRuntimeException;
@@@ -175,7 -176,7 +172,7 @@@ public class VmwareDatacenterApiUnitTes
          acct.setType(Account.ACCOUNT_TYPE_ADMIN);
          acct.setAccountName("admin");
          acct.setDomainId(domainId);
--        UserContext.registerContext(1, acct, null, true);
++        CallContext.register(1, acct, null, true);
  
          when(_accountDao.findByIdIncludingRemoved(0L)).thenReturn(acct);
  

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7b7db056/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java
----------------------------------------------------------------------
diff --cc plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java
index 6dd6f3f,c52020e..5661374b
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java
@@@ -24,7 -24,9 +24,8 @@@ import com.cloud.hypervisor.Hypervisor.
  import com.cloud.storage.GuestOSVO;
  import com.cloud.storage.dao.GuestOSDao;
  import com.cloud.template.VirtualMachineTemplate.BootloaderType;
 -import com.cloud.vm.VirtualMachine;
  import com.cloud.vm.VirtualMachineProfile;
+ import com.cloud.vm.VirtualMachineProfileImpl;
  
  @Local(value=HypervisorGuru.class)
  public class XenServerGuru extends HypervisorGuruBase implements HypervisorGuru {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7b7db056/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
----------------------------------------------------------------------
diff --cc plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
index c01b605,af640a2..c947af6
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
@@@ -1130,31 -1185,42 +1186,42 @@@ public abstract class CitrixResourceBas
          }
      }
  
-     protected VDI mount(Connection conn, String vmName, VolumeTO volume) throws XmlRpcException, XenAPIException {
-         if (volume.getType() == Volume.Type.ISO) {
-             String isopath = volume.getPath();
-             if (isopath == null) {
+     protected VDI mount(Connection conn, String vmName, DiskTO volume) throws XmlRpcException, XenAPIException {
+         DataTO data = volume.getData();
+         Volume.Type type = volume.getType();
+         if (type == Volume.Type.ISO) {
+             TemplateObjectTO iso = (TemplateObjectTO)data;
+             DataStoreTO store = iso.getDataStore();
+             
+             if (store == null) {
+                 //It's a fake iso
                  return null;
              }
-             if (isopath.startsWith("xs-tools")) {
+             
+             //corer case, xenserver pv driver iso
+             String templateName = iso.getName();
+             if (templateName.startsWith("xs-tools")) {
                  try {
-                     Set<VDI> vdis = VDI.getByNameLabel(conn, isopath);
+                     Set<VDI> vdis = VDI.getByNameLabel(conn, templateName);
                      if (vdis.isEmpty()) {
-                         throw new CloudRuntimeException("Could not find ISO with URL: " + isopath);
+                         throw new CloudRuntimeException("Could not find ISO with URL: " + templateName);
                      }
                      return vdis.iterator().next();
- 
                  } catch (XenAPIException e) {
-                     throw new CloudRuntimeException("Unable to get pv iso: " + isopath + " due to " + e.toString());
+                     throw new CloudRuntimeException("Unable to get pv iso: " + templateName + " due to " + e.toString());
                  } catch (Exception e) {
-                     throw new CloudRuntimeException("Unable to get pv iso: " + isopath + " due to " + e.toString());
+                     throw new CloudRuntimeException("Unable to get pv iso: " + templateName + " due to " + e.toString());
                  }
              }
 -            
 +
+             if (!(store instanceof NfsTO)) {
+                 throw new CloudRuntimeException("only support mount iso on nfs");
+             }
+             NfsTO nfsStore = (NfsTO)store;
+             String isoPath = nfsStore.getUrl() + File.separator + iso.getPath();
+             int index = isoPath.lastIndexOf("/");
  
-             int index = isopath.lastIndexOf("/");
- 
-             String mountpoint = isopath.substring(0, index);
+             String mountpoint = isoPath.substring(0, index);
              URI uri;
              try {
                  uri = new URI(mountpoint);
@@@ -1290,16 -1357,21 +1358,21 @@@
  
          if (!(guestOsTypeName.startsWith("Windows") || guestOsTypeName.startsWith("Citrix") || guestOsTypeName.startsWith("Other"))) {
              if (vmSpec.getBootloader() == BootloaderType.CD) {
-                 VolumeTO [] disks = vmSpec.getDisks();
-                 for (VolumeTO disk : disks) {
-                     if (disk.getType() == Volume.Type.ISO && disk.getOsType() != null) {
-                         String isoGuestOsName = getGuestOsType(disk.getOsType(), vmSpec.getBootloader() == BootloaderType.CD);
+                 DiskTO [] disks = vmSpec.getDisks();
+                 for (DiskTO disk : disks) {
+                     Volume.Type type = disk.getType();
+                     if (type == Volume.Type.ISO) {
+                         TemplateObjectTO tmpl = (TemplateObjectTO)disk.getData();
+                         String osType = tmpl.getGuestOsType();
+                         if (tmpl.getFormat() == ImageFormat.ISO && osType != null ) {
+                             String isoGuestOsName = getGuestOsType(osType, vmSpec.getBootloader() == BootloaderType.CD);
 -                            if (!isoGuestOsName.equals(guestOsTypeName)) {
 -                                vmSpec.setBootloader(BootloaderType.PyGrub);
 -                            }
 +                        if (!isoGuestOsName.equals(guestOsTypeName)) {
 +                            vmSpec.setBootloader(BootloaderType.PyGrub);
                          }
                      }
                  }
              }
++            }
              if (vmSpec.getBootloader() == BootloaderType.CD) {
                  vm.setPVBootloader(conn, "eliloader");
                  Map<String, String> otherConfig = vm.getOtherConfig(conn);