You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mc...@apache.org on 2013/02/26 23:13:38 UTC

[1/28] git commit: refs/heads/vim51_win8 - From c72615de97b007517fb324044cb4625258c5fc61 Mon Sep 17 00:00:00 2001 From: Vijayendra Date: Mon, 25 Feb 2013 14:37:27 -0800 Subject: [PATCH] CS-670: Configurable setting to

>From c72615de97b007517fb324044cb4625258c5fc61 Mon Sep 17 00:00:00 2001
From: Vijayendra <vi...@citrix.com>
Date: Mon, 25 Feb 2013 14:37:27 -0800
Subject: [PATCH] CS-670: Configurable setting to use linked clones or not on
 VMware

Description:

  Providing support for creation of user VMs as full clones on ESX.
  Putting in unit tests for VO and Dao classes introduced in this commit.

Signed-off-by: Vijayendra <vi...@citrix.com>
---
 core/src/com/cloud/vm/UserVmCloneSettingVO.java    |  50 ++++++
 .../hypervisor/vmware/manager/VmwareManager.java   |   3 +
 .../vmware/manager/VmwareManagerImpl.java          |  18 +-
 .../hypervisor/vmware/resource/VmwareResource.java | 117 +++++++++----
 server/conf/migration-components.xml               |   1 +
 server/src/com/cloud/configuration/Config.java     |   1 +
 server/src/com/cloud/vm/UserVmManagerImpl.java     | 184 ++++++++++-----------
 .../com/cloud/vm/dao/UserVmCloneSettingDao.java    |  37 +++++
 .../cloud/vm/dao/UserVmCloneSettingDaoImpl.java    |  74 +++++++++
 .../vm/dao/UserVmCloneSettingDaoImplTest.java      |  62 +++++++
 .../UserVmCloneSettingDaoTestConfiguration.java    |  52 ++++++
 .../test/resources/CloneSettingDaoTestContext.xml  |  42 +++++
 setup/db/db/schema-410to420.sql                    |   9 +
 13 files changed, 527 insertions(+), 123 deletions(-)
 create mode 100755 core/src/com/cloud/vm/UserVmCloneSettingVO.java
 create mode 100755 server/src/com/cloud/vm/dao/UserVmCloneSettingDao.java
 create mode 100755 server/src/com/cloud/vm/dao/UserVmCloneSettingDaoImpl.java
 create mode 100644 server/test/com/cloud/vm/dao/UserVmCloneSettingDaoImplTest.java
 create mode 100644 server/test/com/cloud/vm/dao/UserVmCloneSettingDaoTestConfiguration.java
 create mode 100644 server/test/resources/CloneSettingDaoTestContext.xml


Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/cd291f6b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/cd291f6b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/cd291f6b

Branch: refs/heads/vim51_win8
Commit: cd291f6b4b5b851595ef11c5f14def9afddb6a1a
Parents: cc25e58
Author: frank <fr...@citrix.com>
Authored: Mon Feb 25 14:57:57 2013 -0800
Committer: frank <fr...@citrix.com>
Committed: Mon Feb 25 14:57:57 2013 -0800

----------------------------------------------------------------------
 core/src/com/cloud/vm/UserVmCloneSettingVO.java    |   50 ++++
 .../hypervisor/vmware/manager/VmwareManager.java   |    3 +
 .../vmware/manager/VmwareManagerImpl.java          |   18 ++-
 .../hypervisor/vmware/resource/VmwareResource.java |  117 +++++++---
 server/conf/migration-components.xml               |    1 +
 server/src/com/cloud/configuration/Config.java     |    1 +
 server/src/com/cloud/vm/UserVmManagerImpl.java     |  184 +++++++--------
 .../com/cloud/vm/dao/UserVmCloneSettingDao.java    |   37 +++
 .../cloud/vm/dao/UserVmCloneSettingDaoImpl.java    |   74 ++++++
 .../vm/dao/UserVmCloneSettingDaoImplTest.java      |   62 +++++
 .../UserVmCloneSettingDaoTestConfiguration.java    |   52 ++++
 .../test/resources/CloneSettingDaoTestContext.xml  |   42 ++++
 setup/db/db/schema-410to420.sql                    |    9 +
 13 files changed, 527 insertions(+), 123 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/cd291f6b/core/src/com/cloud/vm/UserVmCloneSettingVO.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/vm/UserVmCloneSettingVO.java b/core/src/com/cloud/vm/UserVmCloneSettingVO.java
