use of com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk in project cloudstack by apache.
the class LibvirtComputingResource method createVbd.
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) {
return arg0.getDiskSeq() > arg1.getDiskSeq() ? 1 : -1;
}
});
boolean isUefiEnabled = MapUtils.isNotEmpty(details) && details.containsKey(GuestDef.BootType.UEFI.toString());
if (isUefiEnabled) {
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;
final DataTO data = volume.getData();
if (volume.getType() == Volume.Type.ISO && data.getPath() != null) {
DataStoreTO dataStore = data.getDataStore();
String dataStoreUrl = null;
if (data.getPath().startsWith(ConfigDrive.CONFIGDRIVEDIR) && vmSpec.isConfigDriveOnHostCache() && data instanceof TemplateObjectTO) {
String configDrivePath = getConfigPath() + "/" + data.getPath();
physicalDisk = new KVMPhysicalDisk(configDrivePath, ((TemplateObjectTO) data).getUuid(), null);
physicalDisk.setFormat(PhysicalDiskFormat.FILE);
} else if (dataStore instanceof NfsTO) {
NfsTO nfsStore = (NfsTO) data.getDataStore();
dataStoreUrl = nfsStore.getUrl();
physicalDisk = getPhysicalDiskFromNfsStore(dataStoreUrl, data);
} else if (dataStore instanceof PrimaryDataStoreTO) {
// In order to support directly downloaded ISOs
PrimaryDataStoreTO primaryDataStoreTO = (PrimaryDataStoreTO) dataStore;
if (primaryDataStoreTO.getPoolType().equals(StoragePoolType.NetworkFilesystem)) {
String psHost = primaryDataStoreTO.getHost();
String psPath = primaryDataStoreTO.getPath();
dataStoreUrl = "nfs://" + psHost + File.separator + psPath;
physicalDisk = getPhysicalDiskFromNfsStore(dataStoreUrl, data);
} else if (primaryDataStoreTO.getPoolType().equals(StoragePoolType.SharedMountPoint) || primaryDataStoreTO.getPoolType().equals(StoragePoolType.Filesystem)) {
physicalDisk = getPhysicalDiskPrimaryStore(primaryDataStoreTO, data);
}
}
} else if (volume.getType() != Volume.Type.ISO) {
final PrimaryDataStoreTO store = (PrimaryDataStoreTO) data.getDataStore();
physicalDisk = _storagePoolMgr.getPhysicalDisk(store.getPoolType(), store.getUuid(), data.getPath());
pool = physicalDisk.getPool();
}
String volPath = null;
if (physicalDisk != null) {
volPath = physicalDisk.getPath();
}
if (volume.getType() != Volume.Type.ISO && physicalDisk != null && physicalDisk.getFormat() == PhysicalDiskFormat.QCOW2 && (pool.getType() == StoragePoolType.NetworkFilesystem || pool.getType() == StoragePoolType.SharedMountPoint || pool.getType() == StoragePoolType.Filesystem || pool.getType() == StoragePoolType.Gluster)) {
setBackingFileFormat(physicalDisk.getPath());
}
// check for disk activity, if detected we should exit because vm is running elsewhere
if (_diskActivityCheckEnabled && physicalDisk != null && physicalDisk.getFormat() == PhysicalDiskFormat.QCOW2) {
s_logger.debug("Checking physical disk file at path " + volPath + " for disk activity to ensure vm is not running elsewhere");
try {
HypervisorUtils.checkVolumeFileForActivity(volPath, _diskActivityCheckTimeoutSeconds, _diskActivityInactiveThresholdMilliseconds, _diskActivityCheckFileSizeMin);
} catch (final IOException ex) {
throw new CloudRuntimeException("Unable to check physical disk file for activity", ex);
}
s_logger.debug("Disk activity check cleared");
}
// if params contains a rootDiskController key, use its value (this is what other HVs are doing)
DiskDef.DiskBus diskBusType = getDiskModelFromVMDetail(vmSpec);
if (diskBusType == null) {
diskBusType = getGuestDiskModel(vmSpec.getPlatformEmulator(), isUefiEnabled);
}
DiskDef.DiskBus diskBusTypeData = getDataDiskModelFromVMDetail(vmSpec);
if (diskBusTypeData == null) {
diskBusTypeData = (diskBusType == DiskDef.DiskBus.SCSI) ? diskBusType : DiskDef.DiskBus.VIRTIO;
}
final DiskDef disk = new DiskDef();
int devId = volume.getDiskSeq().intValue();
if (volume.getType() == Volume.Type.ISO) {
disk.defISODisk(volPath, devId, isUefiEnabled);
if (_guestCpuArch != null && _guestCpuArch.equals("aarch64")) {
disk.setBusType(DiskDef.DiskBus.SCSI);
}
} else {
if (diskBusType == DiskDef.DiskBus.SCSI) {
disk.setQemuDriver(true);
disk.setDiscard(DiscardType.UNMAP);
}
setDiskIoDriver(disk);
if (pool.getType() == StoragePoolType.RBD) {
/*
For RBD pools we use the secret mechanism in libvirt.
We store the secret under the UUID of the pool, that's why
we pass the pool's UUID as the authSecret
*/
disk.defNetworkBasedDisk(physicalDisk.getPath().replace("rbd:", ""), pool.getSourceHost(), pool.getSourcePort(), pool.getAuthUserName(), pool.getUuid(), devId, diskBusType, DiskProtocol.RBD, DiskDef.DiskFmtType.RAW);
} else if (pool.getType() == StoragePoolType.PowerFlex) {
disk.defBlockBasedDisk(physicalDisk.getPath(), devId, diskBusTypeData);
} else if (pool.getType() == StoragePoolType.Gluster) {
final String mountpoint = pool.getLocalPath();
final String path = physicalDisk.getPath();
final String glusterVolume = pool.getSourceDir().replace("/", "");
disk.defNetworkBasedDisk(glusterVolume + path.replace(mountpoint, ""), pool.getSourceHost(), pool.getSourcePort(), null, null, devId, diskBusType, DiskProtocol.GLUSTER, DiskDef.DiskFmtType.QCOW2);
} else if (pool.getType() == StoragePoolType.CLVM || physicalDisk.getFormat() == PhysicalDiskFormat.RAW) {
if (volume.getType() == Volume.Type.DATADISK && !(isWindowsTemplate && isUefiEnabled)) {
disk.defBlockBasedDisk(physicalDisk.getPath(), devId, diskBusTypeData);
} else {
disk.defBlockBasedDisk(physicalDisk.getPath(), devId, diskBusType);
}
} else {
if (volume.getType() == Volume.Type.DATADISK && !(isWindowsTemplate && isUefiEnabled)) {
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusTypeData, DiskDef.DiskFmtType.QCOW2);
} else {
if (isSecureBoot) {
disk.defFileBasedDisk(physicalDisk.getPath(), devId, DiskDef.DiskFmtType.QCOW2, isWindowsTemplate);
} else {
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusType, DiskDef.DiskFmtType.QCOW2);
}
}
}
}
if (data instanceof VolumeObjectTO) {
final VolumeObjectTO volumeObjectTO = (VolumeObjectTO) data;
disk.setSerial(diskUuidToSerial(volumeObjectTO.getUuid()));
setBurstProperties(volumeObjectTO, disk);
if (volumeObjectTO.getCacheMode() != null) {
disk.setCacheMode(DiskDef.DiskCacheMode.valueOf(volumeObjectTO.getCacheMode().toString().toUpperCase()));
}
}
if (vm.getDevices() == null) {
s_logger.error("There is no devices for" + vm);
throw new RuntimeException("There is no devices for" + vm);
}
vm.getDevices().addDevice(disk);
}
if (vmSpec.getType() != VirtualMachine.Type.User) {
if (_sysvmISOPath != null) {
final DiskDef iso = new DiskDef();
iso.defISODisk(_sysvmISOPath);
if (_guestCpuArch != null && _guestCpuArch.equals("aarch64")) {
iso.setBusType(DiskDef.DiskBus.SCSI);
}
vm.getDevices().addDevice(iso);
}
}
// For LXC, find and add the root filesystem, rbd data disks
if (HypervisorType.LXC.toString().toLowerCase().equals(vm.getHvsType())) {
for (final DiskTO volume : disks) {
final DataTO data = volume.getData();
final PrimaryDataStoreTO store = (PrimaryDataStoreTO) data.getDataStore();
if (volume.getType() == Volume.Type.ROOT) {
final KVMPhysicalDisk physicalDisk = _storagePoolMgr.getPhysicalDisk(store.getPoolType(), store.getUuid(), data.getPath());
final FilesystemDef rootFs = new FilesystemDef(physicalDisk.getPath(), "/");
vm.getDevices().addDevice(rootFs);
} else if (volume.getType() == Volume.Type.DATADISK) {
final KVMPhysicalDisk physicalDisk = _storagePoolMgr.getPhysicalDisk(store.getPoolType(), store.getUuid(), data.getPath());
final KVMStoragePool pool = physicalDisk.getPool();
if (StoragePoolType.RBD.equals(pool.getType())) {
final int devId = volume.getDiskSeq().intValue();
final String device = mapRbdDevice(physicalDisk);
if (device != null) {
s_logger.debug("RBD device on host is: " + device);
final DiskDef diskdef = new DiskDef();
diskdef.defBlockBasedDisk(device, devId, DiskDef.DiskBus.VIRTIO);
diskdef.setQemuDriver(false);
vm.getDevices().addDevice(diskdef);
} else {
throw new InternalErrorException("Error while mapping RBD device on host");
}
}
}
}
}
}
use of com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk in project cloudstack by apache.
the class LibvirtComputingResourceTest method testPrimaryStorageDownloadCommandNOTemplateDisk.
@Test(expected = NullPointerException.class)
public void testPrimaryStorageDownloadCommandNOTemplateDisk() {
final StoragePool pool = Mockito.mock(StoragePool.class);
final List<KVMPhysicalDisk> disks = new ArrayList<KVMPhysicalDisk>();
final String name = "Test";
final String url = "http://template/";
final ImageFormat format = ImageFormat.QCOW2;
final long accountId = 1l;
final int wait = 0;
final PrimaryStorageDownloadCommand command = new PrimaryStorageDownloadCommand(name, url, format, accountId, pool, wait);
final KVMStoragePoolManager storagePoolMgr = Mockito.mock(KVMStoragePoolManager.class);
final KVMStoragePool primaryPool = Mockito.mock(KVMStoragePool.class);
final KVMStoragePool secondaryPool = Mockito.mock(KVMStoragePool.class);
final KVMPhysicalDisk tmplVol = Mockito.mock(KVMPhysicalDisk.class);
final KVMPhysicalDisk primaryVol = Mockito.mock(KVMPhysicalDisk.class);
final KVMPhysicalDisk disk = new KVMPhysicalDisk("/path", "disk.qcow2", primaryPool);
disks.add(disk);
final int index = url.lastIndexOf("/");
final String mountpoint = url.substring(0, index);
when(libvirtComputingResource.getStoragePoolMgr()).thenReturn(storagePoolMgr);
when(storagePoolMgr.getStoragePoolByURI(mountpoint)).thenReturn(secondaryPool);
when(secondaryPool.listPhysicalDisks()).thenReturn(disks);
when(storagePoolMgr.getStoragePool(command.getPool().getType(), command.getPoolUuid())).thenReturn(primaryPool);
when(storagePoolMgr.copyPhysicalDisk(tmplVol, UUID.randomUUID().toString(), primaryPool, 0)).thenReturn(primaryVol);
final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance();
assertNotNull(wrapper);
final Answer answer = wrapper.execute(command, libvirtComputingResource);
assertFalse(answer.getResult());
verify(libvirtComputingResource, times(1)).getStoragePoolMgr();
}
use of com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk in project cloudstack by apache.
the class LibvirtCreatePrivateTemplateFromVolumeCommandWrapper method execute.
@Override
public Answer execute(final CreatePrivateTemplateFromVolumeCommand command, final LibvirtComputingResource libvirtComputingResource) {
final String secondaryStorageURL = command.getSecondaryStorageUrl();
KVMStoragePool secondaryStorage = null;
KVMStoragePool primary = null;
final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
try {
final String templateFolder = command.getAccountId() + File.separator + command.getTemplateId() + File.separator;
final String templateInstallFolder = "/template/tmpl/" + templateFolder;
secondaryStorage = storagePoolMgr.getStoragePoolByURI(secondaryStorageURL);
try {
primary = storagePoolMgr.getStoragePool(command.getPool().getType(), command.getPrimaryStoragePoolNameLabel());
} catch (final CloudRuntimeException e) {
if (e.getMessage().contains("not found")) {
primary = storagePoolMgr.createStoragePool(command.getPool().getUuid(), command.getPool().getHost(), command.getPool().getPort(), command.getPool().getPath(), command.getPool().getUserInfo(), command.getPool().getType());
} else {
return new CreatePrivateTemplateAnswer(command, false, e.getMessage());
}
}
final KVMPhysicalDisk disk = primary.getPhysicalDisk(command.getVolumePath());
final String tmpltPath = secondaryStorage.getLocalPath() + File.separator + templateInstallFolder;
final StorageLayer storage = libvirtComputingResource.getStorage();
storage.mkdirs(tmpltPath);
if (primary.getType() != StoragePoolType.RBD) {
final String createTmplPath = libvirtComputingResource.createTmplPath();
final int cmdsTimeout = libvirtComputingResource.getCmdsTimeout();
final Script scriptCommand = new Script(createTmplPath, cmdsTimeout, s_logger);
scriptCommand.add("-f", disk.getPath());
scriptCommand.add("-t", tmpltPath);
scriptCommand.add("-n", command.getUniqueName() + ".qcow2");
final String result = scriptCommand.execute();
if (result != null) {
s_logger.debug("failed to create template: " + result);
return new CreatePrivateTemplateAnswer(command, false, result);
}
} else {
s_logger.debug("Converting RBD disk " + disk.getPath() + " into template " + command.getUniqueName());
final QemuImgFile srcFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(primary.getSourceHost(), primary.getSourcePort(), primary.getAuthUserName(), primary.getAuthSecret(), disk.getPath()));
srcFile.setFormat(PhysicalDiskFormat.RAW);
final QemuImgFile destFile = new QemuImgFile(tmpltPath + "/" + command.getUniqueName() + ".qcow2");
destFile.setFormat(PhysicalDiskFormat.QCOW2);
final QemuImg q = new QemuImg(0);
try {
q.convert(srcFile, destFile);
} catch (final QemuImgException | LibvirtException e) {
s_logger.error("Failed to create new template while converting " + srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " + e.getMessage());
}
final File templateProp = new File(tmpltPath + "/template.properties");
if (!templateProp.exists()) {
templateProp.createNewFile();
}
String templateContent = "filename=" + command.getUniqueName() + ".qcow2" + System.getProperty("line.separator");
final DateFormat dateFormat = new SimpleDateFormat("MM_dd_yyyy");
final Date date = new Date();
templateContent += "snapshot.name=" + dateFormat.format(date) + System.getProperty("line.separator");
try (FileOutputStream templFo = new FileOutputStream(templateProp)) {
templFo.write(templateContent.getBytes("UTF-8"));
templFo.flush();
} catch (final IOException ex) {
s_logger.error("CreatePrivateTemplateAnswer:Exception:" + ex.getMessage());
}
}
final Map<String, Object> params = new HashMap<String, Object>();
params.put(StorageLayer.InstanceConfigKey, storage);
final Processor qcow2Processor = new QCOW2Processor();
qcow2Processor.configure("QCOW2 Processor", params);
final FormatInfo info = qcow2Processor.process(tmpltPath, null, command.getUniqueName());
final TemplateLocation loc = new TemplateLocation(storage, tmpltPath);
loc.create(1, true, command.getUniqueName());
loc.addFormat(info);
loc.save();
return new CreatePrivateTemplateAnswer(command, true, null, templateInstallFolder + command.getUniqueName() + ".qcow2", info.virtualSize, info.size, command.getUniqueName(), ImageFormat.QCOW2);
} catch (final InternalErrorException e) {
return new CreatePrivateTemplateAnswer(command, false, e.toString());
} catch (final IOException e) {
return new CreatePrivateTemplateAnswer(command, false, e.toString());
} catch (final ConfigurationException e) {
return new CreatePrivateTemplateAnswer(command, false, e.toString());
} catch (final CloudRuntimeException e) {
return new CreatePrivateTemplateAnswer(command, false, e.toString());
} finally {
if (secondaryStorage != null) {
storagePoolMgr.deleteStoragePool(secondaryStorage.getType(), secondaryStorage.getUuid());
}
}
}
use of com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk in project cloudstack by apache.
the class LibvirtModifyTargetsCommandWrapper method execute.
@Override
public Answer execute(final ModifyTargetsCommand command, final LibvirtComputingResource libvirtComputingResource) {
KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
List<Map<String, String>> targets = command.getTargets();
// When attempting to connect to one or more targets, place the successfully connected path into this List.
List<String> connectedPaths = new ArrayList<>(targets.size());
for (Map<String, String> target : targets) {
StoragePoolType storagePoolType = StoragePoolType.valueOf(target.get(ModifyTargetsCommand.STORAGE_TYPE));
String storageUuid = target.get(ModifyTargetsCommand.STORAGE_UUID);
String path = target.get(ModifyTargetsCommand.IQN);
if (command.getAdd()) {
if (storagePoolMgr.connectPhysicalDisk(storagePoolType, storageUuid, path, target)) {
KVMPhysicalDisk kvmPhysicalDisk = storagePoolMgr.getPhysicalDisk(storagePoolType, storageUuid, path);
connectedPaths.add(kvmPhysicalDisk.getPath());
} else {
throw new CloudRuntimeException("Unable to connect to the following target: " + path);
}
} else {
if (!storagePoolMgr.disconnectPhysicalDisk(storagePoolType, storageUuid, path)) {
throw new CloudRuntimeException("Unable to disconnect from the following target: " + path);
}
}
}
ModifyTargetsAnswer modifyTargetsAnswer = new ModifyTargetsAnswer();
modifyTargetsAnswer.setConnectedPaths(connectedPaths);
return modifyTargetsAnswer;
}
use of com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk in project cloudstack by apache.
the class LibvirtDeleteVMSnapshotCommandWrapper method execute.
@Override
public Answer execute(final DeleteVMSnapshotCommand cmd, final LibvirtComputingResource libvirtComputingResource) {
String vmName = cmd.getVmName();
final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
Domain dm = null;
DomainSnapshot snapshot = null;
DomainInfo.DomainState oldState = null;
boolean tryingResume = false;
Connect conn = null;
try {
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
conn = libvirtUtilitiesHelper.getConnection();
dm = libvirtComputingResource.getDomain(conn, vmName);
snapshot = dm.snapshotLookupByName(cmd.getTarget().getSnapshotName());
oldState = dm.getInfo().state;
if (oldState == DomainInfo.DomainState.VIR_DOMAIN_RUNNING) {
s_logger.debug("Suspending domain " + vmName);
// suspend the vm to avoid image corruption
dm.suspend();
}
// only remove this snapshot, not children
snapshot.delete(0);
if (oldState == DomainInfo.DomainState.VIR_DOMAIN_RUNNING) {
// Resume the VM
tryingResume = true;
dm = libvirtComputingResource.getDomain(conn, vmName);
if (dm.getInfo().state == DomainInfo.DomainState.VIR_DOMAIN_PAUSED) {
dm.resume();
}
}
return new DeleteVMSnapshotAnswer(cmd, cmd.getVolumeTOs());
} catch (LibvirtException e) {
String msg = " Delete VM snapshot failed due to " + e.toString();
if (dm == null) {
s_logger.debug("Can not find running vm: " + vmName + ", now we are trying to delete the vm snapshot using qemu-img if the format of root volume is QCOW2");
VolumeObjectTO rootVolume = null;
for (VolumeObjectTO volume : cmd.getVolumeTOs()) {
if (volume.getVolumeType() == Volume.Type.ROOT) {
rootVolume = volume;
break;
}
}
if (rootVolume != null && ImageFormat.QCOW2.equals(rootVolume.getFormat())) {
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) rootVolume.getDataStore();
KVMPhysicalDisk rootDisk = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), rootVolume.getPath());
String qemu_img_snapshot = Script.runSimpleBashScript("qemu-img snapshot -l " + rootDisk.getPath() + " | tail -n +3 | awk -F ' ' '{print $2}' | grep ^" + cmd.getTarget().getSnapshotName() + "$");
if (qemu_img_snapshot == null) {
s_logger.info("Cannot find snapshot " + cmd.getTarget().getSnapshotName() + " in file " + rootDisk.getPath() + ", return true");
return new DeleteVMSnapshotAnswer(cmd, cmd.getVolumeTOs());
}
int result = Script.runSimpleBashScriptForExitValue("qemu-img snapshot -d " + cmd.getTarget().getSnapshotName() + " " + rootDisk.getPath());
if (result != 0) {
return new DeleteVMSnapshotAnswer(cmd, false, "Delete VM Snapshot Failed due to can not remove snapshot from image file " + rootDisk.getPath() + " : " + result);
} else {
return new DeleteVMSnapshotAnswer(cmd, cmd.getVolumeTOs());
}
}
} else if (snapshot == null) {
s_logger.debug("Can not find vm snapshot " + cmd.getTarget().getSnapshotName() + " on vm: " + vmName + ", return true");
return new DeleteVMSnapshotAnswer(cmd, cmd.getVolumeTOs());
} else if (tryingResume) {
s_logger.error("Failed to resume vm after delete snapshot " + cmd.getTarget().getSnapshotName() + " on vm: " + vmName + " return true : " + e);
return new DeleteVMSnapshotAnswer(cmd, cmd.getVolumeTOs());
}
s_logger.warn(msg, e);
return new DeleteVMSnapshotAnswer(cmd, false, msg);
} finally {
if (dm != null) {
// Make sure if the VM is paused, then resume it, in case we got an exception during our delete() and didn't have the chance before
try {
dm = libvirtComputingResource.getDomain(conn, vmName);
if (oldState == DomainInfo.DomainState.VIR_DOMAIN_RUNNING && dm.getInfo().state == DomainInfo.DomainState.VIR_DOMAIN_PAUSED) {
s_logger.debug("Resuming domain " + vmName);
dm.resume();
}
dm.free();
} catch (LibvirtException e) {
s_logger.error("Failed to resume vm after delete snapshot " + cmd.getTarget().getSnapshotName() + " on vm: " + vmName + " return true : " + e);
}
}
}
}
Aggregations