You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by an...@apache.org on 2020/03/13 19:56:41 UTC

[cloudstack] branch master updated: UEFI Implementation: Enabled UEFI Support for Guest VM's on Hypervisor KVM, VMware. enabled boot modes [Legacy, Secure] support for UEFI boot with known caveats. (#3638)

This is an automated email from the ASF dual-hosted git repository.

andrijapanic pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/master by this push:
     new d4b537e  UEFI Implementation:  Enabled UEFI Support for Guest VM's on Hypervisor KVM,VMware. enabled boot modes [Legacy,Secure] support for UEFI boot with known caveats. (#3638)
d4b537e is described below

commit d4b537efa7ed27ef88b735a22493808b61529186
Author: pavanaravapalli <pa...@accelerite.com>
AuthorDate: Sat Mar 14 01:26:26 2020 +0530

    UEFI Implementation:  Enabled UEFI Support for Guest VM's on Hypervisor KVM,VMware. enabled boot modes [Legacy,Secure] support for UEFI boot with known caveats. (#3638)
    
    Co-authored-by: Pavan Kumar Aravapalli <pa...@accelerite.com>
    Co-authored-by: dahn <da...@shapeblue.com>
---
 .../com/cloud/agent/api/to/VirtualMachineTO.java   |  13 +++
 api/src/main/java/com/cloud/host/Host.java         |   1 +
 .../java/com/cloud/vm/VirtualMachineProfile.java   |   3 +
 .../main/java/com/cloud/vm/VmDetailConstants.java  |   1 +
 .../org/apache/cloudstack/api/ApiConstants.java    |  21 ++++
 .../api/command/user/vm/DeployVMCmd.java           |  48 ++++++++
 .../cloudstack/api/response/HostResponse.java      |  16 +++
 .../cloudstack/api/response/UserVmResponse.java    |  17 +++
 .../cloud/entity/api/VirtualMachineEntity.java     |   6 +
 .../com/cloud/vm/VirtualMachineManagerImpl.java    |   4 +
 .../cloud/entity/api/VMEntityManagerImpl.java      |  10 ++
 .../cloud/entity/api/VirtualMachineEntityImpl.java |  20 ++++
 .../src/main/java/com/cloud/host/dao/HostDao.java  |   2 +
 .../main/java/com/cloud/host/dao/HostDaoImpl.java  |  34 ++++++
 .../implicitplanner/ImplicitPlannerTest.java       |   5 +
 .../kvm/resource/LibvirtComputingResource.java     | 113 +++++++++++++++++-
 .../hypervisor/kvm/resource/LibvirtVMDef.java      | 129 ++++++++++++++++++++-
 .../java/com/cloud/hypervisor/guru/VMwareGuru.java |   1 +
 .../hypervisor/vmware/VmwareServerDiscoverer.java  |   5 +
 .../hypervisor/vmware/resource/VmwareResource.java |  19 +++
 .../manager/allocator/impl/FirstFitAllocator.java  |  28 +++++
 .../com/cloud/api/query/dao/UserVmJoinDaoImpl.java |   9 ++
 .../deploy/DeploymentPlanningManagerImpl.java      |  11 ++
 .../java/com/cloud/deploy/FirstFitPlanner.java     |  29 ++++-
 .../com/cloud/hypervisor/HypervisorGuruBase.java   |  10 +-
 .../kvm/discoverer/LibvirtServerDiscoverer.java    |   7 ++
 .../com/cloud/server/ManagementServerImpl.java     |  14 +++
 .../main/java/com/cloud/vm/UserVmManagerImpl.java  |  16 ++-
 .../vm/DeploymentPlanningManagerImplTest.java      |   7 ++
 .../java/com/cloud/vm/FirstFitPlannerTest.java     |   6 +
 ui/index.html                                      |  25 ++++
 ui/l10n/en.js                                      |   3 +
 ui/scripts/instanceWizard.js                       |  12 ++
 ui/scripts/instances.js                            |   6 +
 ui/scripts/system.js                               |   4 +
 ui/scripts/ui-custom/instanceWizard.js             |  44 +++++++
 .../com/cloud/hypervisor/vmware/mo/HostMO.java     |  13 +++
 .../cloud/hypervisor/vmware/util/VmwareHelper.java |   1 +
 38 files changed, 700 insertions(+), 13 deletions(-)

diff --git a/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java
index d25ffe3..40f30df 100644
--- a/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java
@@ -63,6 +63,8 @@ public class VirtualMachineTO {
     String vncAddr;
     Map<String, String> params;
     String uuid;
+    String bootType;
+    String bootMode;
 
     DiskTO[] disks;
     NicTO[] nics;
@@ -380,4 +382,15 @@ public class VirtualMachineTO {
     public void setOvfProperties(Pair<String, List<OVFPropertyTO>> ovfProperties) {
         this.ovfProperties = ovfProperties;
     }
+    public String getBootType() {
+        return bootType;
+    }
+
+    public void setBootType(String bootType) {
+        this.bootType = bootType;
+    }
+
+    public String getBootMode() { return bootMode; }
+
+    public void setBootMode(String bootMode) { this.bootMode = bootMode; }
 }
diff --git a/api/src/main/java/com/cloud/host/Host.java b/api/src/main/java/com/cloud/host/Host.java
index 1ecd48d..e5a3889 100644
--- a/api/src/main/java/com/cloud/host/Host.java
+++ b/api/src/main/java/com/cloud/host/Host.java
@@ -52,6 +52,7 @@ public interface Host extends StateObject<Status>, Identity, Partition, HAResour
             return strs;
         }
     }