new file mode 100644
index 0000000..24bb1e8
--- /dev/null
+++ b/core/src/com/cloud/vm/UserVmCloneSettingVO.java
@@ -0,0 +1,50 @@
+// 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
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.vm;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="user_vm_clone_setting")
+public class UserVmCloneSettingVO {
+
+    @Column(name="vm_id")
+    private Long vmId;
+
+    @Column(name="clone_type")
+    private String cloneType;
+
+    public UserVmCloneSettingVO() {
+
+    }
+
+    public UserVmCloneSettingVO(long id,
+            String cloneType) {
+        this.vmId = id;
+        this.cloneType = cloneType;
+    }
+
+    public long getVmId() {
+        return this.vmId;
+    }
+
+    public String getCloneType() {
+        return this.cloneType;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/cd291f6b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java
index 445b2f0..36fa0f3 100755
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java
@@ -21,6 +21,7 @@ import java.util.List;
 import java.util.Map;
 
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.hypervisor.vmware.manager.VmwareStorageManager;
 import com.cloud.hypervisor.vmware.mo.HostMO;
 import com.cloud.hypervisor.vmware.util.VmwareContext;
 import com.cloud.utils.Pair;
@@ -60,6 +61,8 @@ public interface VmwareManager {
 
     boolean getNexusVSwitchGlobalParameter();
 
+    boolean getFullCloneFlag();
+
     Map<String, String> getNexusVSMCredentialsByClusterId(Long clusterId);
 
     String getPrivateVSwitchName(long dcId, HypervisorType hypervisorType);

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/cd291f6b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
index 6b6bf19..a0d9943 100755
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
@@ -96,6 +96,7 @@ import com.vmware.vim25.AboutInfo;
 import com.vmware.vim25.HostConnectSpec;
 import com.vmware.vim25.ManagedObjectReference;
 
+
 @Local(value = {VmwareManager.class})
 public class VmwareManagerImpl extends ManagerBase implements VmwareManager, VmwareStorageMount, Listener {
     private static final Logger s_logger = Logger.getLogger(VmwareManagerImpl.class);
@@ -130,6 +131,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
     String _publicNetworkVSwitchName;
     String _guestNetworkVSwitchName;
     boolean _nexusVSwitchActive;
+    boolean _fullCloneFlag;
     String _serviceConsoleName;
     String _managemetPortGroupName;
     String _defaultSystemVmNicAdapterType = VirtualEthernetCardType.E1000.toString();
@@ -197,11 +199,17 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
         if(value == null) {
             _nexusVSwitchActive = false;
         }
-        else
-        {
+        else {
             _nexusVSwitchActive = Boolean.parseBoolean(value);
         }
 
+        value = _configDao.getValue(Config.VmwareCreateFullClone.key());
+        if (value == null) {
+            _fullCloneFlag = false;
+        } else {
+            _fullCloneFlag = Boolean.parseBoolean(value);
+        }
+
         _privateNetworkVSwitchName = _configDao.getValue(Config.VmwarePrivateNetworkVSwitch.key());
 
         if (_privateNetworkVSwitchName == null) {
@@ -316,6 +324,11 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
     }
 
     @Override
+    public boolean getFullCloneFlag() {
+        return _fullCloneFlag;
+    }
+
+    @Override
     public String composeWorkerName() {
         return UUID.randomUUID().toString().replace("-", "");
     }
@@ -495,6 +508,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
         params.put("public.network.vswitch.name", _publicNetworkVSwitchName);
         params.put("guest.network.vswitch.name", _guestNetworkVSwitchName);
         params.put("vmware.use.nexus.vswitch", _nexusVSwitchActive);
+        params.put("vmware.create.full.clone", _fullCloneFlag);
         params.put("service.console.name", _serviceConsoleName);
         params.put("management.portgroup.name", _managemetPortGroupName);
         params.put("vmware.reserve.cpu", _reserveCpu);

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/cd291f6b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
index f754c58..4839b35 100755
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
@@ -159,9 +159,9 @@ 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.to.FirewallRuleTO;
 import com.cloud.agent.api.storage.ResizeVolumeAnswer;
 import com.cloud.agent.api.storage.ResizeVolumeCommand;
+import com.cloud.agent.api.to.FirewallRuleTO;
 import com.cloud.agent.api.to.IpAddressTO;
 import com.cloud.agent.api.to.NicTO;
 import com.cloud.agent.api.to.PortForwardingRuleTO;
@@ -192,6 +192,7 @@ import com.cloud.hypervisor.vmware.mo.VirtualSwitchType;
 import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
 import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHostNetworkSummary;
 import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHostResourceSummary;
+import com.cloud.hypervisor.vmware.resource.VmwareContextFactory;
 import com.cloud.hypervisor.vmware.util.VmwareContext;
 import com.cloud.hypervisor.vmware.util.VmwareGuestOsMapper;
 import com.cloud.hypervisor.vmware.util.VmwareHelper;
@@ -260,6 +261,7 @@ import com.vmware.vim25.VirtualMachinePowerState;
 import com.vmware.vim25.VirtualMachineRuntimeInfo;
 import com.vmware.vim25.VirtualSCSISharing;
 
+
 public class VmwareResource implements StoragePoolResource, ServerResource, VmwareHostService {
     private static final Logger s_logger = Logger.getLogger(VmwareResource.class);
 
@@ -288,6 +290,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
     protected String _guestNetworkVSwitchName;
     protected VirtualSwitchType _vSwitchType = VirtualSwitchType.StandardVirtualSwitch;
     protected boolean _nexusVSwitch = false;
+    protected boolean _fullCloneFlag = false;
 
     protected boolean _reserveCpu = false;
 
@@ -3695,9 +3698,17 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                     dsMo.deleteFile(cmd.getVolume().getPath() + ".vmdk", morDc, true);
 
                     // root volume may be created via linked-clone, delete the delta disk as well
-                    if (s_logger.isInfoEnabled())
+                    if (_fullCloneFlag) {
+                        if (s_logger.isInfoEnabled()) {
+                            s_logger.info("Destroy volume by derived name: " + cmd.getVolume().getPath() + "-flat.vmdk");
+                        }
+                        dsMo.deleteFile(cmd.getVolume().getPath() + "-flat.vmdk", morDc, true);
+                    } else {
+                        if (s_logger.isInfoEnabled()) {
                         s_logger.info("Destroy volume by derived name: " + cmd.getVolume().getPath() + "-delta.vmdk");
+                        }
                     dsMo.deleteFile(cmd.getVolume().getPath() + "-delta.vmdk", morDc, true);
+                    }
                     return new Answer(cmd, true, "Success");
                 }
 
@@ -3799,6 +3810,70 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
         }
     }
 
+
+
+    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;
+    }
+
+    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;
+    }
+
+
     @Override
     public synchronized CreateAnswer execute(CreateCommand cmd) {
         if (s_logger.isInfoEnabled()) {
@@ -3858,37 +3933,16 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
 
                     ManagedObjectReference morPool = hyperHost.getHyperHostOwnerResourcePool();
                     ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
-                    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("create 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);
+                    //createVMLinkedClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
+                    if (!_fullCloneFlag) {
+                        createVMLinkedClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
+                    } else {
+                        createVMFullClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
                     }
 
                     VirtualMachineMO vmMo = new ClusterMO(context, morCluster).findVmOnHyperHost(vmdkName);
                     assert (vmMo != null);
 
-                    // 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);
-
                     s_logger.info("detach disks from volume-wrapper VM " + vmdkName);
                     vmMo.detachAllDisks();
 
@@ -4888,6 +4942,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
         if(value != null && value.equalsIgnoreCase("true"))
             _nexusVSwitch = true;
 
+        value = params.get("vmware.create.full.clone").toString();
+        if (value != null && value.equalsIgnoreCase("true")) {
+            _fullCloneFlag = true;
+        } else {
+            _fullCloneFlag = false;
+        }
+
         s_logger.info("VmwareResource network configuration info. private vSwitch: " + _privateNetworkVSwitchName + ", public vSwitch: " + _publicNetworkVSwitchName + ", guest network: "
                 + _guestNetworkVSwitchName);
 

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/cd291f6b/server/conf/migration-components.xml
----------------------------------------------------------------------
diff --git a/server/conf/migration-components.xml b/server/conf/migration-components.xml
index 90fbafa..2ba35c8 100644
--- a/server/conf/migration-components.xml
+++ b/server/conf/migration-components.xml
@@ -35,6 +35,7 @@ under the License.
         <dao name="VM Instance dao" class="com.cloud.vm.dao.VMInstanceDaoImpl" />
         <dao name="Volume dao" class="com.cloud.storage.dao.VolumeDaoImpl" />
         <dao name="User VM dao" class="com.cloud.vm.dao.UserVmDaoImpl" />
+        <dao name="User VM clone setting dao" class="com.cloud.vm.dao.UserVmCloneSettingDaoImpl" />
         <dao name="domain router dao" class="com.cloud.vm.dao.DomainRouterDaoImpl" />
         <dao name="Storage pool dao" class="com.cloud.storage.dao.StoragePoolDaoImpl" />
         <dao name="Account dao" class="com.cloud.user.dao.AccountDaoImpl" />

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/cd291f6b/server/src/com/cloud/configuration/Config.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java
index 1cea9aa..eb6fb24 100755
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -255,6 +255,7 @@ public enum Config {
     VmwarePublicNetworkVSwitch("Hidden", ManagementServer.class, String.class, "vmware.public.vswitch", null, "Specify the vSwitch on host for public network", null),
     VmwareGuestNetworkVSwitch("Hidden", ManagementServer.class, String.class, "vmware.guest.vswitch", null, "Specify the vSwitch on host for guest network", null),
     VmwareUseNexusVSwitch("Network", ManagementServer.class, Boolean.class, "vmware.use.nexus.vswitch", "false", "Enable/Disable Cisco Nexus 1000v vSwitch in VMware environment", null),
+                            VmwareCreateFullClone("Advanced", ManagementServer.class, Boolean.class, "vmware.create.full.clone", "false", "If set to true, creates guest VMs as full clones on ESX", null),
     VmwareServiceConsole("Advanced", ManagementServer.class, String.class, "vmware.service.console", "Service Console", "Specify the service console network name(for ESX hosts)", null),
     VmwareManagementPortGroup("Advanced", ManagementServer.class, String.class, "vmware.management.portgroup", "Management Network", "Specify the management network name(for ESXi hosts)", null),
     VmwareAdditionalVncPortRangeStart("Advanced", ManagementServer.class, Integer.class, "vmware.additional.vnc.portrange.start", "50000", "Start port number of additional VNC port range", null),

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/cd291f6b/server/src/com/cloud/vm/UserVmManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
index 6cb3f1a..c2bba63 100755
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -210,7 +210,6 @@ import com.cloud.utils.Journal;
 import com.cloud.utils.NumbersUtil;
 import com.cloud.utils.Pair;
 import com.cloud.utils.PasswordGenerator;
-import com.cloud.utils.component.Manager;
 import com.cloud.utils.component.ManagerBase;
 import com.cloud.utils.concurrency.NamedThreadFactory;
 import com.cloud.utils.crypt.RSAHelper;
@@ -226,35 +225,13 @@ import com.cloud.utils.exception.ExecutionException;
 import com.cloud.utils.fsm.NoTransitionException;
 import com.cloud.utils.net.NetUtils;
 import com.cloud.vm.VirtualMachine.State;
-import com.cloud.vm.dao.*;
-import org.apache.cloudstack.acl.ControlledEntity.ACLType;
-import org.apache.cloudstack.acl.SecurityChecker.AccessType;
-import org.apache.cloudstack.api.BaseCmd;
-import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd;
-import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd;
-import org.apache.cloudstack.api.command.user.template.CreateTemplateCmd;
-import org.apache.cloudstack.api.command.user.vm.*;
-import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd;
-import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd;
-import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
-import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
-import org.apache.commons.codec.binary.Base64;
-import org.apache.log4j.Logger;
-
-import javax.ejb.Local;
-import javax.naming.ConfigurationException;
-import java.util.*;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
 import com.cloud.vm.dao.InstanceGroupDao;
 import com.cloud.vm.dao.InstanceGroupVMMapDao;
 import com.cloud.vm.dao.NicDao;
+import com.cloud.vm.dao.UserVmCloneSettingDao;
 import com.cloud.vm.dao.UserVmDao;
 import com.cloud.vm.dao.UserVmDetailsDao;
 import com.cloud.vm.dao.VMInstanceDao;
-import com.cloud.vm.snapshot.VMSnapshot;
 import com.cloud.vm.snapshot.VMSnapshotManager;
 import com.cloud.vm.snapshot.dao.VMSnapshotDao;
 
@@ -266,6 +243,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
     private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION = 3; // 3
     // seconds
 
+    public enum UserVmCloneType {
+        full,
+        linked
+    }
+
     @Inject
     protected HostDao _hostDao = null;
     @Inject
@@ -283,6 +265,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
     @Inject
     protected DomainDao _domainDao = null;
     @Inject
+    protected UserVmCloneSettingDao _vmCloneSettingDao = null;
+    @Inject
     protected UserVmDao _vmDao = null;
     @Inject
     protected UserVmJoinDao _vmJoinDao = null;
@@ -398,10 +382,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
     UsageEventDao _usageEventDao;
     @Inject
     protected VMSnapshotDao _vmSnapshotDao;
-    @Inject 
+    @Inject
     protected VMSnapshotManager _vmSnapshotMgr;
-    
-    @Inject
+
+    @Inject
     List<DeployPlannerSelector> plannerSelectors;
 
     protected ScheduledExecutorService _executor = null;
@@ -420,7 +404,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
 
     @Inject
     protected OrchestrationService _orchSrvc;
-    
+
     @Inject VolumeManager volumeMgr;
 
     @Override
@@ -724,7 +708,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
     }
 
 
-    
+
 
     private void checkVMSnapshots(UserVmVO vm, Long volumeId, boolean attach) {
         // Check that if vm has any VM snapshot
@@ -737,7 +721,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
         }*/
     }
 
-   
+
 
     private UserVm rebootVirtualMachine(long userId, long vmId)
             throws InsufficientCapacityException, ResourceUnavailableException {
@@ -776,14 +760,14 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
             throw new InvalidParameterValueException(
                     "unable to find a virtual machine with id " + vmId);
         }
-        
+
         _accountMgr.checkAccess(caller, null, true, vmInstance);
 
         // Check that the specified service offering ID is valid
         _itMgr.checkIfCanUpgrade(vmInstance, svcOffId);
 
         // remove diskAndMemory VM snapshots
-       /* List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
+        /* List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
         for (VMSnapshotVO vmSnapshotVO : vmSnapshots) {
             if(vmSnapshotVO.getType() == VMSnapshot.Type.DiskAndMemory){
                 if(!_vmSnapshotMgr.deleteAllVMSnapshots(vmId, VMSnapshot.Type.DiskAndMemory)){
@@ -791,10 +775,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
                     s_logger.debug(errMsg);
                     throw new CloudRuntimeException(errMsg);
                 }
-                    
+
             }
         }*/
-        
+
         _itMgr.upgradeVmDb(vmId, svcOffId);
 
         return _vmDao.findById(vmInstance.getId());
@@ -817,7 +801,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
         }
         NicProfile profile = new NicProfile(null, null);
         if(ipAddress != null) {
-          profile = new NicProfile(ipAddress, null);
+            profile = new NicProfile(ipAddress, null);
         }
 
         // Perform permission check on VM
@@ -837,7 +821,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
                 throw new PermissionDeniedException("Unable to modify a vm using network with id " + network.getId() + ", permission denied");
             }
         }
