mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Merge remote-tracking branch 'origin/4.15'
This commit is contained in:
commit
49acd1dec7
@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
package org.apache.cloudstack.storage.command;
|
package org.apache.cloudstack.storage.command;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import com.cloud.agent.api.to.DiskTO;
|
import com.cloud.agent.api.to.DiskTO;
|
||||||
|
|
||||||
public class DettachCommand extends StorageSubSystemCommand {
|
public class DettachCommand extends StorageSubSystemCommand {
|
||||||
@ -28,6 +30,7 @@ public class DettachCommand extends StorageSubSystemCommand {
|
|||||||
private String _iScsiName;
|
private String _iScsiName;
|
||||||
private String _storageHost;
|
private String _storageHost;
|
||||||
private int _storagePort;
|
private int _storagePort;
|
||||||
|
private Map<String, String> params;
|
||||||
|
|
||||||
public DettachCommand(final DiskTO disk, final String vmName) {
|
public DettachCommand(final DiskTO disk, final String vmName) {
|
||||||
super();
|
super();
|
||||||
@ -35,6 +38,13 @@ public class DettachCommand extends StorageSubSystemCommand {
|
|||||||
this.vmName = vmName;
|
this.vmName = vmName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DettachCommand(final DiskTO disk, final String vmName, Map<String, String> params) {
|
||||||
|
super();
|
||||||
|
this.disk = disk;
|
||||||
|
this.vmName = vmName;
|
||||||
|
this.params = params;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean executeInSequence() {
|
public boolean executeInSequence() {
|
||||||
return false;
|
return false;
|
||||||
@ -88,6 +98,14 @@ public class DettachCommand extends StorageSubSystemCommand {
|
|||||||
return _storagePort;
|
return _storagePort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getParams() {
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParams(Map<String, String> params) {
|
||||||
|
this.params = params;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setExecuteInSequence(final boolean inSeq) {
|
public void setExecuteInSequence(final boolean inSeq) {
|
||||||
|
|
||||||
|
|||||||
@ -2426,7 +2426,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||||||
DiskDef.DiskBus busT = getDiskModelFromVMDetail(vmTO);
|
DiskDef.DiskBus busT = getDiskModelFromVMDetail(vmTO);
|
||||||
|
|
||||||
if (busT == null) {
|
if (busT == null) {
|
||||||
busT = getGuestDiskModel(vmTO.getPlatformEmulator());
|
busT = getGuestDiskModel(vmTO.getPlatformEmulator(), isUefiEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're using virtio scsi, then we need to add a virtual scsi controller
|
// If we're using virtio scsi, then we need to add a virtual scsi controller
|
||||||
@ -2521,7 +2521,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (MapUtils.isNotEmpty(details) && details.containsKey(GuestDef.BootType.UEFI.toString())) {
|
boolean isUefiEnabled = MapUtils.isNotEmpty(details) && details.containsKey(GuestDef.BootType.UEFI.toString());
|
||||||
|
if (isUefiEnabled) {
|
||||||
isSecureBoot = isSecureMode(details.get(GuestDef.BootType.UEFI.toString()));
|
isSecureBoot = isSecureMode(details.get(GuestDef.BootType.UEFI.toString()));
|
||||||
}
|
}
|
||||||
if (vmSpec.getOs().toLowerCase().contains("window")) {
|
if (vmSpec.getOs().toLowerCase().contains("window")) {
|
||||||
@ -2589,7 +2590,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||||||
// if params contains a rootDiskController key, use its value (this is what other HVs are doing)
|
// if params contains a rootDiskController key, use its value (this is what other HVs are doing)
|
||||||
DiskDef.DiskBus diskBusType = getDiskModelFromVMDetail(vmSpec);
|
DiskDef.DiskBus diskBusType = getDiskModelFromVMDetail(vmSpec);
|
||||||
if (diskBusType == null) {
|
if (diskBusType == null) {
|
||||||
diskBusType = getGuestDiskModel(vmSpec.getPlatformEmulator());
|
diskBusType = getGuestDiskModel(vmSpec.getPlatformEmulator(), isUefiEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
DiskDef.DiskBus diskBusTypeData = getDataDiskModelFromVMDetail(vmSpec);
|
DiskDef.DiskBus diskBusTypeData = getDataDiskModelFromVMDetail(vmSpec);
|
||||||
@ -2600,16 +2601,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||||||
final DiskDef disk = new DiskDef();
|
final DiskDef disk = new DiskDef();
|
||||||
int devId = volume.getDiskSeq().intValue();
|
int devId = volume.getDiskSeq().intValue();
|
||||||
if (volume.getType() == Volume.Type.ISO) {
|
if (volume.getType() == Volume.Type.ISO) {
|
||||||
if (volPath == null) {
|
|
||||||
if (isSecureBoot) {
|
disk.defISODisk(volPath, devId, isUefiEnabled);
|
||||||
disk.defISODisk(null, devId,isSecureBoot,isWindowsTemplate);
|
|
||||||
} else {
|
|
||||||
/* Add iso as placeholder */
|
|
||||||
disk.defISODisk(null, devId);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
disk.defISODisk(volPath, devId);
|
|
||||||
}
|
|
||||||
if (_guestCpuArch != null && _guestCpuArch.equals("aarch64")) {
|
if (_guestCpuArch != null && _guestCpuArch.equals("aarch64")) {
|
||||||
disk.setBusType(DiskDef.DiskBus.SCSI);
|
disk.setBusType(DiskDef.DiskBus.SCSI);
|
||||||
}
|
}
|
||||||
@ -2636,14 +2630,14 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||||||
disk.defNetworkBasedDisk(glusterVolume + path.replace(mountpoint, ""), pool.getSourceHost(), pool.getSourcePort(), null,
|
disk.defNetworkBasedDisk(glusterVolume + path.replace(mountpoint, ""), pool.getSourceHost(), pool.getSourcePort(), null,
|
||||||
null, devId, diskBusType, DiskProtocol.GLUSTER, DiskDef.DiskFmtType.QCOW2);
|
null, devId, diskBusType, DiskProtocol.GLUSTER, DiskDef.DiskFmtType.QCOW2);
|
||||||
} else if (pool.getType() == StoragePoolType.CLVM || physicalDisk.getFormat() == PhysicalDiskFormat.RAW) {
|
} else if (pool.getType() == StoragePoolType.CLVM || physicalDisk.getFormat() == PhysicalDiskFormat.RAW) {
|
||||||
if (volume.getType() == Volume.Type.DATADISK) {
|
if (volume.getType() == Volume.Type.DATADISK && !(isWindowsTemplate && isUefiEnabled)) {
|
||||||
disk.defBlockBasedDisk(physicalDisk.getPath(), devId, diskBusTypeData);
|
disk.defBlockBasedDisk(physicalDisk.getPath(), devId, diskBusTypeData);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
disk.defBlockBasedDisk(physicalDisk.getPath(), devId, diskBusType);
|
disk.defBlockBasedDisk(physicalDisk.getPath(), devId, diskBusType);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (volume.getType() == Volume.Type.DATADISK) {
|
if (volume.getType() == Volume.Type.DATADISK && !(isWindowsTemplate && isUefiEnabled)) {
|
||||||
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusTypeData, DiskDef.DiskFmtType.QCOW2);
|
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusTypeData, DiskDef.DiskFmtType.QCOW2);
|
||||||
} else {
|
} else {
|
||||||
if (isSecureBoot) {
|
if (isSecureBoot) {
|
||||||
@ -3429,7 +3423,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean isGuestPVEnabled(final String guestOSName) {
|
boolean isGuestPVEnabled(final String guestOSName) {
|
||||||
DiskDef.DiskBus db = getGuestDiskModel(guestOSName);
|
DiskDef.DiskBus db = getGuestDiskModel(guestOSName, false);
|
||||||
return db != DiskDef.DiskBus.IDE;
|
return db != DiskDef.DiskBus.IDE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3483,7 +3477,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DiskDef.DiskBus getGuestDiskModel(final String platformEmulator) {
|
private DiskDef.DiskBus getGuestDiskModel(final String platformEmulator, boolean isUefiEnabled) {
|
||||||
if (_guestCpuArch != null && _guestCpuArch.equals("aarch64")) {
|
if (_guestCpuArch != null && _guestCpuArch.equals("aarch64")) {
|
||||||
return DiskDef.DiskBus.SCSI;
|
return DiskDef.DiskBus.SCSI;
|
||||||
}
|
}
|
||||||
@ -3492,6 +3486,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||||||
return DiskDef.DiskBus.IDE;
|
return DiskDef.DiskBus.IDE;
|
||||||
} else if (platformEmulator.startsWith("Other PV Virtio-SCSI")) {
|
} else if (platformEmulator.startsWith("Other PV Virtio-SCSI")) {
|
||||||
return DiskDef.DiskBus.SCSI;
|
return DiskDef.DiskBus.SCSI;
|
||||||
|
} else if (isUefiEnabled && platformEmulator.startsWith("Windows")) {
|
||||||
|
return DiskDef.DiskBus.SATA;
|
||||||
} else if (platformEmulator.contains("Ubuntu") ||
|
} else if (platformEmulator.contains("Ubuntu") ||
|
||||||
platformEmulator.startsWith("Fedora") ||
|
platformEmulator.startsWith("Fedora") ||
|
||||||
platformEmulator.startsWith("CentOS") ||
|
platformEmulator.startsWith("CentOS") ||
|
||||||
|
|||||||
@ -716,16 +716,14 @@ public class LibvirtVMDef {
|
|||||||
} else if (bus == DiskBus.VIRTIO) {
|
} else if (bus == DiskBus.VIRTIO) {
|
||||||
return "vd" + getDevLabelSuffix(devId);
|
return "vd" + getDevLabelSuffix(devId);
|
||||||
} else if (bus == DiskBus.SATA){
|
} else if (bus == DiskBus.SATA){
|
||||||
if (!forIso) {
|
return "sd" + getDevLabelSuffix(devId);
|
||||||
return "sda";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (forIso) {
|
if (forIso) {
|
||||||
devId --;
|
devId --;
|
||||||
} else if(devId >= 2) {
|
} else if(devId >= 2) {
|
||||||
devId += 2;
|
devId += 2;
|
||||||
}
|
}
|
||||||
return (DiskBus.SATA == bus) ? "sdb" : "hd" + getDevLabelSuffix(devId);
|
return "hd" + getDevLabelSuffix(devId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -784,6 +782,16 @@ public class LibvirtVMDef {
|
|||||||
_bus = DiskBus.IDE;
|
_bus = DiskBus.IDE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void defISODisk(String volPath, boolean isUefiEnabled) {
|
||||||
|
_diskType = DiskType.FILE;
|
||||||
|
_deviceType = DeviceType.CDROM;
|
||||||
|
_sourcePath = volPath;
|
||||||
|
_bus = isUefiEnabled ? DiskBus.SATA : DiskBus.IDE;
|
||||||
|
_diskLabel = getDevLabel(3, _bus, true);
|
||||||
|
_diskFmtType = DiskFmtType.RAW;
|
||||||
|
_diskCacheMode = DiskCacheMode.NONE;
|
||||||
|
}
|
||||||
|
|
||||||
public void defISODisk(String volPath, Integer devId) {
|
public void defISODisk(String volPath, Integer devId) {
|
||||||
if (devId == null) {
|
if (devId == null) {
|
||||||
defISODisk(volPath);
|
defISODisk(volPath);
|
||||||
@ -798,20 +806,15 @@ public class LibvirtVMDef {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void defISODisk(String volPath, Integer devId,boolean isSecure, boolean isWindowOs) {
|
public void defISODisk(String volPath, Integer devId,boolean isSecure) {
|
||||||
if (!isSecure) {
|
if (!isSecure) {
|
||||||
defISODisk(volPath, devId);
|
defISODisk(volPath, devId);
|
||||||
} else {
|
} else {
|
||||||
_diskType = DiskType.FILE;
|
_diskType = DiskType.FILE;
|
||||||
_deviceType = DeviceType.CDROM;
|
_deviceType = DeviceType.CDROM;
|
||||||
_sourcePath = volPath;
|
_sourcePath = volPath;
|
||||||
if (isWindowOs) {
|
_diskLabel = getDevLabel(devId, DiskBus.SATA, true);
|
||||||
_diskLabel = getDevLabel(devId, DiskBus.SATA, true);
|
_bus = DiskBus.SATA;
|
||||||
_bus = DiskBus.SATA;
|
|
||||||
} else {
|
|
||||||
_diskLabel = getDevLabel(devId, DiskBus.SCSI, true);
|
|
||||||
_bus = DiskBus.SCSI;
|
|
||||||
}
|
|
||||||
_diskFmtType = DiskFmtType.RAW;
|
_diskFmtType = DiskFmtType.RAW;
|
||||||
_diskCacheMode = DiskCacheMode.NONE;
|
_diskCacheMode = DiskCacheMode.NONE;
|
||||||
|
|
||||||
|
|||||||
@ -67,6 +67,7 @@ import org.apache.cloudstack.utils.qemu.QemuImg;
|
|||||||
import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat;
|
import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat;
|
||||||
import org.apache.cloudstack.utils.qemu.QemuImgException;
|
import org.apache.cloudstack.utils.qemu.QemuImgException;
|
||||||
import org.apache.cloudstack.utils.qemu.QemuImgFile;
|
import org.apache.cloudstack.utils.qemu.QemuImgFile;
|
||||||
|
import org.apache.commons.collections.MapUtils;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.libvirt.Connect;
|
import org.libvirt.Connect;
|
||||||
@ -1081,9 +1082,10 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized String attachOrDetachISO(final Connect conn, final String vmName, String isoPath, final boolean isAttach) throws LibvirtException, URISyntaxException,
|
protected synchronized String attachOrDetachISO(final Connect conn, final String vmName, String isoPath, final boolean isAttach, Map<String, String> params) throws LibvirtException, URISyntaxException,
|
||||||
InternalErrorException {
|
InternalErrorException {
|
||||||
String isoXml = null;
|
String isoXml = null;
|
||||||
|
boolean isUefiEnabled = MapUtils.isNotEmpty(params) && params.containsKey("UEFI");
|
||||||
if (isoPath != null && isAttach) {
|
if (isoPath != null && isAttach) {
|
||||||
final int index = isoPath.lastIndexOf("/");
|
final int index = isoPath.lastIndexOf("/");
|
||||||
final String path = isoPath.substring(0, index);
|
final String path = isoPath.substring(0, index);
|
||||||
@ -1093,11 +1095,11 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||||||
isoPath = isoVol.getPath();
|
isoPath = isoVol.getPath();
|
||||||
|
|
||||||
final DiskDef iso = new DiskDef();
|
final DiskDef iso = new DiskDef();
|
||||||
iso.defISODisk(isoPath);
|
iso.defISODisk(isoPath, isUefiEnabled);
|
||||||
isoXml = iso.toString();
|
isoXml = iso.toString();
|
||||||
} else {
|
} else {
|
||||||
final DiskDef iso = new DiskDef();
|
final DiskDef iso = new DiskDef();
|
||||||
iso.defISODisk(null);
|
iso.defISODisk(null, isUefiEnabled);
|
||||||
isoXml = iso.toString();
|
isoXml = iso.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1123,7 +1125,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||||||
try {
|
try {
|
||||||
String dataStoreUrl = getDataStoreUrlFromStore(store);
|
String dataStoreUrl = getDataStoreUrlFromStore(store);
|
||||||
final Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
|
final Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
|
||||||
attachOrDetachISO(conn, cmd.getVmName(), dataStoreUrl + File.separator + isoTO.getPath(), true);
|
attachOrDetachISO(conn, cmd.getVmName(), dataStoreUrl + File.separator + isoTO.getPath(), true, cmd.getControllerInfo());
|
||||||
} catch (final LibvirtException e) {
|
} catch (final LibvirtException e) {
|
||||||
return new Answer(cmd, false, e.toString());
|
return new Answer(cmd, false, e.toString());
|
||||||
} catch (final URISyntaxException e) {
|
} catch (final URISyntaxException e) {
|
||||||
@ -1146,7 +1148,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||||||
try {
|
try {
|
||||||
String dataStoreUrl = getDataStoreUrlFromStore(store);
|
String dataStoreUrl = getDataStoreUrlFromStore(store);
|
||||||
final Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
|
final Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
|
||||||
attachOrDetachISO(conn, cmd.getVmName(), dataStoreUrl + File.separator + isoTO.getPath(), false);
|
attachOrDetachISO(conn, cmd.getVmName(), dataStoreUrl + File.separator + isoTO.getPath(), false, cmd.getParams());
|
||||||
} catch (final LibvirtException e) {
|
} catch (final LibvirtException e) {
|
||||||
return new Answer(cmd, false, e.toString());
|
return new Answer(cmd, false, e.toString());
|
||||||
} catch (final URISyntaxException e) {
|
} catch (final URISyntaxException e) {
|
||||||
|
|||||||
2
pom.xml
2
pom.xml
@ -112,7 +112,7 @@
|
|||||||
<cs.selenium.server.version>1.0-20081010.060147</cs.selenium.server.version>
|
<cs.selenium.server.version>1.0-20081010.060147</cs.selenium.server.version>
|
||||||
<cs.selenium-java-client-driver.version>1.0.1</cs.selenium-java-client-driver.version>
|
<cs.selenium-java-client-driver.version>1.0.1</cs.selenium-java-client-driver.version>
|
||||||
<cs.testng.version>7.1.0</cs.testng.version>
|
<cs.testng.version>7.1.0</cs.testng.version>
|
||||||
<cs.wiremock.version>2.11.0</cs.wiremock.version>
|
<cs.wiremock.version>2.27.2</cs.wiremock.version>
|
||||||
<cs.xercesImpl.version>2.12.0</cs.xercesImpl.version>
|
<cs.xercesImpl.version>2.12.0</cs.xercesImpl.version>
|
||||||
|
|
||||||
<!-- Dependencies versions -->
|
<!-- Dependencies versions -->
|
||||||
|
|||||||
@ -112,6 +112,7 @@ import com.cloud.agent.api.to.DataTO;
|
|||||||
import com.cloud.agent.api.to.DatadiskTO;
|
import com.cloud.agent.api.to.DatadiskTO;
|
||||||
import com.cloud.agent.api.to.DiskTO;
|
import com.cloud.agent.api.to.DiskTO;
|
||||||
import com.cloud.agent.api.to.NfsTO;
|
import com.cloud.agent.api.to.NfsTO;
|
||||||
|
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||||
import com.cloud.api.ApiDBUtils;
|
import com.cloud.api.ApiDBUtils;
|
||||||
import com.cloud.api.ApiResponseHelper;
|
import com.cloud.api.ApiResponseHelper;
|
||||||
import com.cloud.api.query.dao.UserVmJoinDao;
|
import com.cloud.api.query.dao.UserVmJoinDao;
|
||||||
@ -136,6 +137,8 @@ import com.cloud.exception.StorageUnavailableException;
|
|||||||
import com.cloud.host.HostVO;
|
import com.cloud.host.HostVO;
|
||||||
import com.cloud.host.dao.HostDao;
|
import com.cloud.host.dao.HostDao;
|
||||||
import com.cloud.hypervisor.Hypervisor;
|
import com.cloud.hypervisor.Hypervisor;
|
||||||
|
import com.cloud.hypervisor.HypervisorGuru;
|
||||||
|
import com.cloud.hypervisor.HypervisorGuruManager;
|
||||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
import com.cloud.projects.Project;
|
import com.cloud.projects.Project;
|
||||||
import com.cloud.projects.ProjectManager;
|
import com.cloud.projects.ProjectManager;
|
||||||
@ -199,6 +202,7 @@ import com.cloud.vm.UserVmVO;
|
|||||||
import com.cloud.vm.VMInstanceVO;
|
import com.cloud.vm.VMInstanceVO;
|
||||||
import com.cloud.vm.VirtualMachine.State;
|
import com.cloud.vm.VirtualMachine.State;
|
||||||
import com.cloud.vm.VirtualMachineProfile;
|
import com.cloud.vm.VirtualMachineProfile;
|
||||||
|
import com.cloud.vm.VirtualMachineProfileImpl;
|
||||||
import com.cloud.vm.VmDetailConstants;
|
import com.cloud.vm.VmDetailConstants;
|
||||||
import com.cloud.vm.dao.UserVmDao;
|
import com.cloud.vm.dao.UserVmDao;
|
||||||
import com.cloud.vm.dao.VMInstanceDao;
|
import com.cloud.vm.dao.VMInstanceDao;
|
||||||
@ -283,6 +287,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||||||
MessageBus _messageBus;
|
MessageBus _messageBus;
|
||||||
@Inject
|
@Inject
|
||||||
private VMTemplateDetailsDao _tmpltDetailsDao;
|
private VMTemplateDetailsDao _tmpltDetailsDao;
|
||||||
|
@Inject
|
||||||
|
private HypervisorGuruManager _hvGuruMgr;
|
||||||
|
|
||||||
private boolean _disableExtraction = false;
|
private boolean _disableExtraction = false;
|
||||||
private List<TemplateAdapter> _adapters;
|
private List<TemplateAdapter> _adapters;
|
||||||
@ -1289,11 +1295,16 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||||||
|
|
||||||
DataTO isoTO = tmplt.getTO();
|
DataTO isoTO = tmplt.getTO();
|
||||||
DiskTO disk = new DiskTO(isoTO, null, null, Volume.Type.ISO);
|
DiskTO disk = new DiskTO(isoTO, null, null, Volume.Type.ISO);
|
||||||
|
|
||||||
|
HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
|
||||||
|
VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
|
||||||
|
VirtualMachineTO vmTO = hvGuru.implement(profile);
|
||||||
|
|
||||||
Command cmd = null;
|
Command cmd = null;
|
||||||
if (attach) {
|
if (attach) {
|
||||||
cmd = new AttachCommand(disk, vmName);
|
cmd = new AttachCommand(disk, vmName, vmTO.getDetails());
|
||||||
} else {
|
} else {
|
||||||
cmd = new DettachCommand(disk, vmName);
|
cmd = new DettachCommand(disk, vmName, vmTO.getDetails());
|
||||||
}
|
}
|
||||||
Answer a = _agentMgr.easySend(vm.getHostId(), cmd);
|
Answer a = _agentMgr.easySend(vm.getHostId(), cmd);
|
||||||
return (a != null && a.getResult());
|
return (a != null && a.getResult());
|
||||||
|
|||||||
@ -30,6 +30,7 @@ import com.cloud.exception.ResourceAllocationException;
|
|||||||
import com.cloud.host.Status;
|
import com.cloud.host.Status;
|
||||||
import com.cloud.host.dao.HostDao;
|
import com.cloud.host.dao.HostDao;
|
||||||
import com.cloud.hypervisor.Hypervisor;
|
import com.cloud.hypervisor.Hypervisor;
|
||||||
|
import com.cloud.hypervisor.HypervisorGuruManager;
|
||||||
import com.cloud.storage.Storage;
|
import com.cloud.storage.Storage;
|
||||||
import com.cloud.storage.TemplateProfile;
|
import com.cloud.storage.TemplateProfile;
|
||||||
import com.cloud.projects.ProjectManager;
|
import com.cloud.projects.ProjectManager;
|
||||||
@ -180,6 +181,8 @@ public class TemplateManagerImplTest {
|
|||||||
@Inject
|
@Inject
|
||||||
private VMTemplateDao _tmpltDao;
|
private VMTemplateDao _tmpltDao;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
HypervisorGuruManager _hvGuruMgr;
|
||||||
|
|
||||||
public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
|
public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
|
||||||
AtomicInteger ai = new AtomicInteger(0);
|
AtomicInteger ai = new AtomicInteger(0);
|
||||||
@ -697,6 +700,11 @@ public class TemplateManagerImplTest {
|
|||||||
return Mockito.mock(VMTemplateDetailsDao.class);
|
return Mockito.mock(VMTemplateDetailsDao.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public HypervisorGuruManager hypervisorGuruManager() {
|
||||||
|
return Mockito.mock(HypervisorGuruManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
public static class Library implements TypeFilter {
|
public static class Library implements TypeFilter {
|
||||||
@Override
|
@Override
|
||||||
public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException {
|
public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException {
|
||||||
|
|||||||
235
test/integration/smoke/test_deploy_vm_iso_uefi.py
Normal file
235
test/integration/smoke/test_deploy_vm_iso_uefi.py
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
""" Deploy VM from ISO with UEFI
|
||||||
|
"""
|
||||||
|
# Import Local Modules
|
||||||
|
from nose.plugins.attrib import attr
|
||||||
|
from marvin.cloudstackTestCase import cloudstackTestCase, unittest
|
||||||
|
from marvin.lib.utils import cleanup_resources
|
||||||
|
from marvin.lib.base import (Account,
|
||||||
|
VirtualMachine,
|
||||||
|
ServiceOffering,
|
||||||
|
Iso,
|
||||||
|
DiskOffering,
|
||||||
|
Host,
|
||||||
|
)
|
||||||
|
from marvin.lib.common import (get_zone,
|
||||||
|
get_domain,
|
||||||
|
list_hosts,
|
||||||
|
)
|
||||||
|
from marvin.codes import PASS
|
||||||
|
from marvin.sshClient import SshClient
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
from lxml import etree
|
||||||
|
|
||||||
|
class TestDeployVMFromISOWithUefi(cloudstackTestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.testClient = super(TestDeployVMFromISOWithUefi, cls).getClsTestClient()
|
||||||
|
cls.apiclient = cls.testClient.getApiClient()
|
||||||
|
|
||||||
|
cls.hypervisor = cls.testClient.getHypervisorInfo()
|
||||||
|
|
||||||
|
if cls.hypervisor != 'kvm':
|
||||||
|
raise unittest.SkipTest("Those tests can be run only for KVM hypervisor")
|
||||||
|
|
||||||
|
cls.testdata = cls.testClient.getParsedTestDataConfig()
|
||||||
|
# Get Zone, Domain and templates
|
||||||
|
cls.domain = get_domain(cls.apiclient)
|
||||||
|
cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests())
|
||||||
|
|
||||||
|
hosts = list_hosts(cls.apiclient, zoneid = cls.zone.id, type="Routing")
|
||||||
|
|
||||||
|
if not cls.isUefiEnabledOnAtLeastOnHost(hosts):
|
||||||
|
raise unittest.SkipTest("At least one host should support UEFI")
|
||||||
|
|
||||||
|
cls.hostConfig = cls.config.__dict__["zones"][0].__dict__["pods"][0].__dict__["clusters"][0].__dict__["hosts"][0].__dict__
|
||||||
|
|
||||||
|
# Create service, disk offerings etc
|
||||||
|
cls.service_offering = ServiceOffering.create(
|
||||||
|
cls.apiclient,
|
||||||
|
cls.testdata["service_offering"]
|
||||||
|
)
|
||||||
|
|
||||||
|
cls.disk_offering = DiskOffering.create(
|
||||||
|
cls.apiclient,
|
||||||
|
cls.testdata["disk_offering"]
|
||||||
|
)
|
||||||
|
|
||||||
|
cls.testdata["virtual_machine"]["zoneid"] = cls.zone.id
|
||||||
|
cls.testdata["iso1"]["zoneid"] = cls.zone.id
|
||||||
|
cls.testdata["iso3"]["zoneid"] = cls.zone.id
|
||||||
|
cls.account = Account.create(
|
||||||
|
cls.apiclient,
|
||||||
|
cls.testdata["account"],
|
||||||
|
domainid=cls.domain.id
|
||||||
|
)
|
||||||
|
cls._cleanup = [cls.account, cls.service_offering, cls.disk_offering]
|
||||||
|
|
||||||
|
cls.centos_iso = Iso.create(
|
||||||
|
cls.apiclient,
|
||||||
|
cls.testdata["iso1"],
|
||||||
|
account=cls.account.name,
|
||||||
|
domainid=cls.account.domainid,
|
||||||
|
zoneid=cls.zone.id
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
# Download the ISO
|
||||||
|
cls.centos_iso.download(cls.apiclient)
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Exception while downloading ISO %s: %s"
|
||||||
|
% (cls.centos_iso.id, e))
|
||||||
|
|
||||||
|
cls.windows_iso = Iso.create(
|
||||||
|
cls.apiclient,
|
||||||
|
cls.testdata["iso3"],
|
||||||
|
account=cls.account.name,
|
||||||
|
domainid=cls.account.domainid,
|
||||||
|
zoneid=cls.zone.id
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
# Download the ISO
|
||||||
|
cls.windows_iso.download(cls.apiclient)
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Exception while downloading ISO %s: %s"
|
||||||
|
% (cls.windows_iso.id, e))
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
try:
|
||||||
|
cleanup_resources(cls.apiclient, cls._cleanup)
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.hypervisor = self.testClient.getHypervisorInfo()
|
||||||
|
if self.hypervisor != 'kvm':
|
||||||
|
raise self.skipTest("Skipping test case for non-kvm hypervisor")
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@attr(tags=["advanced", "eip", "advancedns", "basic", "sg"], required_hardware="true")
|
||||||
|
def test_01_deploy_vm_from_iso_uefi_secure(self):
|
||||||
|
"""Test Deploy CentOS Virtual Machine from ISO with UEFI Secure
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.deployVmAndTestUefi(self.centos_iso, 'Secure', 'yes')
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
@attr(tags=["advanced", "eip", "advancedns", "basic", "sg"], required_hardware="true")
|
||||||
|
def test_02_deploy_vm_from_iso_uefi_legacy(self):
|
||||||
|
"""Test Deploy CentOS Virtual Machine from ISO with UEFI Legacy mode
|
||||||
|
"""
|
||||||
|
self.deployVmAndTestUefi(self.centos_iso, 'Legacy', 'no')
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
@attr(tags=["advanced", "eip", "advancedns", "basic", "sg"], required_hardware="true")
|
||||||
|
def test_03_deploy_windows_vm_from_iso_uefi_legacy(self):
|
||||||
|
"""Test Deploy Windows Virtual Machine from ISO with UEFI Legacy mode
|
||||||
|
"""
|
||||||
|
self.deployVmAndTestUefi(self.windows_iso, 'Legacy', 'no')
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
@attr(tags=["advanced", "eip", "advancedns", "basic", "sg"], required_hardware="true")
|
||||||
|
def test_04_deploy_windows_vm_from_iso_uefi_secure(self):
|
||||||
|
"""Test Deploy Windows Virtual Machine from ISO with UEFI Secure mode
|
||||||
|
"""
|
||||||
|
self.deployVmAndTestUefi(self.windows_iso, 'Secure', 'yes')
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def getVirshXML(self, host, instancename):
|
||||||
|
self.assertIsNotNone(host, "Host should not be None")
|
||||||
|
|
||||||
|
self.assertIsNotNone(instancename, "Instance name should not be None")
|
||||||
|
|
||||||
|
sshc = SshClient(
|
||||||
|
host=host.ipaddress,
|
||||||
|
port=22,
|
||||||
|
user=self.hostConfig['username'],
|
||||||
|
passwd=self.hostConfig['password'])
|
||||||
|
|
||||||
|
virsh_cmd = 'virsh dumpxml %s' % instancename
|
||||||
|
xml_res = sshc.execute(virsh_cmd)
|
||||||
|
xml_as_str = ''.join(xml_res)
|
||||||
|
parser = etree.XMLParser(remove_blank_text=True)
|
||||||
|
return ET.fromstring(xml_as_str, parser=parser)
|
||||||
|
|
||||||
|
def checkBootTypeAndMode(self, root, bootmodesecure, isWindowsIso):
|
||||||
|
|
||||||
|
machine = root.find(".os/type").get("machine")
|
||||||
|
|
||||||
|
self.assertEqual(("q35" in machine), True, "The virtual machine is not with UEFI boot type")
|
||||||
|
|
||||||
|
bootmode = root.find(".os/loader").get("secure")
|
||||||
|
|
||||||
|
self.assertEqual((bootmode == bootmodesecure), True, "The VM is not in the right boot mode")
|
||||||
|
|
||||||
|
if isWindowsIso:
|
||||||
|
disks = root.findall("devices/disk")
|
||||||
|
for disk in disks:
|
||||||
|
bus = disk.find("target").get("bus")
|
||||||
|
self.debug("bus is %s" % bus)
|
||||||
|
self.assertEqual(bus == 'sata', True, "All disks of the VM should be with bus SATA")
|
||||||
|
|
||||||
|
def deployVmAndTestUefi(self, iso, bootmode, bootmodesecure):
|
||||||
|
self.virtual_machine = VirtualMachine.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.testdata["virtual_machine"],
|
||||||
|
accountid=self.account.name,
|
||||||
|
domainid=self.account.domainid,
|
||||||
|
templateid=iso.id,
|
||||||
|
serviceofferingid=self.service_offering.id,
|
||||||
|
diskofferingid=self.disk_offering.id,
|
||||||
|
hypervisor=self.hypervisor,
|
||||||
|
boottype='UEFI',
|
||||||
|
bootmode=bootmode,
|
||||||
|
zoneid=self.zone.id
|
||||||
|
)
|
||||||
|
|
||||||
|
response = self.virtual_machine.getState(
|
||||||
|
self.apiclient,
|
||||||
|
VirtualMachine.RUNNING)
|
||||||
|
self.assertEqual(response[0], PASS, response[1])
|
||||||
|
|
||||||
|
hosts = Host.list(self.apiclient, id=self.virtual_machine.hostid)
|
||||||
|
if len(hosts) != 1:
|
||||||
|
assert False, "Could not find host with id " + self.virtual_machine.hostid
|
||||||
|
|
||||||
|
host = hosts[0]
|
||||||
|
|
||||||
|
isWindowsIso = False
|
||||||
|
if "Windows" in iso.ostypename:
|
||||||
|
isWindowsIso = True
|
||||||
|
|
||||||
|
instancename = self.virtual_machine.instancename
|
||||||
|
virshxml = self.getVirshXML(host, instancename)
|
||||||
|
self.checkBootTypeAndMode(virshxml, bootmodesecure, isWindowsIso)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def isUefiEnabledOnAtLeastOnHost(cls, hosts):
|
||||||
|
for h in hosts:
|
||||||
|
if h.ueficapability:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
@ -940,6 +940,16 @@ test_data = {
|
|||||||
"ostype": "CentOS 5.6 (64-bit)",
|
"ostype": "CentOS 5.6 (64-bit)",
|
||||||
"mode": 'HTTP_DOWNLOAD',
|
"mode": 'HTTP_DOWNLOAD',
|
||||||
},
|
},
|
||||||
|
"iso3": {
|
||||||
|
"displaytext": "Test ISO 3",
|
||||||
|
"name": "ISO 3",
|
||||||
|
"url": "http://people.apache.org/~tsp/dummy.iso",
|
||||||
|
"isextractable": True,
|
||||||
|
"isfeatured": True,
|
||||||
|
"ispublic": True,
|
||||||
|
"ostype": "Windows Server 2012 (64-bit)",
|
||||||
|
"mode": 'HTTP_DOWNLOAD',
|
||||||
|
},
|
||||||
"isfeatured": True,
|
"isfeatured": True,
|
||||||
"ispublic": True,
|
"ispublic": True,
|
||||||
"isextractable": True,
|
"isextractable": True,
|
||||||
|
|||||||
@ -522,7 +522,7 @@ class VirtualMachine:
|
|||||||
method='GET', hypervisor=None, customcpunumber=None,
|
method='GET', hypervisor=None, customcpunumber=None,
|
||||||
customcpuspeed=None, custommemory=None, rootdisksize=None,
|
customcpuspeed=None, custommemory=None, rootdisksize=None,
|
||||||
rootdiskcontroller=None, vpcid=None, macaddress=None, datadisktemplate_diskoffering_list={},
|
rootdiskcontroller=None, vpcid=None, macaddress=None, datadisktemplate_diskoffering_list={},
|
||||||
properties=None, nicnetworklist=None):
|
properties=None, nicnetworklist=None, bootmode=None, boottype=None):
|
||||||
"""Create the instance"""
|
"""Create the instance"""
|
||||||
|
|
||||||
cmd = deployVirtualMachine.deployVirtualMachineCmd()
|
cmd = deployVirtualMachine.deployVirtualMachineCmd()
|
||||||
@ -657,6 +657,12 @@ class VirtualMachine:
|
|||||||
if nicnetworklist:
|
if nicnetworklist:
|
||||||
cmd.nicnetworklist = nicnetworklist
|
cmd.nicnetworklist = nicnetworklist
|
||||||
|
|
||||||
|
if bootmode:
|
||||||
|
cmd.bootmode = bootmode
|
||||||
|
|
||||||
|
if boottype:
|
||||||
|
cmd.boottype = boottype
|
||||||
|
|
||||||
virtual_machine = apiclient.deployVirtualMachine(cmd, method=method)
|
virtual_machine = apiclient.deployVirtualMachine(cmd, method=method)
|
||||||
|
|
||||||
if 'password' in virtual_machine.__dict__.keys():
|
if 'password' in virtual_machine.__dict__.keys():
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user