+    public static final String HOST_UEFI_ENABLE = "host.uefi.enable";
 
     /**
      * @return name of the machine.
diff --git a/api/src/main/java/com/cloud/vm/VirtualMachineProfile.java b/api/src/main/java/com/cloud/vm/VirtualMachineProfile.java
index 977e27e..1abc764 100644
--- a/api/src/main/java/com/cloud/vm/VirtualMachineProfile.java
+++ b/api/src/main/java/com/cloud/vm/VirtualMachineProfile.java
@@ -60,6 +60,9 @@ public interface VirtualMachineProfile {
         public static final Param PxeSeverType = new Param("PxeSeverType");
         public static final Param HaTag = new Param("HaTag");
         public static final Param HaOperation = new Param("HaOperation");
+        public static final Param UefiFlag = new Param("UefiFlag");
+        public static final Param BootMode = new Param("BootMode");
+        public static final Param BootType = new Param("BootType");
 
         private String name;
 
diff --git a/api/src/main/java/com/cloud/vm/VmDetailConstants.java b/api/src/main/java/com/cloud/vm/VmDetailConstants.java
index 7c40a7b..3812aa2 100644
--- a/api/src/main/java/com/cloud/vm/VmDetailConstants.java
+++ b/api/src/main/java/com/cloud/vm/VmDetailConstants.java
@@ -20,6 +20,7 @@ public interface VmDetailConstants {
     String KEYBOARD = "keyboard";
     String CPU_CORE_PER_SOCKET = "cpu.corespersocket";
     String ROOT_DISK_SIZE = "rootdisksize";
+    String BOOT_MODE = "boot.mode";
 
     // VMware specific
     String NIC_ADAPTER = "nicAdapter";
diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
index 0482364..2a201db 100644
--- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
@@ -804,6 +804,27 @@ public class ApiConstants {
     public static final String NODE_ROOT_DISK_SIZE = "noderootdisksize";
     public static final String SUPPORTS_HA = "supportsha";
 
+    public static final String BOOT_TYPE ="boottype";
+    public static final String BOOT_MODE ="bootmode";
+
+    public enum BootType {
+        UEFI, BIOS;
+
+        @Override
+        public String toString() {
+            return this.name();
+        }
+    }
+
+    public enum BootMode {
+        LEGACY, SECURE;
+
+        @Override
+        public String toString() {
+            return this.name();
+        }
+    }
+
     public enum HostDetails {
         all, capacity, events, stats, min;
     }
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java
index 60b9f31..db315cc 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java
@@ -17,6 +17,7 @@
 package org.apache.cloudstack.api.command.user.vm;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -26,6 +27,8 @@ import java.util.Map;
 
 import javax.annotation.Nonnull;
 
+import com.cloud.utils.StringUtils;
+
 import org.apache.cloudstack.acl.RoleType;
 import org.apache.cloudstack.affinity.AffinityGroupResponse;
 import org.apache.cloudstack.api.ACL;
@@ -110,6 +113,12 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG
     @Parameter(name = ApiConstants.NETWORK_IDS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = NetworkResponse.class, description = "list of network ids used by virtual machine. Can't be specified with ipToNetworkList parameter")
     private List<Long> networkIds;
 
+    @Parameter(name = ApiConstants.BOOT_TYPE, type = CommandType.STRING, required = false, description = "Guest VM Boot option either custom[UEFI] or default boot [BIOS]")
+    private String bootType;
+
+    @Parameter(name = ApiConstants.BOOT_MODE, type = CommandType.STRING, required = false, description = "Boot Mode [Legacy] or [Secure] Applicable when Boot Type Selected is UEFI, otherwise Legacy By default for BIOS")
+    private String bootMode;
+
     //DataDisk information
     @ACL
     @Parameter(name = ApiConstants.DISK_OFFERING_ID, type = CommandType.UUID, entityType = DiskOfferingResponse.class, description = "the ID of the disk offering for the virtual machine. If the template is of ISO format,"
@@ -244,6 +253,22 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG
         return domainId;
     }
 
+    private ApiConstants.BootType  getBootType() {
+
+        if (StringUtils.isNotBlank(bootType)) {
+            try {
+                String type = bootType.trim().toUpperCase();
+                return ApiConstants.BootType.valueOf(type);
+            } catch (IllegalArgumentException e) {
+                String errMesg = "Invalid bootType " + bootType + "Specified for vm " + getName()
+                        + " Valid values are: " + Arrays.toString(ApiConstants.BootType.values());
+                s_logger.warn(errMesg);
+                throw new InvalidParameterValueException(errMesg);
+            }
+        }
+        return null;
+    }
+
     public Map<String, String> getDetails() {
         Map<String, String> customparameterMap = new HashMap<String, String>();
         if (details != null && details.size() != 0) {
@@ -256,12 +281,35 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG
                 }
             }
         }
+        if(getBootType() != null){ // export to get
+            if(getBootType() == ApiConstants.BootType.UEFI) {
+                customparameterMap.put(getBootType().toString(), getBootMode().toString());
+            }
+        }
+
         if (rootdisksize != null && !customparameterMap.containsKey("rootdisksize")) {
             customparameterMap.put("rootdisksize", rootdisksize.toString());
         }
         return customparameterMap;
     }
 
+
+    public ApiConstants.BootMode getBootMode() {
+        if (StringUtils.isNotBlank(bootMode)) {
+            try {
+                String mode = bootMode.trim().toUpperCase();
+                return ApiConstants.BootMode.valueOf(mode);
+            } catch (IllegalArgumentException e) {
+                String errMesg = "Invalid bootMode " + bootMode + "Specified for vm " + getName()
+                        + " Valid values are:  "+ Arrays.toString(ApiConstants.BootMode.values());
+                s_logger.warn(errMesg);
+                throw new InvalidParameterValueException(errMesg);
+                }
+        }
+        return null;
+    }
+
+
     public Map<String, String> getVmOVFProperties() {
         Map<String, String> map = new HashMap<>();
         if (MapUtils.isNotEmpty(vmOvfProperties)) {
diff --git a/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java
index cd70af1..7b47f8a 100644
--- a/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java
+++ b/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java
@@ -244,6 +244,10 @@ public class HostResponse extends BaseResponse {
     @Param(description = "the admin that annotated this host", since = "4.11")
     private String username;
 
+    @SerializedName("ueficapability")
+    @Param(description = "true if the host has capability to support UEFI boot")
+    private Boolean uefiCapabilty;
+
     @Override
     public String getObjectId() {
         return this.getId();
@@ -499,6 +503,14 @@ public class HostResponse extends BaseResponse {
         detailsCopy.remove("username");
         detailsCopy.remove("password");
 
+        if(detailsCopy.containsKey(Host.HOST_UEFI_ENABLE)) {
+            this.setUefiCapabilty(Boolean.parseBoolean((String) detailsCopy.get(Host.HOST_UEFI_ENABLE)));
+            detailsCopy.remove(Host.HOST_UEFI_ENABLE);
+        } else {
+            this.setUefiCapabilty(new Boolean(false)); // in case of existing host which is not scanned for UEFI capability
+        }
+
+
         this.details = detailsCopy;
     }
 
@@ -668,4 +680,8 @@ public class HostResponse extends BaseResponse {
     public Boolean getHaHost() {
         return haHost;
     }
+
+    public void setUefiCapabilty(Boolean hostCapability) {
+        this.uefiCapabilty = hostCapability;
+    }
 }
diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java
index ca3ca87..b8b0189 100644
--- a/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java
+++ b/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java
@@ -298,6 +298,14 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co
     @Param(description = "OS type id of the vm", since = "4.4")
     private String osTypeId;
 
+    @SerializedName(ApiConstants.BOOT_MODE)
+    @Param(description = "Guest vm Boot Mode")
+    private String bootMode;
+
+    @SerializedName(ApiConstants.BOOT_TYPE)
+    @Param(description = "Guest vm Boot Type")
+    private String bootType;
+
     public UserVmResponse() {
         securityGroupList = new LinkedHashSet<SecurityGroupResponse>();
         nics = new LinkedHashSet<NicResponse>();
@@ -873,4 +881,13 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co
     public String getOsTypeId() {
         return osTypeId;
     }
+
+    public String getBootType() { return bootType; }
+
+    public void setBootType(String bootType) { this.bootType = bootType; }
+
+    public String getBootMode() { return bootMode; }
+
+    public void setBootMode(String bootMode) { this.bootMode = bootMode; }
+
 }
diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/cloud/entity/api/VirtualMachineEntity.java b/engine/api/src/main/java/org/apache/cloudstack/engine/cloud/entity/api/VirtualMachineEntity.java
index c004514..7b34077 100644
--- a/engine/api/src/main/java/org/apache/cloudstack/engine/cloud/entity/api/VirtualMachineEntity.java
+++ b/engine/api/src/main/java/org/apache/cloudstack/engine/cloud/entity/api/VirtualMachineEntity.java
@@ -171,4 +171,10 @@ public interface VirtualMachineEntity extends CloudStackEntity {
      * @param netowrk network to disconnect from
      */
     void disconnectFrom(NetworkEntity netowrk, short nicId);
+
+    /**
+     *  passing additional params of deployment associated with the virtual machine
+     */
+    void setParamsToEntity(Map<VirtualMachineProfile.Param, Object> params);
+
 }
diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
index 7765611..8817efb 100755
--- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -1064,6 +1064,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 }
 
                 final VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, template, offering, owner, params);
+                s_logger.info(" Uefi params " + "UefiFlag: " + params.get(VirtualMachineProfile.Param.UefiFlag)
+                        + " Boot Type: " + params.get(VirtualMachineProfile.Param.BootType)
+                        + " Boot Mode: " + params.get(VirtualMachineProfile.Param.BootMode)
+                );
                 DeployDestination dest = null;
                 try {
                     dest = _dpMgr.planDeployment(vmProfile, plan, avoids, planner);
diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java
index ef9c44a..567675a 100644
--- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java
+++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java
@@ -29,6 +29,7 @@ import org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMEntityDao;
 import org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMReservationDao;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
 import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.commons.collections.MapUtils;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
@@ -148,6 +149,15 @@ public class VMEntityManagerImpl implements VMEntityManager {
         VMInstanceVO vm = _vmDao.findByUuid(vmEntityVO.getUuid());
         VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm);
         vmProfile.setServiceOffering(_serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()));
+        if (MapUtils.isNotEmpty(vmEntityVO.getDetails()) &&
+                vmEntityVO.getDetails().containsKey(VirtualMachineProfile.Param.UefiFlag.getName()) &&
+                "yes".equalsIgnoreCase(vmEntityVO.getDetails().get(VirtualMachineProfile.Param.UefiFlag.getName())))
+        {
+            Map<String, String> details = vmEntityVO.getDetails();
+            vmProfile.getParameters().put(VirtualMachineProfile.Param.BootType, details.get(VirtualMachineProfile.Param.BootType.getName()));
+            vmProfile.getParameters().put(VirtualMachineProfile.Param.BootMode, details.get(VirtualMachineProfile.Param.BootMode.getName()));
+            vmProfile.getParameters().put(VirtualMachineProfile.Param.UefiFlag, details.get(VirtualMachineProfile.Param.UefiFlag.getName()));
+        }
         DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), vm.getPodIdToDeployIn(), null, null, null, null);
         if (planToDeploy != null && planToDeploy.getDataCenterId() != 0) {
             plan =
diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/cloud/entity/api/VirtualMachineEntityImpl.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/cloud/entity/api/VirtualMachineEntityImpl.java
index 598e619..3e5f910 100644
--- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/cloud/entity/api/VirtualMachineEntityImpl.java
+++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/cloud/entity/api/VirtualMachineEntityImpl.java
@@ -20,9 +20,11 @@ import java.lang.reflect.Method;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import java.util.HashMap;
 
 import javax.inject.Inject;
 
+import org.apache.commons.collections.MapUtils;
 import org.springframework.stereotype.Component;
 import org.apache.cloudstack.engine.cloud.entity.api.db.VMEntityVO;
 
@@ -269,4 +271,22 @@ public class VirtualMachineEntityImpl implements VirtualMachineEntity {
 
     }
 
+    @Override
+    public void setParamsToEntity(Map<VirtualMachineProfile.Param, Object> map) {
+        if (MapUtils.isNotEmpty(map)) {
+            if (this.vmEntityVO != null) {
+                Map<String, String> details = this.vmEntityVO.getDetails();
+                if (details == null) {
+                    details = new HashMap<String, String>();
+                }
+                for (Map.Entry<VirtualMachineProfile.Param, Object> entry : map.entrySet()) {
+                    if (null != entry && null != entry.getValue() && null != entry.getKey()) {
+                        details.put(entry.getKey().getName(), entry.getValue().toString());
+                    }
+                }
+                this.vmEntityVO.setDetails(details);
+            }
+        }
+
+    }
 }
diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java
index 34b8963..ced19ce 100644
--- a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java
+++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java
@@ -112,5 +112,7 @@ public interface HostDao extends GenericDao<HostVO, Long>, StateDao<Status, Stat
 
     List<HostVO> listAllHostsUpByZoneAndHypervisor(long zoneId, HypervisorType hypervisorType);
 
+    List<HostVO> listByHostCapability(Host.Type type, Long clusterId, Long podId, long dcId, String hostCapabilty);
+
     List<HostVO> listByClusterAndHypervisorType(long clusterId, HypervisorType hypervisorType);
 }
diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
index 20d817c..ec4573f 100644
--- a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
+++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
@@ -43,6 +43,7 @@ import com.cloud.dc.dao.ClusterDao;
 import com.cloud.gpu.dao.HostGpuGroupsDao;
 import com.cloud.gpu.dao.VGPUTypesDao;
 import com.cloud.host.Host;
+import com.cloud.host.DetailVO;
 import com.cloud.host.Host.Type;
 import com.cloud.host.HostTagVO;
 import com.cloud.host.HostVO;
@@ -1222,6 +1223,39 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
     }
 
     @Override
+    public List<HostVO> listByHostCapability(Type type, Long clusterId, Long podId, long dcId, String hostCapabilty) {
+        SearchBuilder<DetailVO> hostCapabilitySearch = _detailsDao.createSearchBuilder();
+        DetailVO tagEntity = hostCapabilitySearch.entity();
+        hostCapabilitySearch.and("capability", tagEntity.getName(), SearchCriteria.Op.EQ);
+        hostCapabilitySearch.and("value", tagEntity.getValue(), SearchCriteria.Op.EQ);
+
+        SearchBuilder<HostVO> hostSearch = createSearchBuilder();
+        HostVO entity = hostSearch.entity();
+        hostSearch.and("type", entity.getType(), SearchCriteria.Op.EQ);
+        hostSearch.and("pod", entity.getPodId(), SearchCriteria.Op.EQ);
+        hostSearch.and("dc", entity.getDataCenterId(), SearchCriteria.Op.EQ);
+        hostSearch.and("cluster", entity.getClusterId(), SearchCriteria.Op.EQ);
+        hostSearch.and("status", entity.getStatus(), SearchCriteria.Op.EQ);
+        hostSearch.and("resourceState", entity.getResourceState(), SearchCriteria.Op.EQ);
+        hostSearch.join("hostCapabilitySearch", hostCapabilitySearch, entity.getId(), tagEntity.getHostId(), JoinBuilder.JoinType.INNER);
+
+        SearchCriteria<HostVO> sc = hostSearch.create();
+        sc.setJoinParameters("hostCapabilitySearch", "value", Boolean.toString(true));
+        sc.setJoinParameters("hostCapabilitySearch", "capability", hostCapabilty);
+        sc.setParameters("type", type.toString());
+        if (podId != null) {
+            sc.setParameters("pod", podId);
+        }
+        if (clusterId != null) {
+            sc.setParameters("cluster", clusterId);
+        }
+        sc.setParameters("dc", dcId);
+        sc.setParameters("status", Status.Up.toString());
+        sc.setParameters("resourceState", ResourceState.Enabled.toString());
+
+        return listBy(sc);
+    }
+
     public List<HostVO> listByClusterAndHypervisorType(long clusterId, HypervisorType hypervisorType) {
         SearchCriteria<HostVO> sc = ClusterHypervisorSearch.create();
         sc.setParameters("clusterId", clusterId);
diff --git a/plugins/deployment-planners/implicit-dedication/src/test/java/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java b/plugins/deployment-planners/implicit-dedication/src/test/java/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java
index 79cb1b4..1a3aed0 100644
--- a/plugins/deployment-planners/implicit-dedication/src/test/java/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java
+++ b/plugins/deployment-planners/implicit-dedication/src/test/java/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java
@@ -73,6 +73,7 @@ import com.cloud.exception.InsufficientServerCapacityException;
 import com.cloud.gpu.dao.HostGpuGroupsDao;
 import com.cloud.host.HostVO;
 import com.cloud.host.dao.HostDao;
+import com.cloud.host.dao.HostDetailsDao;
 import com.cloud.host.dao.HostTagsDao;
 import com.cloud.resource.ResourceManager;
 import com.cloud.service.ServiceOfferingVO;
@@ -574,6 +575,10 @@ public class ImplicitPlannerTest {
         }
 
         @Bean
+        public HostDetailsDao hostDetailsDao() { return Mockito.mock(HostDetailsDao.class); }
+
+
+        @Bean
         public ClusterDetailsDao clusterDetailsDao() {
             return Mockito.mock(ClusterDetailsDao.class);
         }
diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
index 1be6785..fd9075e 100644
--- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
+++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
@@ -224,6 +224,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
     private String _dcId;
     private String _pod;
     private String _clusterId;
+    private final Properties _uefiProperties = new Properties();
 
     private long _hvVersion;
     private Duration _timeout;
@@ -497,7 +498,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
     public StorageSubsystemCommandHandler getStorageHandler() {
         return storageHandler;
     }
-
     private static final class KeyValueInterpreter extends OutputInterpreter {
         private final Map<String, String> map = new HashMap<String, String>();
 
@@ -628,6 +628,11 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
         if (!success) {
             return false;
         }
+        try {
+            loadUefiProperties();
+        } catch (FileNotFoundException e) {
+            s_logger.error("uefi properties file not found due to: " + e.getLocalizedMessage());
+        }
 
         _storage = new JavaStorageLayer();
         _storage.configure("StorageLayer", params);
@@ -1150,6 +1155,31 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
         return true;
     }
 
+    private void loadUefiProperties() throws FileNotFoundException {
+
+        if (_uefiProperties != null && _uefiProperties.getProperty("guest.loader.legacy") != null) {
+            return;
+        }
+        final File file = PropertiesUtil.findConfigFile("uefi.properties");
+        if (file == null) {
+            throw new FileNotFoundException("Unable to find file uefi.properties.");
+        }
+
+        s_logger.info("uefi.properties file found at " + file.getAbsolutePath());
+        try {
+            PropertiesUtil.loadFromFile(_uefiProperties, file);
+            s_logger.info("guest.nvram.template.legacy = " + _uefiProperties.getProperty("guest.nvram.template.legacy"));
+            s_logger.info("guest.loader.legacy = " + _uefiProperties.getProperty("guest.loader.legacy"));
+            s_logger.info("guest.nvram.template.secure = " + _uefiProperties.getProperty("guest.nvram.template.secure"));
+            s_logger.info("guest.loader.secure =" + _uefiProperties.getProperty("guest.loader.secure"));
+            s_logger.info("guest.nvram.path = " + _uefiProperties.getProperty("guest.nvram.path"));
+        } catch (final FileNotFoundException ex) {
+            throw new CloudRuntimeException("Cannot find the file: " + file.getAbsolutePath(), ex);
+        } catch (final IOException ex) {
+            throw new CloudRuntimeException("IOException in reading " + file.getAbsolutePath(), ex);
+        }
+    }
+
     protected void configureDiskActivityChecks(final Map<String, Object> params) {
         _diskActivityCheckEnabled = Boolean.parseBoolean((String)params.get("vm.diskactivity.checkenabled"));
         if (_diskActivityCheckEnabled) {
@@ -2106,6 +2136,18 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
         vm.setDomDescription(vmTO.getOs());
         vm.setPlatformEmulator(vmTO.getPlatformEmulator());
 
+        Map<String, String> customParams = vmTO.getDetails();
+        boolean isUefiEnabled = false;
+        boolean isSecureBoot = false;
+        String bootMode =null;
+        if (MapUtils.isNotEmpty(customParams) && customParams.containsKey(GuestDef.BootType.UEFI.toString())) {
+            isUefiEnabled = true;
+            bootMode = customParams.get(GuestDef.BootType.UEFI.toString());
+            if (StringUtils.isNotBlank(bootMode) && "secure".equalsIgnoreCase(bootMode)) {
+                isSecureBoot = true;
+            }
+        }
+
         Map<String, String> extraConfig = vmTO.getExtraConfig();
         if (dpdkSupport && (!extraConfig.containsKey(DpdkHelper.DPDK_NUMA) || !extraConfig.containsKey(DpdkHelper.DPDK_HUGE_PAGES))) {
             s_logger.info("DPDK is enabled but it needs extra configurations for CPU NUMA and Huge Pages for VM deployment");
@@ -2125,11 +2167,44 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
         }
         guest.setGuestArch(_guestCpuArch != null ? _guestCpuArch : vmTO.getArch());
         guest.setMachineType(_guestCpuArch != null && _guestCpuArch.equals("aarch64") ? "virt" : "pc");
+        guest.setBootType(GuestDef.BootType.BIOS);
+        if (MapUtils.isNotEmpty(customParams) && customParams.containsKey(GuestDef.BootType.UEFI.toString())) {
+            guest.setBootType(GuestDef.BootType.UEFI);
+            guest.setBootMode(GuestDef.BootMode.LEGACY);
+            if (StringUtils.isNotBlank(customParams.get(GuestDef.BootType.UEFI.toString())) && "secure".equalsIgnoreCase(customParams.get(GuestDef.BootType.UEFI.toString()))) {
+                guest.setMachineType("q35");
+                guest.setBootMode(GuestDef.BootMode.SECURE); // setting to secure mode
+            }
+        }
         guest.setUuid(uuid);
         guest.setBootOrder(GuestDef.BootOrder.CDROM);
         guest.setBootOrder(GuestDef.BootOrder.HARDISK);
 
-        vm.addComp(guest);
+        if (isUefiEnabled) {
+            if (_uefiProperties.getProperty(GuestDef.GUEST_LOADER_SECURE) != null && "secure".equalsIgnoreCase(bootMode)) {
+                guest.setLoader(_uefiProperties.getProperty(GuestDef.GUEST_LOADER_SECURE));
+            }
+
+            if (_uefiProperties.getProperty(GuestDef.GUEST_LOADER_LEGACY) != null && "legacy".equalsIgnoreCase(bootMode)) {
+                guest.setLoader(_uefiProperties.getProperty(GuestDef.GUEST_LOADER_LEGACY));
+            }
+
+            if (_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_PATH) != null) {
+                guest.setNvram(_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_PATH));
+            }
+
+            if (isSecureBoot) {
+                if (_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_SECURE) != null && "secure".equalsIgnoreCase(bootMode)) {
+                    guest.setNvramTemplate(_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_SECURE));
+                }
+            } else {
+                if (_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_LEGACY) != null) {
+                    guest.setNvramTemplate(_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_LEGACY));
+                }
+            }
+        }
+
+            vm.addComp(guest);
 
         final GuestResourceDef grd = new GuestResourceDef();
 