-        
+
         //ensure network belongs in zone
         if (network.getDataCenterId() != vmInstance.getDataCenterId()) {
             throw new CloudRuntimeException(vmInstance + " is in zone:" + vmInstance.getDataCenterId() + " but " + network + " is in zone:" + network.getDataCenterId());
@@ -853,7 +837,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
                 throw new CloudRuntimeException(network + " already has a vm with host name: '" + vmInstance.getHostName());
             }
         }
-        
+
         NicProfile guestNic = null;
 
         try {
@@ -914,14 +898,14 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
                 throw new PermissionDeniedException("Unable to modify a vm using network with id " + network.getId() + ", permission denied");
             }
         }
-        
+
         boolean nicremoved = false;
 
         try {
             nicremoved = _itMgr.removeNicFromVm(vmInstance, nic);
         } catch (ResourceUnavailableException e) {
             throw new CloudRuntimeException("Unable to remove " + network + " from " + vmInstance +": " + e);
-            
+
         } catch (ConcurrentOperationException e) {
             throw new CloudRuntimeException("Concurrent operations on removing " + network + " from " + vmInstance + ": " + e);
         }
@@ -929,19 +913,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
         if (!nicremoved) {
             throw new CloudRuntimeException("Unable to remove " + network +  " from " + vmInstance );
         }
-            
+
         s_logger.debug("Successful removal of " + network + " from " + vmInstance);
         return _vmDao.findById(vmInstance.getId());
 
-        
+
     }
-    
+
     @Override
     public UserVm updateDefaultNicForVirtualMachine(UpdateDefaultNicForVMCmd cmd) throws InvalidParameterValueException, CloudRuntimeException {
         Long vmId = cmd.getVmId();
         Long nicId = cmd.getNicId();
         Account caller = UserContext.current().getCaller();
-        
+
         UserVmVO vmInstance = _vmDao.findById(vmId);
         if (vmInstance == null){
             throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
@@ -954,7 +938,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
         if (network == null){
             throw new InvalidParameterValueException("unable to find a network with id " + nic.getNetworkId());
         }
-        
+
         // Perform permission check on VM
         _accountMgr.checkAccess(caller, null, true, vmInstance);
 
@@ -966,7 +950,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
 
         // no need to check permissions for network, we'll enumerate the ones they already have access to
         Network existingdefaultnet = _networkModel.getDefaultNetworkForVm(vmId);
-        
+
         //check to see if nic is attached to VM
         if (nic.getInstanceId() != vmId) {
             throw new InvalidParameterValueException(nic + " is not a nic on  " + vmInstance);
@@ -980,7 +964,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
         if ((vmInstance.getState() != State.Running) && (vmInstance.getState() != State.Stopped)) {
             throw new CloudRuntimeException("refusing to set default " + vmInstance + " is not Running or Stopped");
         }
-        
+
         NicProfile existing = null;
         List<NicProfile> nicProfiles = _networkMgr.getNicProfiles(vmInstance);
         for (NicProfile nicProfile : nicProfiles) {
@@ -1009,26 +993,26 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
 
         Network newdefault = null;
         newdefault = _networkModel.getDefaultNetworkForVm(vmId);
-        
+
         if (newdefault == null){
-             nic.setDefaultNic(false);
-             nic.setDeviceId(chosenID);
-             existingVO.setDefaultNic(true);
-             existingVO.setDeviceId(existingID);
-
-             nic = _nicDao.persist(nic);
-             existingVO = _nicDao.persist(existingVO);
-             
-             newdefault = _networkModel.getDefaultNetworkForVm(vmId);
-             if (newdefault.getId() == existingdefaultnet.getId()) {
-                    throw new CloudRuntimeException("Setting a default nic failed, and we had no default nic, but we were able to set it back to the original");
-             }
-             throw new CloudRuntimeException("Failed to change default nic to " + nic + " and now we have no default");
+            nic.setDefaultNic(false);
+            nic.setDeviceId(chosenID);
+            existingVO.setDefaultNic(true);
+            existingVO.setDeviceId(existingID);
+
+            nic = _nicDao.persist(nic);
+            existingVO = _nicDao.persist(existingVO);
+
+            newdefault = _networkModel.getDefaultNetworkForVm(vmId);
+            if (newdefault.getId() == existingdefaultnet.getId()) {
+                throw new CloudRuntimeException("Setting a default nic failed, and we had no default nic, but we were able to set it back to the original");
+            }
+            throw new CloudRuntimeException("Failed to change default nic to " + nic + " and now we have no default");
         } else if (newdefault.getId() == nic.getNetworkId()) {
             s_logger.debug("successfully set default network to " + network + " for " + vmInstance);
             return _vmDao.findById(vmInstance.getId());
         }
- 
+
         throw new CloudRuntimeException("something strange happened, new default network(" + newdefault.getId() + ") is not null, and is not equal to the network(" + nic.getNetworkId() + ") of the chosen nic");
     }
 
@@ -1963,7 +1947,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
                 if (isSecurityGroupEnabled) {
                     if (networkIdList.size() > 1) {
                         throw new InvalidParameterValueException("Can't create a vm with multiple networks one of" +
-                        		" which is Security Group enabled");
+                                " which is Security Group enabled");
                     }
 
                     isSecurityGroupEnabledNetworkUsed = true;
@@ -1971,7 +1955,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
 
                 if (!(network.getTrafficType() == TrafficType.Guest && network.getGuestType() == Network.GuestType.Shared)) {
                     throw new InvalidParameterValueException("Can specify only Shared Guest networks when" +
-                    		" deploy vm in Advance Security Group enabled zone");
+                            " deploy vm in Advance Security Group enabled zone");
                 }
 
                 // Perform account permission check
@@ -1984,8 +1968,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
 
         // if network is security group enabled, and no security group is specified, then add the default security group automatically
         if (isSecurityGroupEnabledNetworkUsed && !isVmWare && _networkModel.canAddDefaultSecurityGroup()) {
-            
-          //add the default securityGroup only if no security group is specified
+
+            //add the default securityGroup only if no security group is specified
             if(securityGroupIdList == null || securityGroupIdList.isEmpty()){
                 if (securityGroupIdList == null) {
                     securityGroupIdList = new ArrayList<Long>();
@@ -2109,7 +2093,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
                     }
 
                 }
-                
+
                 _networkModel.checkNetworkPermissions(owner, network);
 
                 // don't allow to use system networks
@@ -2139,7 +2123,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
     @DB @ActionEvent(eventType = EventTypes.EVENT_VM_CREATE, eventDescription = "deploying Vm", create = true)
     protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, String hostName, String displayName, Account owner, Long diskOfferingId,
             Long diskSize, List<NetworkVO> networkList, List<Long> securityGroupIdList, String group, String userData, String sshKeyPair, HypervisorType hypervisor, Account caller, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, String keyboard)
-            		throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, StorageUnavailableException, ResourceAllocationException {
+                    throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, StorageUnavailableException, ResourceAllocationException {
 
         _accountMgr.checkAccess(caller, null, true, owner);
 
@@ -2193,7 +2177,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
                 }
             }
         }
-
+
         if (template.getHypervisorType() != null && template.getHypervisorType() != HypervisorType.BareMetal) {
             // check if we have available pools for vm deployment
             long availablePools = _storagePoolDao.countPoolsByStatus(StoragePoolStatus.Up);
@@ -2246,7 +2230,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
         }
 
         List<Pair<NetworkVO, NicProfile>> networks = new ArrayList<Pair<NetworkVO, NicProfile>>();
-       
+
         Map<String, NicProfile> networkNicMap = new HashMap<String, NicProfile>();
 
         short defaultNetworkNumber = 0;
@@ -2263,20 +2247,20 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
             if (requestedIps != null && !requestedIps.isEmpty()) {
                 requestedIpPair = requestedIps.get(network.getId());
             }
-            
+
             if (requestedIpPair == null) {
-            	requestedIpPair = new IpAddresses(null, null);
+                requestedIpPair = new IpAddresses(null, null);
             } else {
-            	_networkModel.checkRequestedIpAddresses(network.getId(), requestedIpPair.getIp4Address(), requestedIpPair.getIp6Address());
+                _networkModel.checkRequestedIpAddresses(network.getId(), requestedIpPair.getIp4Address(), requestedIpPair.getIp6Address());
             }
-            
+
             NicProfile profile = new NicProfile(requestedIpPair.getIp4Address(), requestedIpPair.getIp6Address());
 
             if (defaultNetworkNumber == 0) {
                 defaultNetworkNumber++;
                 // if user requested specific ip for default network, add it
                 if (defaultIps.getIp4Address() != null || defaultIps.getIp6Address() != null) {
-                	_networkModel.checkRequestedIpAddresses(network.getId(), defaultIps.getIp4Address(), defaultIps.getIp6Address());
+                    _networkModel.checkRequestedIpAddresses(network.getId(), defaultIps.getIp4Address(), defaultIps.getIp6Address());
                     profile = new NicProfile(defaultIps.getIp4Address(), defaultIps.getIp6Address());
                 }
 
@@ -2405,6 +2389,20 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
             vm.setIsoId(template.getId());
         }
 
+        // If hypervisor is vSphere, check for clone type setting.
+        if (hypervisorType.equals(HypervisorType.VMware)) {
+            // retrieve clone flag.
+            UserVmCloneType cloneType = UserVmCloneType.linked;
+            String value = _configDao.getValue(Config.VmwareCreateFullClone.key());
+            if (value != null) {
+                if (Boolean.parseBoolean(value) == true)
+                    cloneType = UserVmCloneType.full;
+            }
+            UserVmCloneSettingVO vmCloneSettingVO = new UserVmCloneSettingVO(id, cloneType.toString());
+            _vmCloneSettingDao.persist(vmCloneSettingVO);
+        }
+
+
         _vmDao.persist(vm);
         _vmDao.saveDetails(vm);
 
@@ -2429,7 +2427,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
             VirtualMachineEntity vmEntity = _orchSrvc.createVirtualMachine(vm.getUuid(), new Long(owner.getAccountId()).toString(), new Long(template.getId()).toString(), hostName, displayName, hypervisor.name(), offering.getCpu(),  offering.getSpeed(), offering.getRamSize(), diskSize, computeTags, rootDiskTags, networkNicMap, plan);
         }
 