@@ -2189,6 +2264,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
         features.addFeatures("pae");
         features.addFeatures("apic");
         features.addFeatures("acpi");
+        if (isUefiEnabled && isSecureMode(customParams.get(GuestDef.BootType.UEFI.toString()))) {
+            features.addFeatures("smm");
+        }
 
         //KVM hyperv enlightenment features based on OS Type
         enlightenWindowsVm(vmTO, features);
@@ -2329,7 +2407,10 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
     }
 
     public void createVbd(final Connect conn, final VirtualMachineTO vmSpec, final String vmName, final LibvirtVMDef vm) throws InternalErrorException, LibvirtException, URISyntaxException {
+        final Map<String, String> details = vmSpec.getDetails();
         final List<DiskTO> disks = Arrays.asList(vmSpec.getDisks());
+        boolean isSecureBoot = false;
+        boolean isWindowsTemplate = false;
         Collections.sort(disks, new Comparator<DiskTO>() {
             @Override
             public int compare(final DiskTO arg0, final DiskTO arg1) {
@@ -2337,6 +2418,12 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
             }
         });
 
+        if (MapUtils.isNotEmpty(details) && details.containsKey(GuestDef.BootType.UEFI.toString())) {
+            isSecureBoot = isSecureMode(details.get(GuestDef.BootType.UEFI.toString()));
+        }
+        if (vmSpec.getOs().toLowerCase().contains("window")) {
+            isWindowsTemplate =true;
+        }
         for (final DiskTO volume : disks) {
             KVMPhysicalDisk physicalDisk = null;
             KVMStoragePool pool = null;
@@ -2397,8 +2484,12 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
             int devId = volume.getDiskSeq().intValue();
             if (volume.getType() == Volume.Type.ISO) {
                 if (volPath == null) {
-                    /* Add iso as placeholder */
-                    disk.defISODisk(null, devId);
+                    if (isSecureBoot) {
+                        disk.defISODisk(null, devId,isSecureBoot,isWindowsTemplate);
+                    } else {
+                        /* Add iso as placeholder */
+                        disk.defISODisk(null, devId);
+                    }
                 } else {
                     disk.defISODisk(volPath, devId);
                 }
@@ -2436,7 +2527,11 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
                     if (volume.getType() == Volume.Type.DATADISK) {
                         disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusTypeData, DiskDef.DiskFmtType.QCOW2);
                     } else {
-                        disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusType, DiskDef.DiskFmtType.QCOW2);
+                        if (isSecureBoot) {
+                            disk.defFileBasedDisk(physicalDisk.getPath(), devId, DiskDef.DiskFmtType.QCOW2, isWindowsTemplate);
+                        } else {
+                            disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusType, DiskDef.DiskFmtType.QCOW2);
+                        }
                     }
 
                 }
@@ -4052,4 +4147,12 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
         }
         return true;
     }
+
+    public boolean isSecureMode(String bootMode) {
+        if (StringUtils.isNotBlank(bootMode) && "secure".equalsIgnoreCase(bootMode)) {
+            return true;
+        }
+
+        return false;
+    }
 }
diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
index bfbb4d5..e2d506c 100644
--- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
+++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
@@ -57,7 +57,39 @@ public class LibvirtVMDef {
             }
         }
 
+        enum BootType {
+            UEFI("UEFI"), BIOS("BIOS");
+
+            String _type;
+
+            BootType(String type) {
+                _type = type;
+            }
+
+            @Override
+            public String toString() {
+                return _type;
+            }
+        }
+
+        enum BootMode {
+            LEGACY("LEGACY"), SECURE("SECURE");
+
+            String _mode;
+
+            BootMode(String mode) {
+                _mode = mode;
+            }
+
+            @Override
+            public String toString() {
+                return _mode;
+            }
+        }
+
         private GuestType _type;
+        private BootType _boottype;
+        private BootMode _bootmode;
         private String _arch;
         private String _loader;
         private String _kernel;