-        
+
 
         if (s_logger.isDebugEnabled()) {
             s_logger.debug("Successfully allocated DB entry for " + vm);
@@ -2465,7 +2463,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
         return vm;
     }
 
-	private void validateUserData(String userData) {
+    private void validateUserData(String userData) {
         byte[] decodedUserData = null;
         if (userData != null) {
             if (!Base64.isBase64(userData)) {
@@ -2499,7 +2497,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
     protected UserVm startVirtualMachine(DeployVMCmd cmd,
             Map<VirtualMachineProfile.Param, Object> additonalParams)
                     throws ResourceUnavailableException, InsufficientCapacityException,
-    ConcurrentOperationException {
+                    ConcurrentOperationException {
 
         long vmId = cmd.getEntityId();
         Long hostId = cmd.getHostId();
@@ -2896,18 +2894,18 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
         }
 
         VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
-        
-        String plannerName = null;
-        for (DeployPlannerSelector dps : plannerSelectors) {
-            plannerName = dps.selectPlanner(vm);
-            if (plannerName != null) {
+
+        String plannerName = null;
+        for (DeployPlannerSelector dps : plannerSelectors) {
+            plannerName = dps.selectPlanner(vm);
+            if (plannerName != null) {
                 break;
             }
-        }
-        if (plannerName == null) {
+        }
+        if (plannerName == null) {
             throw new CloudRuntimeException(String.format("cannot find DeployPlannerSelector for vm[uuid:%s, hypervisorType:%s]", vm.getUuid(), vm.getHypervisorType()));
-        }
-        
+        }
+
         String reservationId = vmEntity.reserve(plannerName, plan, new ExcludeList(), new Long(callerUser.getId()).toString());
         vmEntity.deploy(reservationId, new Long(callerUser.getId()).toString());
 
@@ -3069,7 +3067,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
 
         if (tags != null && !tags.isEmpty()) {
             int count = 0;
-             for (String key : tags.keySet()) {
+            for (String key : tags.keySet()) {
                 sc.setParameters("key" + String.valueOf(count), key);
                 sc.setParameters("value" + String.valueOf(count), tags.get(key));
                 count++;
@@ -3189,7 +3187,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
     public UserVm createVirtualMachine(DeployVMCmd cmd)
             throws InsufficientCapacityException, ResourceUnavailableException,
             ConcurrentOperationException, StorageUnavailableException,
-    ResourceAllocationException {
+            ResourceAllocationException {
         // TODO Auto-generated method stub
         return null;
     }
@@ -3557,12 +3555,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
         List<Long> securityGroupIdList = cmd.getSecurityGroupIdList();
 
         if (zone.getNetworkType() == NetworkType.Basic) {
-             if (networkIdList != null && !networkIdList.isEmpty()) {
+            if (networkIdList != null && !networkIdList.isEmpty()) {
                 throw new InvalidParameterValueException(
                         "Can't move vm with network Ids; this is a basic zone VM");
-             }
+            }
             // cleanup the old security groups
-             _securityGroupMgr.removeInstanceFromGroups(cmd.getVmId());
+            _securityGroupMgr.removeInstanceFromGroups(cmd.getVmId());
             // cleanup the network for the oldOwner
             _networkMgr.cleanupNics(vmOldProfile);
             _networkMgr.expungeNics(vmOldProfile);
@@ -3700,7 +3698,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
                                 throw new InvalidParameterValueException("Unable to find physical network with id: "+physicalNetworkId   + " and tag: " +requiredOfferings.get(0).getTags());
                             }
                             s_logger.debug("Creating network for account " + newAccount + " from the network offering id=" +
-                        requiredOfferings.get(0).getId() + " as a part of deployVM process");
+                                    requiredOfferings.get(0).getId() + " as a part of deployVM process");
                             Network newNetwork = _networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(),
                                     newAccount.getAccountName() + "-network", newAccount.getAccountName() + "-network", null, null,
                                     null, null, newAccount, null, physicalNetwork, zone.getId(), ACLType.Account, null, null, null, null);
@@ -3909,7 +3907,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
     public boolean plugNic(Network network, NicTO nic, VirtualMachineTO vm,
             ReservationContext context, DeployDestination dest)
                     throws ConcurrentOperationException, ResourceUnavailableException,
-            InsufficientCapacityException {
+                    InsufficientCapacityException {
         UserVmVO vmVO = _vmDao.findById(vm.getId());
         if (vmVO.getState() == State.Running) {
             try {

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/cd291f6b/server/src/com/cloud/vm/dao/UserVmCloneSettingDao.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/dao/UserVmCloneSettingDao.java b/server/src/com/cloud/vm/dao/UserVmCloneSettingDao.java
new file mode 100644
index 0000000..44a1bf3
--- /dev/null
+++ b/server/src/com/cloud/vm/dao/UserVmCloneSettingDao.java
@@ -0,0 +1,37 @@
+// 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
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.vm.dao;
+
+import java.util.List;
+
+import com.cloud.utils.db.GenericDao;
+import com.cloud.vm.UserVmCloneSettingVO;
+
+public interface UserVmCloneSettingDao extends GenericDao<UserVmCloneSettingVO, Long> {
+
+    /*
+     * Returns a User VM clone type record by vm id.
+     */
+    UserVmCloneSettingVO findByVmId(long id);
+
+    /*
+     * Returns a list of VMs by clone type.
+     * cloneType can be full/linked.
+     */
+    List<UserVmCloneSettingVO> listByCloneType(String cloneType);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/cd291f6b/server/src/com/cloud/vm/dao/UserVmCloneSettingDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/dao/UserVmCloneSettingDaoImpl.java b/server/src/com/cloud/vm/dao/UserVmCloneSettingDaoImpl.java
new file mode 100644
index 0000000..174f283
--- /dev/null
+++ b/server/src/com/cloud/vm/dao/UserVmCloneSettingDaoImpl.java
@@ -0,0 +1,74 @@
+// 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
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.vm.dao;
+
+
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+import javax.ejb.Local;
+
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.SearchCriteria.Op;
+import com.cloud.vm.UserVmCloneSettingVO;
+import com.cloud.utils.db.DB;
+
+
+@Component
+@Local(value= { UserVmCloneSettingDao.class })
+@DB(txn = false)
+public class UserVmCloneSettingDaoImpl extends GenericDaoBase<UserVmCloneSettingVO, Long> implements UserVmCloneSettingDao {
+    public static final Logger s_logger = Logger.getLogger(UserVmCloneSettingDaoImpl.class);
+
+    protected SearchBuilder<UserVmCloneSettingVO> vmIdSearch;
+    protected SearchBuilder<UserVmCloneSettingVO> cloneTypeSearch;
+
+    public UserVmCloneSettingDaoImpl() {
+    }
+
+    @PostConstruct
+    public void init() {
+        // Initialize the search builders.
+        vmIdSearch = createSearchBuilder();
+        vmIdSearch.and("vmId", vmIdSearch.entity().getCloneType(), Op.EQ);
+        vmIdSearch.done();
+
+        cloneTypeSearch = createSearchBuilder();
+        cloneTypeSearch.and("cloneType", cloneTypeSearch.entity().getCloneType(), Op.EQ);
+        cloneTypeSearch.done();
+    }
+
+    @Override
+    public UserVmCloneSettingVO findByVmId(long vmId) {
+        SearchCriteria<UserVmCloneSettingVO> sc = vmIdSearch.create();
+        sc.setParameters("vmId", vmId);
+        return findOneBy(sc);
+    }
+
+    @Override
+    public List<UserVmCloneSettingVO> listByCloneType(String cloneType) {
+        SearchCriteria<UserVmCloneSettingVO> sc = cloneTypeSearch.create();
+        sc.setParameters("cloneType", cloneType);
+        return search(sc, null);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/cd291f6b/server/test/com/cloud/vm/dao/UserVmCloneSettingDaoImplTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vm/dao/UserVmCloneSettingDaoImplTest.java b/server/test/com/cloud/vm/dao/UserVmCloneSettingDaoImplTest.java
new file mode 100644
index 0000000..c96ba36
--- /dev/null
+++ b/server/test/com/cloud/vm/dao/UserVmCloneSettingDaoImplTest.java
@@ -0,0 +1,62 @@
+// 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
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.vm.dao;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import junit.framework.TestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import com.cloud.vm.UserVmCloneSettingVO;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = "classpath:/CloneSettingDaoTestContext.xml")
+public class UserVmCloneSettingDaoImplTest extends TestCase {
+    @Inject UserVmCloneSettingDaoImpl _vmcsdao;
+
+    public void makeEntry(Long vmId, String cloneType) {
+        UserVmCloneSettingVO vo = new UserVmCloneSettingVO(vmId, cloneType);
+        _vmcsdao.persist(vo);
+        vo = _vmcsdao.findById(vmId);
+        assert (vo.getCloneType().equalsIgnoreCase(cloneType)) : "Unexpected Clone Type retrieved from table! Retrieved: " + vo.getCloneType() + " while expected was: " + cloneType;
+
+        // Next test whether the record is retrieved by clone type.
+        List<UserVmCloneSettingVO> voList = new ArrayList<UserVmCloneSettingVO>();
+        voList = _vmcsdao.listByCloneType(cloneType);
+        assert (voList != null && !voList.isEmpty()) : "Failed to retrieve any record of VMs by clone type!";
+
+        // If a vo list is indeed retrieved, also check whether the vm id retrieved matches what we put in there.
+        assert (voList.get(0).getVmId() == vmId) : "Retrieved vmId " + voList.get(0).getVmId() + " does not match input vmId: " + vmId;
+    }
+    @Test
+    public void testPersist() {
+
+        Long vmId = 2222l;
+        String[] arr = {"full", "linked"};
+        for (String cloneType : arr) {
+            _vmcsdao.expunge(vmId);
+            makeEntry(vmId, cloneType);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/cd291f6b/server/test/com/cloud/vm/dao/UserVmCloneSettingDaoTestConfiguration.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vm/dao/UserVmCloneSettingDaoTestConfiguration.java b/server/test/com/cloud/vm/dao/UserVmCloneSettingDaoTestConfiguration.java
new file mode 100644
index 0000000..8bb2a4d
--- /dev/null
+++ b/server/test/com/cloud/vm/dao/UserVmCloneSettingDaoTestConfiguration.java
@@ -0,0 +1,52 @@
+// 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
+// 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.cloud.storage.dao;
+
+import java.io.IOException;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.ComponentScan.Filter;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.FilterType;
+import org.springframework.core.type.classreading.MetadataReader;
+import org.springframework.core.type.classreading.MetadataReaderFactory;
+import org.springframework.core.type.filter.TypeFilter;
+
+import com.cloud.utils.component.SpringComponentScanUtils;
+import com.cloud.vm.dao.UserVmCloneSettingDaoImpl;
+
+@Configuration
+@ComponentScan(basePackageClasses={
+        UserVmCloneSettingDaoImpl.class},
+        includeFilters={@Filter(value=UserVmCloneSettingDaoTestConfiguration.Library.class, type=FilterType.CUSTOM)},
+        useDefaultFilters=false
+        )
+public class UserVmCloneSettingDaoTestConfiguration {
+
+
+    public static class Library implements TypeFilter {
+
+        @Override
+        public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException {
+            mdr.getClassMetadata().getClassName();
+            ComponentScan cs = UserVmCloneSettingDaoTestConfiguration.class.getAnnotation(ComponentScan.class);
+            return SpringComponentScanUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs);
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/cd291f6b/server/test/resources/CloneSettingDaoTestContext.xml
----------------------------------------------------------------------
diff --git a/server/test/resources/CloneSettingDaoTestContext.xml b/server/test/resources/CloneSettingDaoTestContext.xml
new file mode 100644
index 0000000..1d13500
--- /dev/null
+++ b/server/test/resources/CloneSettingDaoTestContext.xml
@@ -0,0 +1,42 @@
+<!-- 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 specific
+  language governing permissions and limitations under the License. -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
+  xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans
+                      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+                      http://www.springframework.org/schema/tx
+                      http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
+                      http://www.springframework.org/schema/aop
+                      http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
+                      http://www.springframework.org/schema/context
+                      http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+
+  <context:annotation-config />
+
+  <!-- @DB support -->
+  <aop:config proxy-target-class="true">
+    <aop:aspect id="dbContextBuilder" ref="transactionContextBuilder">
+      <aop:pointcut id="captureAnyMethod" expression="execution(* *(..))" />
+
+      <aop:around pointcut-ref="captureAnyMethod" method="AroundAnyMethod" />
+    </aop:aspect>
+
+  </aop:config>
+
+  <bean id="transactionContextBuilder" class="com.cloud.utils.db.TransactionContextBuilder" />
+  <bean id="componentContext" class="com.cloud.utils.component.ComponentContext"/>
+  <bean id="CSTestConfiguration"
+    class="com.cloud.vm.dao.UserVmCloneSettingDaoTestConfiguration" />
+  <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" >
+    <property name="requiredParameterValue" value="false" />
+  </bean>
+</beans>

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/cd291f6b/setup/db/db/schema-410to420.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql
index be8e7f5..6c831f0 100644
--- a/setup/db/db/schema-410to420.sql
+++ b/setup/db/db/schema-410to420.sql
@@ -100,3 +100,12 @@ CREATE TABLE  `vpc_service_map` (
 SET foreign_key_checks = 1;
 
 INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'vm.instancename.flag', 'false', 'Append guest VM display Name (if set) to the internal name of the VM');
+
+CREATE TABLE `cloud`.`user_vm_clone_setting` (
+  `vm_id` bigint unsigned NOT NULL COMMENT 'guest VM id',
+  `clone_type` varchar(10) NOT NULL COMMENT 'Full or Linked Clone (applicable to VMs on ESX)',
+  PRIMARY KEY (`vm_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+
+INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'UserVmManager', 'vmware.create.full.clone' , 'false', 'If set to true, creates VMs as full clones on ESX hypervisor');