@@ -67,6 +99,14 @@ public class LibvirtVMDef {
         private String _uuid;
         private final List<BootOrder> _bootdevs = new ArrayList<BootOrder>();
         private String _machine;
+        private String _nvram;
+        private String _nvramTemplate;
+
+        public static final String GUEST_LOADER_SECURE = "guest.loader.secure";
+        public static final String GUEST_LOADER_LEGACY = "guest.loader.legacy";
+        public static final String GUEST_NVRAM_PATH = "guest.nvram.path";
+        public static final String GUEST_NVRAM_TEMPLATE_SECURE = "guest.nvram.template.secure";
+        public static final String GUEST_NVRAM_TEMPLATE_LEGACY = "guest.nvram.template.legacy";
 
         public void setGuestType(GuestType type) {
             _type = type;
@@ -76,6 +116,10 @@ public class LibvirtVMDef {
             return _type;
         }
 
+        public void setNvram(String nvram) { _nvram = nvram; }
+
+        public void setNvramTemplate(String nvramTemplate) { _nvramTemplate = nvramTemplate; }
+
         public void setGuestArch(String arch) {
             _arch = arch;
         }
@@ -103,6 +147,22 @@ public class LibvirtVMDef {
             _uuid = uuid;
         }
 
+        public BootType getBootType() {
+            return _boottype;
+        }
+
+        public void setBootType(BootType boottype) {
+            this._boottype = boottype;
+        }
+
+        public BootMode getBootMode() {
+            return _bootmode;
+        }
+
+        public void setBootMode(BootMode bootmode) {
+            this._bootmode = bootmode;
+        }
+
         @Override
         public String toString() {
             if (_type == GuestType.KVM) {
@@ -128,6 +188,24 @@ public class LibvirtVMDef {
                 if (_arch != null && _arch.equals("aarch64")) {
                     guestDef.append("<loader readonly='yes' type='pflash'>/usr/share/AAVMF/AAVMF_CODE.fd</loader>\n");
                 }
+                if (_loader != null) {
+                    if (_bootmode == BootMode.LEGACY) {
+                        guestDef.append("<loader readonly='yes' secure='no' type='pflash'>" + _loader + "</loader>\n");
+                    } else if (_bootmode == BootMode.SECURE) {
+                        guestDef.append("<loader readonly='yes' secure='yes' type='pflash'>" + _loader + "</loader>\n");
+                    }
+                }
+                if (_nvram != null) {
+                    guestDef.append("<nvram ");
+                    if (_nvramTemplate != null) {
+                        guestDef.append("template='" + _nvramTemplate + "'>");
+                    } else {
+                        guestDef.append(">");
+                    }
+
+                    guestDef.append(_nvram);
+                    guestDef.append(_uuid + ".fd</nvram>");
+                }
                 if (!_bootdevs.isEmpty()) {
                     for (BootOrder bo : _bootdevs) {
                         guestDef.append("<boot dev='" + bo + "'/>\n");
@@ -276,7 +354,11 @@ public class LibvirtVMDef {
             StringBuilder feaBuilder = new StringBuilder();
             feaBuilder.append("<features>\n");
             for (String feature : _features) {
-                feaBuilder.append("<" + feature + "/>\n");
+                if (feature.equalsIgnoreCase("smm")) {
+                    feaBuilder.append("<" + feature + " state=\'on\' " + "/>\n");
+                } else {
+                    feaBuilder.append("<" + feature + "/>\n");
+                }
             }
             if (hyperVEnlightenmentFeatureDef != null) {
                 String hpervF = hyperVEnlightenmentFeatureDef.toString();
@@ -508,7 +590,7 @@ public class LibvirtVMDef {
         }
 
         public enum DiskBus {
-            IDE("ide"), SCSI("scsi"), VIRTIO("virtio"), XEN("xen"), USB("usb"), UML("uml"), FDC("fdc");
+            IDE("ide"), SCSI("scsi"), VIRTIO("virtio"), XEN("xen"), USB("usb"), UML("uml"), FDC("fdc"), SATA("sata");
             String _bus;
 
             DiskBus(String bus) {
@@ -633,13 +715,17 @@ public class LibvirtVMDef {
                 return "sd" + getDevLabelSuffix(devId);
             } else if (bus == DiskBus.VIRTIO) {
                 return "vd" + getDevLabelSuffix(devId);
+            } else if (bus == DiskBus.SATA){
+                if (!forIso) {
+                    return "sda";
+                }
             }
             if (forIso) {
                 devId --;
             } else if(devId >= 2) {
                 devId += 2;
             }
-            return "hd" + getDevLabelSuffix(devId);
+            return (DiskBus.SATA == bus) ? "sdb" : "hd" + getDevLabelSuffix(devId);
 
         }
 
@@ -671,6 +757,23 @@ public class LibvirtVMDef {
 
         }
 
+        public void defFileBasedDisk(String filePath, int devId, DiskFmtType diskFmtType,boolean isWindowsOS) {
+
+            _diskType = DiskType.FILE;
+            _deviceType = DeviceType.DISK;
+            _diskCacheMode = DiskCacheMode.NONE;
+            _sourcePath = filePath;
+            _diskFmtType = diskFmtType;
+
+            if (isWindowsOS) {
+                _diskLabel = getDevLabel(devId, DiskBus.SATA, false); // Windows Secure VM
+                _bus = DiskBus.SATA;
+            } else {
+                _diskLabel = getDevLabel(devId, DiskBus.VIRTIO, false); // Linux Secure VM
+                _bus = DiskBus.VIRTIO;
+            }
+        }
+
         public void defISODisk(String volPath) {
             _diskType = DiskType.FILE;
             _deviceType = DeviceType.CDROM;
@@ -695,6 +798,26 @@ public class LibvirtVMDef {
             }
         }
 
+        public void defISODisk(String volPath, Integer devId,boolean isSecure, boolean isWindowOs) {
+            if (!isSecure) {
+                defISODisk(volPath, devId);
+            } else {
+                _diskType = DiskType.FILE;
+                _deviceType = DeviceType.CDROM;
+                _sourcePath = volPath;
+                if (isWindowOs) {
+                    _diskLabel = getDevLabel(devId, DiskBus.SATA, true);
+                    _bus = DiskBus.SATA;
+                } else {
+                    _diskLabel = getDevLabel(devId, DiskBus.SCSI, true);
+                    _bus = DiskBus.SCSI;
+                }
+                _diskFmtType = DiskFmtType.RAW;
+                _diskCacheMode = DiskCacheMode.NONE;
+
+            }
+        }
+
         public void defBlockBasedDisk(String diskName, int devId, DiskBus bus) {
             _diskType = DiskType.BLOCK;
             _deviceType = DeviceType.DISK;
diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/guru/VMwareGuru.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/guru/VMwareGuru.java
index 39c1e66..4e8acad 100644
--- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/guru/VMwareGuru.java
+++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/guru/VMwareGuru.java
@@ -294,6 +294,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
             }
         }
 
+        details.put(VmDetailConstants.BOOT_MODE, to.getBootType());
         String diskDeviceType = details.get(VmDetailConstants.ROOT_DISK_CONTROLLER);
         if (userVm) {
             if (diskDeviceType == null) {
diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java
index 4b2f830..1102f9d 100644
--- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java
+++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java
@@ -45,6 +45,7 @@ import com.cloud.exception.DiscoveredWithErrorException;
 import com.cloud.exception.DiscoveryException;
 import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.exception.ResourceInUseException;
+import com.cloud.host.Host;
 import com.cloud.host.HostVO;
 import com.cloud.hypervisor.Hypervisor;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
@@ -367,6 +368,10 @@ public class VmwareServerDiscoverer extends DiscovererBase implements Discoverer
                 details.put("url", hostMo.getHostName());
                 details.put("username", username);
                 details.put("password", password);
+                boolean uefiLegacySupported = hostMo.isUefiLegacySupported();
+                if (uefiLegacySupported) {
+                    details.put(Host.HOST_UEFI_ENABLE, "true");
+                }
                 String guid = morHost.getType() + ":" + morHost.getValue() + "@" + url.getHost();
                 details.put("guid", guid);
 
diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
index 7624f95..5a1459d 100644
--- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
+++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
@@ -318,6 +318,7 @@ import com.vmware.vim25.VirtualEthernetCardNetworkBackingInfo;
 import com.vmware.vim25.VirtualEthernetCardOpaqueNetworkBackingInfo;
 import com.vmware.vim25.VirtualIDEController;
 import com.vmware.vim25.VirtualMachineConfigSpec;
+import com.vmware.vim25.VirtualMachineBootOptions;
 import com.vmware.vim25.VirtualMachineFileInfo;
 import com.vmware.vim25.VirtualMachineFileLayoutEx;
 import com.vmware.vim25.VirtualMachineFileLayoutExFileInfo;
@@ -1723,6 +1724,11 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
         String dataDiskController = vmSpec.getDetails().get(VmDetailConstants.DATA_DISK_CONTROLLER);
         String rootDiskController = vmSpec.getDetails().get(VmDetailConstants.ROOT_DISK_CONTROLLER);
         DiskTO rootDiskTO = null;
+        String bootMode = ApiConstants.BootType.BIOS.toString();
+        if (vmSpec.getDetails().containsKey(VmDetailConstants.BOOT_MODE)) {
+            bootMode = vmSpec.getDetails().get(VmDetailConstants.BOOT_MODE);
+        }
+
         // If root disk controller is scsi, then data disk controller would also be scsi instead of using 'osdefault'
         // This helps avoid mix of different scsi subtype controllers in instance.
         if (DiskControllerType.osdefault == DiskControllerType.getType(dataDiskController) && DiskControllerType.lsilogic == DiskControllerType.getType(rootDiskController)) {
@@ -2280,6 +2286,16 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                 }
             }
 
+            if (!bootMode.equalsIgnoreCase(ApiConstants.BootType.BIOS.toString())) {
+                vmConfigSpec.setFirmware("efi");
+                if (vmSpec.getDetails().containsKey(ApiConstants.BootType.UEFI.toString()) && "secure".equalsIgnoreCase(vmSpec.getDetails().get(ApiConstants.BootType.UEFI.toString()))) {
+                    VirtualMachineBootOptions bootOptions = new VirtualMachineBootOptions();
+                    bootOptions.setEfiSecureBootEnabled(true);
+                    vmConfigSpec.setBootOptions(bootOptions);
+                }
+            }
+
+
             //
             // Configure VM
             //
@@ -2772,6 +2788,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
     private static void configCustomExtraOption(List<OptionValue> extraOptions, VirtualMachineTO vmSpec) {
         // we no longer to validation anymore
         for (Map.Entry<String, String> entry : vmSpec.getDetails().entrySet()) {
+            if (entry.getKey().equalsIgnoreCase(VmDetailConstants.BOOT_MODE)) {
+                continue;
+            }
             OptionValue newVal = new OptionValue();
             newVal.setKey(entry.getKey());
             newVal.setValue(entry.getValue());
diff --git a/server/src/main/java/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java b/server/src/main/java/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java
index 186c654..aab9510 100644
--- a/server/src/main/java/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java
+++ b/server/src/main/java/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java
@@ -61,6 +61,9 @@ import com.cloud.utils.component.AdapterBase;
 import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.VirtualMachineProfile;
 import com.cloud.vm.dao.VMInstanceDao;
+import com.cloud.vm.UserVmDetailVO;
+import com.cloud.vm.dao.UserVmDetailsDao;
+
 
 /**
  * An allocator that tries to find a fit on a computing host.  This allocator does not care whether or not the host supports routing.
@@ -92,6 +95,8 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
     CapacityManager _capacityMgr;
     @Inject
     CapacityDao _capacityDao;
+    @Inject
+    UserVmDetailsDao _userVmDetailsDao;
 
     boolean _checkHvm = true;
     protected String _allocationAlgorithm = "random";
@@ -112,6 +117,16 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
         VMTemplateVO template = (VMTemplateVO)vmProfile.getTemplate();
         Account account = vmProfile.getOwner();
 
+        boolean isVMDeployedWithUefi = false;
+        UserVmDetailVO userVmDetailVO = _userVmDetailsDao.findDetail(vmProfile.getId(), "UEFI");
+        if(userVmDetailVO != null){
+            if ("secure".equalsIgnoreCase(userVmDetailVO.getValue()) || "legacy".equalsIgnoreCase(userVmDetailVO.getValue())) {
+                isVMDeployedWithUefi = true;
+            }
+        }
+        s_logger.info(" Guest VM is requested with Cusotm[UEFI] Boot Type "+ isVMDeployedWithUefi);
+
+
         if (type == Host.Type.Storage) {
             // FirstFitAllocator should be used for user VMs only since it won't care whether the host is capable of routing or not
             return new ArrayList<Host>();
@@ -123,11 +138,20 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
 
         String hostTagOnOffering = offering.getHostTag();
         String hostTagOnTemplate = template.getTemplateTag();
+        String hostTagUefi = "UEFI";
 
         boolean hasSvcOfferingTag = hostTagOnOffering != null ? true : false;
         boolean hasTemplateTag = hostTagOnTemplate != null ? true : false;
 
         List<HostVO> clusterHosts = new ArrayList<HostVO>();
+        List<HostVO> hostsMatchingUefiTag = new ArrayList<HostVO>();
+        if(isVMDeployedWithUefi){
+            hostsMatchingUefiTag = _hostDao.listByHostCapability(type, clusterId, podId, dcId, Host.HOST_UEFI_ENABLE);
+            if (s_logger.isDebugEnabled()) {
+                s_logger.debug("Hosts with tag '" + hostTagUefi + "' are:" + hostsMatchingUefiTag);
+            }
+        }
+
 
         String haVmTag = (String)vmProfile.getParameter(VirtualMachineProfile.Param.HaTag);
         if (haVmTag != null) {
@@ -175,6 +199,10 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
             }
         }
 
+        if (isVMDeployedWithUefi) {
+            clusterHosts.retainAll(hostsMatchingUefiTag);
+        }
+
         // add all hosts that we are not considering to the avoid list
         List<HostVO> allhostsInCluster = _hostDao.listAllUpAndEnabledNonHAHosts(type, clusterId, podId, dcId, null);
         allhostsInCluster.removeAll(clusterHosts);
diff --git a/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java
index a612829..21c6786 100644
--- a/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java
+++ b/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java
@@ -321,6 +321,15 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
                         (UserVmManager.DisplayVMOVFProperties.value() && userVmDetailVO.getName().startsWith(ApiConstants.OVF_PROPERTIES))) {
                     resourceDetails.put(userVmDetailVO.getName(), userVmDetailVO.getValue());
                 }
+                if ((ApiConstants.BootType.UEFI.toString()).equalsIgnoreCase(userVmDetailVO.getName())) {
+                    userVmResponse.setBootType("Uefi");
+                    userVmResponse.setBootMode(userVmDetailVO.getValue().toLowerCase());
+
+                }
+            }
+            if (vmDetails.size() == 0) {
+                userVmResponse.setBootType("Bios");
+                userVmResponse.setBootMode("legacy");
             }
             // Remove blacklisted settings if user is not admin
             if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) {
diff --git a/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java
index 1315cdf..0c1aab3 100644
--- a/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java
+++ b/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java
@@ -30,10 +30,12 @@ import java.util.TreeSet;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
+import com.cloud.utils.StringUtils;
 import com.cloud.utils.db.Filter;
 import com.cloud.utils.fsm.StateMachine2;
 
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
 import org.apache.log4j.Logger;
 import org.apache.cloudstack.affinity.AffinityGroupProcessor;
 import org.apache.cloudstack.affinity.AffinityGroupService;
@@ -271,6 +273,7 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> {
         }
 
         String haVmTag = (String)vmProfile.getParameter(VirtualMachineProfile.Param.HaTag);
+        String uefiFlag = (String)vmProfile.getParameter(VirtualMachineProfile.Param.UefiFlag);
 
         if (plan.getHostId() != null && haVmTag == null) {
             Long hostIdSpecified = plan.getHostId();
@@ -278,6 +281,14 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> {
                 s_logger.debug("DeploymentPlan has host_id specified, choosing this host and making no checks on this host: " + hostIdSpecified);
             }
             HostVO host = _hostDao.findById(hostIdSpecified);
+            if (host != null && StringUtils.isNotBlank(uefiFlag) && "yes".equalsIgnoreCase(uefiFlag)) {
+                _hostDao.loadDetails(host);
+                if (MapUtils.isNotEmpty(host.getDetails()) && host.getDetails().containsKey(Host.HOST_UEFI_ENABLE) && "false".equalsIgnoreCase(host.getDetails().get(Host.HOST_UEFI_ENABLE))) {
+                    s_logger.debug("Cannot deploy to specified host as host does n't support uefi vm deployment, returning.");
+                    return null;
+
+                }
+            }
             if (host == null) {
                 s_logger.debug("The specified host cannot be found");
             } else if (avoids.shouldAvoid(host)) {
diff --git a/server/src/main/java/com/cloud/deploy/FirstFitPlanner.java b/server/src/main/java/com/cloud/deploy/FirstFitPlanner.java
index 5760e24..88f6b95 100644
--- a/server/src/main/java/com/cloud/deploy/FirstFitPlanner.java
+++ b/server/src/main/java/com/cloud/deploy/FirstFitPlanner.java
@@ -68,12 +68,15 @@ import com.cloud.vm.VirtualMachineProfile;
 import com.cloud.vm.dao.UserVmDao;
 import com.cloud.vm.dao.UserVmDetailsDao;
 import com.cloud.vm.dao.VMInstanceDao;
+import com.cloud.host.dao.HostDetailsDao;
 
 public class FirstFitPlanner extends AdapterBase implements DeploymentClusterPlanner, Configurable, DeploymentPlanner {
     private static final Logger s_logger = Logger.getLogger(FirstFitPlanner.class);
     @Inject
     protected HostDao hostDao;
     @Inject
+    protected HostDetailsDao hostDetailsDao;
+    @Inject
     protected DataCenterDao dcDao;
     @Inject
     protected HostPodDao podDao;
@@ -187,8 +190,16 @@ public class FirstFitPlanner extends AdapterBase implements DeploymentClusterPla
 
         if (clusterList != null && !clusterList.isEmpty()) {
             ServiceOffering offering = vmProfile.getServiceOffering();
+            boolean nonUefiVMDeploy =false;
+            if (vmProfile.getParameters().containsKey(VirtualMachineProfile.Param.BootType)) {
+                if (vmProfile.getParameters().get(VirtualMachineProfile.Param.BootType).toString().equalsIgnoreCase("BIOS")) {
+                    nonUefiVMDeploy = true;
+
+                }
+
+            }
             // In case of non-GPU VMs, protect GPU enabled Hosts and prefer VM deployment on non-GPU Hosts.
-            if ((serviceOfferingDetailsDao.findDetail(offering.getId(), GPU.Keys.vgpuType.toString()) == null) && !(hostGpuGroupsDao.listHostIds().isEmpty())) {
+            if (((serviceOfferingDetailsDao.findDetail(offering.getId(), GPU.Keys.vgpuType.toString()) == null) && !(hostGpuGroupsDao.listHostIds().isEmpty())) || nonUefiVMDeploy) {
                 int requiredCpu = offering.getCpu() * offering.getSpeed();
                 long requiredRam = offering.getRamSize() * 1024L * 1024L;
                 reorderClustersBasedOnImplicitTags(clusterList, requiredCpu, requiredRam);
@@ -205,7 +216,8 @@ public class FirstFitPlanner extends AdapterBase implements DeploymentClusterPla
             List<Long> hostList = capacityDao.listHostsWithEnoughCapacity(requiredCpu, requiredRam, clusterId, Host.Type.Routing.toString());
             if (!hostList.isEmpty() && implicitHostTags.length > 0) {
                 uniqueTags = new Long(hostTagsDao.getDistinctImplicitHostTags(hostList, implicitHostTags).size());
-                }
+                uniqueTags = uniqueTags + getHostsByCapability(hostList, Host.HOST_UEFI_ENABLE);
+            }
                 UniqueTagsInClusterMap.put(clusterId, uniqueTags);
             }
             Collections.sort(clusterList, new Comparator<Long>() {
@@ -218,6 +230,19 @@ public class FirstFitPlanner extends AdapterBase implements DeploymentClusterPla
             });
     }
 
+    private Long getHostsByCapability(List<Long> hostList, String hostCapability) {
+        for (Long host : hostList) { //TODO: Fix this in single query instead of polling request for each Host
+            Map<String, String> details = hostDetailsDao.findDetails(host);
+            if (details.containsKey(Host.HOST_UEFI_ENABLE)) {
+                if (details.get(Host.HOST_UEFI_ENABLE).equalsIgnoreCase("Yes")) {
+                    return new Long(1);
+                }
+
+            }
+        }
+        return new Long(0);
+    }
+
     private List<Long> scanPodsForDestination(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid) {
 
         ServiceOffering offering = vmProfile.getServiceOffering();
diff --git a/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java
index 9e55506..0c3263a 100644
--- a/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java
+++ b/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java
@@ -22,8 +22,6 @@ import java.util.UUID;
 
 import javax.inject.Inject;
 
-import com.cloud.network.dao.NetworkDetailVO;
-import com.cloud.network.dao.NetworkDetailsDao;
 import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.backup.Backup;
 import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
@@ -37,6 +35,8 @@ import com.cloud.agent.api.to.VirtualMachineTO;
 import com.cloud.gpu.GPU;
 import com.cloud.network.Networks.BroadcastDomainType;
 import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.dao.NetworkDetailVO;
+import com.cloud.network.dao.NetworkDetailsDao;
 import com.cloud.network.dao.NetworkVO;
 import com.cloud.offering.NetworkOffering;
 import com.cloud.offering.ServiceOffering;
@@ -47,6 +47,7 @@ import com.cloud.service.dao.ServiceOfferingDao;
 import com.cloud.service.dao.ServiceOfferingDetailsDao;
 import com.cloud.storage.StoragePool;
 import com.cloud.utils.Pair;
+import com.cloud.utils.StringUtils;
 import com.cloud.utils.component.AdapterBase;
 import com.cloud.vm.NicProfile;
 import com.cloud.vm.NicVO;
@@ -171,6 +172,11 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
                 offering.getRamSize() * 1024l * 1024l, null, null, vm.isHaEnabled(), vm.limitCpuUse(), vm.getVncPassword());
         to.setBootArgs(vmProfile.getBootArgs());
 
+        String bootType = (String)vmProfile.getParameter(new VirtualMachineProfile.Param("BootType"));
+        if (StringUtils.isNotBlank(bootType)) {
+            to.setBootType(bootType);
+        }
+
         List<NicProfile> nicProfiles = vmProfile.getNics();
         NicTO[] nics = new NicTO[nicProfiles.size()];
         int i = 0;
diff --git a/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java b/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java
index e232d6a..904a488 100644
--- a/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java
+++ b/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java
@@ -202,6 +202,7 @@ public abstract class LibvirtServerDiscoverer extends DiscovererBase implements
     @Override
     public Map<? extends ServerResource, Map<String, String>>
         find(long dcId, Long podId, Long clusterId, URI uri, String username, String password, List<String> hostTags) throws DiscoveryException {
+        boolean isUefiSupported = false;
 
         ClusterVO cluster = _clusterDao.findById(clusterId);
         if (cluster == null || cluster.getHypervisorType() != getHypervisorType()) {
@@ -256,6 +257,11 @@ public abstract class LibvirtServerDiscoverer extends DiscovererBase implements
                 return null;
             }
 
+            if (SSHCmdHelper.sshExecuteCmd(sshConnection, "rpm -qa | grep -i ovmf", 3)) {
+                s_logger.debug("It's UEFI enabled KVM machine");
+                isUefiSupported = true;
+            }
+
             List<PhysicalNetworkSetupInfo> netInfos = _networkMgr.getPhysicalNetworkInfo(dcId, getHypervisorType());
             String kvmPrivateNic = null;
             String kvmPublicNic = null;
@@ -338,6 +344,7 @@ public abstract class LibvirtServerDiscoverer extends DiscovererBase implements
             Map<String, String> hostDetails = connectedHost.getDetails();
             hostDetails.put("password", password);
             hostDetails.put("username", username);
+            hostDetails.put(Host.HOST_UEFI_ENABLE, isUefiSupported == true ? Boolean.toString(true) : Boolean.toString(false));
             _hostDao.saveDetails(connectedHost);
             return resources;
         } catch (DiscoveredWithErrorException e) {
diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java
index ff29f1d..a3e9bb6 100644
--- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java
@@ -709,6 +709,8 @@ import com.cloud.vm.dao.InstanceGroupDao;
 import com.cloud.vm.dao.SecondaryStorageVmDao;
 import com.cloud.vm.dao.UserVmDao;
 import com.cloud.vm.dao.VMInstanceDao;
+import com.cloud.vm.UserVmDetailVO;
+import com.cloud.vm.dao.UserVmDetailsDao;
 
 public class ManagementServerImpl extends ManagerBase implements ManagementServer, Configurable {
     public static final Logger s_logger = Logger.getLogger(ManagementServerImpl.class.getName());
@@ -728,6 +730,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
     @Inject
     private ClusterDao _clusterDao;
     @Inject
+    private UserVmDetailsDao _UserVmDetailsDao;
+    @Inject
     private SecondaryStorageVmDao _secStorageVmDao;
     @Inject
     public EventDao _eventDao;
@@ -1191,6 +1195,16 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
             throw ex;
         }
 
+        UserVmDetailVO userVmDetailVO = _UserVmDetailsDao.findDetail(vm.getId(), ApiConstants.BootType.UEFI.toString());
+        if (userVmDetailVO != null) {
+            s_logger.info(" Live Migration of UEFI enabled VM : " + vm.getInstanceName() + " is not supported");
+            if ("legacy".equalsIgnoreCase(userVmDetailVO.getValue()) || "secure".equalsIgnoreCase(userVmDetailVO.getValue())) {
+                // Return empty list.
+                return new Ternary<Pair<List<? extends Host>, Integer>, List<? extends Host>, Map<Host, Boolean>>(new Pair<List<? extends Host>,
+                        Integer>(new ArrayList<HostVO>(), new Integer(0)), new ArrayList<Host>(), new HashMap<Host, Boolean>());
+            }
+        }
+
         if (_serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) {
             s_logger.info(" Live Migration of GPU enabled VM : " + vm.getInstanceName() + " is not supported");
             // Return empty list.
diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
index 3f28f12..b88e250 100644
--- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
@@ -3963,6 +3963,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
                     } else {
                         vm.setDetail(key, customParameters.get(key));
                     }
+
+                    if (key.equalsIgnoreCase(ApiConstants.BootType.UEFI.toString())) {
+                        vm.setDetail(key, customParameters.get(key));
+                        continue;
+                    }
                 }
                 vm.setDetail(VmDetailConstants.DEPLOY_VM, "true");
 
@@ -4282,13 +4287,21 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
         Long podId = null;
         Long clusterId = null;
         Long hostId = cmd.getHostId();
+        Map<VirtualMachineProfile.Param, Object> additonalParams = null;
         Map<Long, DiskOffering> diskOfferingMap = cmd.getDataDiskTemplateToDiskOfferingMap();
         if (cmd instanceof DeployVMCmdByAdmin) {
             DeployVMCmdByAdmin adminCmd = (DeployVMCmdByAdmin)cmd;
             podId = adminCmd.getPodId();
             clusterId = adminCmd.getClusterId();
         }
-        return startVirtualMachine(vmId, podId, clusterId, hostId, diskOfferingMap, null, cmd.getDeploymentPlanner());
+        if (MapUtils.isNotEmpty(cmd.getDetails()) && cmd.getDetails().containsKey(ApiConstants.BootType.UEFI.toString())) {
+            additonalParams = new HashMap<VirtualMachineProfile.Param, Object>();
+            Map<String, String> map = cmd.getDetails();
+            additonalParams.put(VirtualMachineProfile.Param.UefiFlag, "Yes");
+            additonalParams.put(VirtualMachineProfile.Param.BootType, ApiConstants.BootType.UEFI.toString());
+            additonalParams.put(VirtualMachineProfile.Param.BootMode, map.get(ApiConstants.BootType.UEFI.toString()));
+        }
+        return startVirtualMachine(vmId, podId, clusterId, hostId, diskOfferingMap, additonalParams, cmd.getDeploymentPlanner());
     }
 
     private UserVm startVirtualMachine(long vmId, Long podId, Long clusterId, Long hostId, Map<Long, DiskOffering> diskOfferingMap, Map<VirtualMachineProfile.Param, Object> additonalParams, String deploymentPlannerToUse)
@@ -4747,6 +4760,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
                 throw new InvalidParameterValueException("Can't find a planner by name " + deploymentPlannerToUse);
             }
         }
+        vmEntity.setParamsToEntity(additionalParams);
 
         String reservationId = vmEntity.reserve(planner, plan, new ExcludeList(), Long.toString(callerUser.getId()));
         vmEntity.deploy(reservationId, Long.toString(callerUser.getId()), params, deployOnGivenHost);
diff --git a/server/src/test/java/com/cloud/vm/DeploymentPlanningManagerImplTest.java b/server/src/test/java/com/cloud/vm/DeploymentPlanningManagerImplTest.java
index 1d1ab89..e73c0c6 100644
--- a/server/src/test/java/com/cloud/vm/DeploymentPlanningManagerImplTest.java
+++ b/server/src/test/java/com/cloud/vm/DeploymentPlanningManagerImplTest.java
@@ -102,6 +102,7 @@ import com.cloud.utils.component.ComponentContext;
 import com.cloud.vm.dao.UserVmDao;
 import com.cloud.vm.dao.UserVmDetailsDao;
 import com.cloud.vm.dao.VMInstanceDao;
+import com.cloud.host.dao.HostDetailsDao;
 
 @RunWith(SpringJUnit4ClassRunner.class)
 @ContextConfiguration(loader = AnnotationConfigContextLoader.class)
@@ -285,6 +286,12 @@ public class DeploymentPlanningManagerImplTest {
         }
 
         @Bean
+        public HostDetailsDao hostDetailsDao() {
+            return Mockito.mock(HostDetailsDao.class);
+        }
+
+
+        @Bean
         public ClusterDetailsDao clusterDetailsDao() {
             return Mockito.mock(ClusterDetailsDao.class);
         }
diff --git a/server/src/test/java/com/cloud/vm/FirstFitPlannerTest.java b/server/src/test/java/com/cloud/vm/FirstFitPlannerTest.java
index 85463de..41deea2 100644
--- a/server/src/test/java/com/cloud/vm/FirstFitPlannerTest.java
+++ b/server/src/test/java/com/cloud/vm/FirstFitPlannerTest.java
@@ -95,6 +95,7 @@ import com.cloud.utils.component.ComponentContext;
 import com.cloud.vm.dao.UserVmDao;
 import com.cloud.vm.dao.UserVmDetailsDao;
 import com.cloud.vm.dao.VMInstanceDao;
+import com.cloud.host.dao.HostDetailsDao;
 
 @RunWith(SpringJUnit4ClassRunner.class)
 @ContextConfiguration(loader = AnnotationConfigContextLoader.class)
@@ -109,6 +110,8 @@ public class FirstFitPlannerTest {
     @Inject
     UserVmDao vmDao;
     @Inject
+    HostDetailsDao hostDetailsDao;
+    @Inject
     UserVmDetailsDao vmDetailsDao;
     @Inject
     ConfigurationDao configDao;
@@ -356,6 +359,9 @@ public class FirstFitPlannerTest {
         }
 
         @Bean
+        public HostDetailsDao hostDetailsDao() { return  Mockito.mock(HostDetailsDao.class); }
+
+        @Bean
         public HostGpuGroupsDao hostGpuGroupsDao() {
             return Mockito.mock(HostGpuGroupsDao.class);
         }
diff --git a/ui/index.html b/ui/index.html
index 7d24838..ef7a461 100644
--- a/ui/index.html
+++ b/ui/index.html
@@ -480,6 +480,31 @@
                                         </div>
                                     </div>
 
+                                    <!--  UEFI Boot -->
+                                    <div class="select" odd>
+                                        <div class="name">
+                                            <span><translate key="label.vm.boottype" /></span>
+                                        </div>
+                                        <div class="value">
+                                            <select name="customboot" id="customboot">
+                                                <option value="BIOS">BIOS</option>
+                                                <option value="UEFI">UEFI</option>
+                                            </select>
+                                        </div>
+                                    </div>
+
+                                    <div class="select field hide-if-unselected">
+                                        <div class="name">
+                                            <span><translate key="label.vm.bootmode" /></span>
+                                        </div>
+                                        <div class="value">
+                                            <select name="bootmode" id="bootmode">
+                                                <option value="LEGACY">LEGACY</option>
+                                            </select>
+                                        </div>
+                                    </div>
+
+
                                     <!-- Zone -->
                                     <div class="select">
                                         <div class="name">
diff --git a/ui/l10n/en.js b/ui/l10n/en.js
index d01b622..cb967be 100644
--- a/ui/l10n/en.js
+++ b/ui/l10n/en.js
@@ -893,6 +893,7 @@ var dictionary = {
 "label.host.name":"Host Name",
 "label.host.tag":"Host Tag",
 "label.host.tags":"Host Tags",
+"label.host.ueficapability":"UEFI Supported",
 "label.hosts":"Hosts",
 "label.hourly":"Hourly",
 "label.hvm":"HVM",
@@ -990,6 +991,8 @@ var dictionary = {
 "label.keep.colon":"Keep:",
 "label.key":"Key",
 "label.keyboard.language":"Keyboard language",
+"label.vm.boottype":"Boot Type",
+"label.vm.bootmode":"Boot Mode",
 "label.keyboard.type":"Keyboard type",
 "label.kubernetes.cluster":"Kubernetes cluster",
 "label.kubernetes.cluster.details":"Kubernetes cluster details",
diff --git a/ui/scripts/instanceWizard.js b/ui/scripts/instanceWizard.js
index 04cceaa..cd95913 100644
--- a/ui/scripts/instanceWizard.js
+++ b/ui/scripts/instanceWizard.js
@@ -1399,6 +1399,18 @@
                     keyboard : keyboard
                 });
             }
+            var boottype = args.data.customboot;
+            if (boottype != null && boottype.length > 0) {
+                $.extend(deployVmData, {
+                    boottype : boottype
+                });
+            }
+            var bootmode = args.data.bootmode;
+            if (bootmode != null && bootmode.length > 0) {
+                $.extend(deployVmData, {
+                    bootmode : bootmode
+                });
+            }
 
             if (g_hostid != null) {
                 $.extend(deployVmData, {
diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js
index bb32d3a..58cb86c 100644
--- a/ui/scripts/instances.js
+++ b/ui/scripts/instances.js
@@ -3322,6 +3322,12 @@
                             },
                             id: {
                                 label: 'label.id'
+                            },
+                            boottype: {
+                                label: 'label.vm.boottype'
+                            },
+                            bootmode: {
+                                 label: 'label.vm.bootmode'
                             }
                         }],
 
diff --git a/ui/scripts/system.js b/ui/scripts/system.js
index 1e29500..29f428a 100755
--- a/ui/scripts/system.js
+++ b/ui/scripts/system.js
@@ -18024,6 +18024,10 @@
                                             });
                                         }
                                     },
+                                    ueficapability: {
+                                        label:'label.host.ueficapability',
+                                        converter: cloudStack.converters.toBooleanText
+                                    },
                                     hahost: {
                                         label: 'label.ha.enabled',
                                         converter: cloudStack.converters.toBooleanText
diff --git a/ui/scripts/ui-custom/instanceWizard.js b/ui/scripts/ui-custom/instanceWizard.js
index 2450ed1..4aefa97 100644
--- a/ui/scripts/ui-custom/instanceWizard.js
+++ b/ui/scripts/ui-custom/instanceWizard.js
@@ -1392,6 +1392,50 @@
                                     $(this).closest('div.select').hide();
                                 }
                             }
+
+                            var uefi = function(bootType){
+                                var $bootmode  = $step.find('select[name=bootmode]');
+
+                                if(bootType.toLowerCase() == 'uefi' ){
+                                    $bootmode.html('');
+                                    var $option = $('<option>');
+                                    var id = 'LEGACY';
+                                    var description = 'LEGACY';
+
+                                    $option.attr('value', id);
+                                    $option.html(description);
+                                    $option.appendTo($bootmode);
+
+                                    var $option2 = $('<option>');
+                                    var id2 = 'SECURE';
+                                    var description2 = 'SECURE';
+
+                                    $option2.attr('value', id2);
+                                    $option2.html(description2);
+                                    $option2.appendTo($bootmode);
+
+                                }
+
+                                if(bootType.toLowerCase() == 'bios' ){
+                                     $bootmode.html('');
+
+                                     var $option = $('<option>');
+                                     var id = 'LEGACY';
+                                     var description = 'LEGACY';
+
+                                     $option.attr('value', id);
+                                     $option.html(description);
+                                     $option.appendTo($bootmode);
+                                }
+
+                            }
+
+                            var $uefiselect  = $step.find('select[name=customboot]');
+                            $uefiselect.unbind('change');
+                            $uefiselect.change(function(){
+                                 uefi($uefiselect.val());
+                            });
+
                         });
                     }
                 };
diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java
index 5aab3a2..7877db9 100644
--- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java
+++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java
@@ -1196,4 +1196,17 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
         }
         return morNetwork;
     }
+
+    public String getProductVersion() throws Exception {
+        return getHostAboutInfo().getVersion();
+    }
+
+    public boolean isUefiLegacySupported() throws Exception {
+        String hostVersion = getProductVersion();
+        if (hostVersion.compareTo(VmwareHelper.MIN_VERSION_UEFI_LEGACY) >= 0) {
+            return true;
+        }
+        return false;
+    }
+
 }
diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java
index dd65775..3d209fb 100644
--- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java
+++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java
@@ -92,6 +92,7 @@ public class VmwareHelper {
     public static final int MAX_IDE_CONTROLLER_COUNT = 2;
     public static final int MAX_ALLOWED_DEVICES_IDE_CONTROLLER = 2;
     public static final int MAX_ALLOWED_DEVICES_SCSI_CONTROLLER = 15;
+    public static final String MIN_VERSION_UEFI_LEGACY = "5.5";
 
     public static boolean isReservedScsiDeviceNumber(int deviceNumber) {
         return deviceNumber == 7;