use of org.apache.cloudstack.storage.to.PrimaryDataStoreTO in project cloudstack by apache.
the class KVMStorageProcessor method copyVolumeFromPrimaryToPrimary.
@Override
public Answer copyVolumeFromPrimaryToPrimary(CopyCommand cmd) {
final DataTO srcData = cmd.getSrcTO();
final DataTO destData = cmd.getDestTO();
final VolumeObjectTO srcVol = (VolumeObjectTO) srcData;
final VolumeObjectTO destVol = (VolumeObjectTO) destData;
final ImageFormat srcFormat = srcVol.getFormat();
final ImageFormat destFormat = destVol.getFormat();
final DataStoreTO srcStore = srcData.getDataStore();
final DataStoreTO destStore = destData.getDataStore();
final PrimaryDataStoreTO srcPrimaryStore = (PrimaryDataStoreTO) srcStore;
final PrimaryDataStoreTO destPrimaryStore = (PrimaryDataStoreTO) destStore;
final String srcVolumePath = srcData.getPath();
final String destVolumePath = destData.getPath();
KVMStoragePool destPool = null;
try {
s_logger.debug("Copying src volume (id: " + srcVol.getId() + ", format: " + srcFormat + ", path: " + srcVolumePath + ", primary storage: [id: " + srcPrimaryStore.getId() + ", type: " + srcPrimaryStore.getPoolType() + "]) to dest volume (id: " + destVol.getId() + ", format: " + destFormat + ", path: " + destVolumePath + ", primary storage: [id: " + destPrimaryStore.getId() + ", type: " + destPrimaryStore.getPoolType() + "]).");
if (srcPrimaryStore.isManaged()) {
if (!storagePoolMgr.connectPhysicalDisk(srcPrimaryStore.getPoolType(), srcPrimaryStore.getUuid(), srcVolumePath, srcPrimaryStore.getDetails())) {
s_logger.warn("Failed to connect src volume at path: " + srcVolumePath + ", in storage pool id: " + srcPrimaryStore.getUuid());
}
}
final KVMPhysicalDisk volume = storagePoolMgr.getPhysicalDisk(srcPrimaryStore.getPoolType(), srcPrimaryStore.getUuid(), srcVolumePath);
if (volume == null) {
s_logger.debug("Failed to get physical disk for volume: " + srcVolumePath);
throw new CloudRuntimeException("Failed to get physical disk for volume at path: " + srcVolumePath);
}
volume.setFormat(PhysicalDiskFormat.valueOf(srcFormat.toString()));
String destVolumeName = null;
if (destPrimaryStore.isManaged()) {
if (!storagePoolMgr.connectPhysicalDisk(destPrimaryStore.getPoolType(), destPrimaryStore.getUuid(), destVolumePath, destPrimaryStore.getDetails())) {
s_logger.warn("Failed to connect dest volume at path: " + destVolumePath + ", in storage pool id: " + destPrimaryStore.getUuid());
}
String managedStoreTarget = destPrimaryStore.getDetails() != null ? destPrimaryStore.getDetails().get("managedStoreTarget") : null;
destVolumeName = managedStoreTarget != null ? managedStoreTarget : destVolumePath;
} else {
final String volumeName = UUID.randomUUID().toString();
destVolumeName = volumeName + "." + destFormat.getFileExtension();
}
destPool = storagePoolMgr.getStoragePool(destPrimaryStore.getPoolType(), destPrimaryStore.getUuid());
try {
storagePoolMgr.copyPhysicalDisk(volume, destVolumeName, destPool, cmd.getWaitInMillSeconds());
} catch (Exception e) {
// Any exceptions while copying the disk, should send failed answer with the error message
String errMsg = String.format("Failed to copy volume: %s to dest storage: %s, due to %s", srcVol.getName(), destPrimaryStore.getName(), e.toString());
s_logger.debug(errMsg, e);
throw new CloudRuntimeException(errMsg);
} finally {
if (srcPrimaryStore.isManaged()) {
storagePoolMgr.disconnectPhysicalDisk(srcPrimaryStore.getPoolType(), srcPrimaryStore.getUuid(), srcVolumePath);
}
if (destPrimaryStore.isManaged()) {
storagePoolMgr.disconnectPhysicalDisk(destPrimaryStore.getPoolType(), destPrimaryStore.getUuid(), destVolumePath);
}
}
final VolumeObjectTO newVol = new VolumeObjectTO();
String path = destPrimaryStore.isManaged() ? destVolumeName : destVolumePath + File.separator + destVolumeName;
newVol.setPath(path);
newVol.setFormat(destFormat);
return new CopyCmdAnswer(newVol);
} catch (final CloudRuntimeException e) {
s_logger.debug("Failed to copyVolumeFromPrimaryToPrimary: ", e);
return new CopyCmdAnswer(e.toString());
}
}
use of org.apache.cloudstack.storage.to.PrimaryDataStoreTO in project cloudstack by apache.
the class KVMStorageProcessor method createSnapshot.
@Override
public Answer createSnapshot(final CreateObjectCommand cmd) {
final SnapshotObjectTO snapshotTO = (SnapshotObjectTO) cmd.getData();
final PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) snapshotTO.getDataStore();
final VolumeObjectTO volume = snapshotTO.getVolume();
final String snapshotName = UUID.randomUUID().toString();
final String vmName = volume.getVmName();
try {
final Connect conn = LibvirtConnection.getConnectionByVmName(vmName);
DomainInfo.DomainState state = null;
Domain vm = null;
if (vmName != null) {
try {
vm = resource.getDomain(conn, vmName);
state = vm.getInfo().state;
} catch (final LibvirtException e) {
s_logger.trace("Ignoring libvirt error.", e);
}
}
final KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid());
final KVMPhysicalDisk disk = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), volume.getPath());
if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING && !primaryPool.isExternalSnapshot()) {
final String vmUuid = vm.getUUIDString();
final Object[] args = new Object[] { snapshotName, vmUuid };
final String snapshot = SnapshotXML.format(args);
final long start = System.currentTimeMillis();
vm.snapshotCreateXML(snapshot);
final long total = (System.currentTimeMillis() - start) / 1000;
s_logger.debug("snapshot takes " + total + " seconds to finish");
/*
* libvirt on RHEL6 doesn't handle resume event emitted from
* qemu
*/
vm = resource.getDomain(conn, vmName);
state = vm.getInfo().state;
if (state == DomainInfo.DomainState.VIR_DOMAIN_PAUSED) {
vm.resume();
}
} else {
/**
* For RBD we can't use libvirt to do our snapshotting or any Bash scripts.
* libvirt also wants to store the memory contents of the Virtual Machine,
* but that's not possible with RBD since there is no way to store the memory
* contents in RBD.
*
* So we rely on the Java bindings for RBD to create our snapshot
*
* This snapshot might not be 100% consistent due to writes still being in the
* memory of the Virtual Machine, but if the VM runs a kernel which supports
* barriers properly (>2.6.32) this won't be any different then pulling the power
* cord out of a running machine.
*/
if (primaryPool.getType() == StoragePoolType.RBD) {
try {
Rados r = radosConnect(primaryPool);
final IoCTX io = r.ioCtxCreate(primaryPool.getSourceDir());
final Rbd rbd = new Rbd(io);
final RbdImage image = rbd.open(disk.getName());
s_logger.debug("Attempting to create RBD snapshot " + disk.getName() + "@" + snapshotName);
image.snapCreate(snapshotName);
rbd.close(image);
r.ioCtxDestroy(io);
} catch (final Exception e) {
s_logger.error("A RBD snapshot operation on " + disk.getName() + " failed. The error was: " + e.getMessage());
}
} else {
/* VM is not running, create a snapshot by ourself */
final Script command = new Script(_manageSnapshotPath, _cmdsTimeout, s_logger);
command.add(MANAGE_SNAPSTHOT_CREATE_OPTION, disk.getPath());
command.add(NAME_OPTION, snapshotName);
final String result = command.execute();
if (result != null) {
s_logger.debug("Failed to manage snapshot: " + result);
return new CreateObjectAnswer("Failed to manage snapshot: " + result);
}
}
}
final SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
// NOTE: sort of hack, we'd better just put snapshtoName
newSnapshot.setPath(disk.getPath() + File.separator + snapshotName);
return new CreateObjectAnswer(newSnapshot);
} catch (final LibvirtException e) {
s_logger.debug("Failed to manage snapshot: ", e);
return new CreateObjectAnswer("Failed to manage snapshot: " + e.toString());
}
}
use of org.apache.cloudstack.storage.to.PrimaryDataStoreTO in project cloudstack by apache.
the class KVMStorageProcessor method dettachVolume.
@Override
public Answer dettachVolume(final DettachCommand cmd) {
final DiskTO disk = cmd.getDisk();
final VolumeObjectTO vol = (VolumeObjectTO) disk.getData();
final PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) vol.getDataStore();
final String vmName = cmd.getVmName();
final String serial = resource.diskUuidToSerial(vol.getUuid());
try {
final Connect conn = LibvirtConnection.getConnectionByVmName(vmName);
final KVMPhysicalDisk phyDisk = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), vol.getPath());
final String volCacheMode = vol.getCacheMode() == null ? null : vol.getCacheMode().toString();
attachOrDetachDisk(conn, false, vmName, phyDisk, disk.getDiskSeq().intValue(), serial, vol.getBytesReadRate(), vol.getBytesReadRateMax(), vol.getBytesReadRateMaxLength(), vol.getBytesWriteRate(), vol.getBytesWriteRateMax(), vol.getBytesWriteRateMaxLength(), vol.getIopsReadRate(), vol.getIopsReadRateMax(), vol.getIopsReadRateMaxLength(), vol.getIopsWriteRate(), vol.getIopsWriteRateMax(), vol.getIopsWriteRateMaxLength(), volCacheMode);
storagePoolMgr.disconnectPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), vol.getPath());
return new DettachAnswer(disk);
} catch (final LibvirtException e) {
s_logger.debug("Failed to detach volume: " + vol.getPath() + ", due to ", e);
return new DettachAnswer(e.toString());
} catch (final InternalErrorException e) {
s_logger.debug("Failed to detach volume: " + vol.getPath() + ", due to ", e);
return new DettachAnswer(e.toString());
} catch (final CloudRuntimeException e) {
s_logger.debug("Failed to detach volume: " + vol.getPath() + ", due to ", e);
return new DettachAnswer(e.toString());
}
}
use of org.apache.cloudstack.storage.to.PrimaryDataStoreTO in project cloudstack by apache.
the class KVMStorageProcessor method backupSnapshot.
@Override
public Answer backupSnapshot(final CopyCommand cmd) {
final DataTO srcData = cmd.getSrcTO();
final DataTO destData = cmd.getDestTO();
final SnapshotObjectTO snapshot = (SnapshotObjectTO) srcData;
final PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) snapshot.getDataStore();
final SnapshotObjectTO destSnapshot = (SnapshotObjectTO) destData;
final DataStoreTO imageStore = destData.getDataStore();
if (!(imageStore instanceof NfsTO)) {
return backupSnapshotForObjectStore(cmd);
}
final NfsTO nfsImageStore = (NfsTO) imageStore;
final String secondaryStoragePoolUrl = nfsImageStore.getUrl();
// NOTE: snapshot name is encoded in snapshot path
final int index = snapshot.getPath().lastIndexOf("/");
// -1 means the snapshot is created from existing vm snapshot
final boolean isCreatedFromVmSnapshot = (index == -1) ? true : false;
final String snapshotName = snapshot.getPath().substring(index + 1);
String descName = snapshotName;
final String volumePath = snapshot.getVolume().getPath();
String snapshotDestPath = null;
String snapshotRelPath = null;
final String vmName = snapshot.getVmName();
KVMStoragePool secondaryStoragePool = null;
Connect conn = null;
KVMPhysicalDisk snapshotDisk = null;
KVMStoragePool primaryPool = null;
try {
conn = LibvirtConnection.getConnectionByVmName(vmName);
secondaryStoragePool = storagePoolMgr.getStoragePoolByURI(secondaryStoragePoolUrl);
final String ssPmountPath = secondaryStoragePool.getLocalPath();
snapshotRelPath = destSnapshot.getPath();
snapshotDestPath = ssPmountPath + File.separator + snapshotRelPath;
snapshotDisk = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), volumePath);
primaryPool = snapshotDisk.getPool();
long size = 0;
/**
* Since Ceph version Dumpling (0.67.X) librbd / Qemu supports converting RBD
* snapshots to RAW/QCOW2 files directly.
*
* This reduces the amount of time and storage it takes to back up a snapshot dramatically
*/
if (primaryPool.getType() == StoragePoolType.RBD) {
final String rbdSnapshot = snapshotDisk.getPath() + "@" + snapshotName;
final String snapshotFile = snapshotDestPath + "/" + snapshotName;
try {
s_logger.debug("Attempting to backup RBD snapshot " + rbdSnapshot);
final File snapDir = new File(snapshotDestPath);
s_logger.debug("Attempting to create " + snapDir.getAbsolutePath() + " recursively for snapshot storage");
FileUtils.forceMkdir(snapDir);
final QemuImgFile srcFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(primaryPool.getSourceHost(), primaryPool.getSourcePort(), primaryPool.getAuthUserName(), primaryPool.getAuthSecret(), rbdSnapshot));
srcFile.setFormat(snapshotDisk.getFormat());
final QemuImgFile destFile = new QemuImgFile(snapshotFile);
destFile.setFormat(PhysicalDiskFormat.QCOW2);
s_logger.debug("Backing up RBD snapshot " + rbdSnapshot + " to " + snapshotFile);
final QemuImg q = new QemuImg(cmd.getWaitInMillSeconds());
q.convert(srcFile, destFile);
final File snapFile = new File(snapshotFile);
if (snapFile.exists()) {
size = snapFile.length();
}
s_logger.debug("Finished backing up RBD snapshot " + rbdSnapshot + " to " + snapshotFile + " Snapshot size: " + toHumanReadableSize(size));
} catch (final FileNotFoundException e) {
s_logger.error("Failed to open " + snapshotDestPath + ". The error was: " + e.getMessage());
return new CopyCmdAnswer(e.toString());
} catch (final IOException e) {
s_logger.error("Failed to create " + snapshotDestPath + ". The error was: " + e.getMessage());
return new CopyCmdAnswer(e.toString());
} catch (final QemuImgException | LibvirtException e) {
s_logger.error("Failed to backup the RBD snapshot from " + rbdSnapshot + " to " + snapshotFile + " the error was: " + e.getMessage());
return new CopyCmdAnswer(e.toString());
}
} else {
final Script command = new Script(_manageSnapshotPath, cmd.getWaitInMillSeconds(), s_logger);
command.add("-b", snapshotDisk.getPath());
command.add(NAME_OPTION, snapshotName);
command.add("-p", snapshotDestPath);
if (isCreatedFromVmSnapshot) {
descName = UUID.randomUUID().toString();
}
command.add("-t", descName);
final String result = command.execute();
if (result != null) {
s_logger.debug("Failed to backup snaptshot: " + result);
return new CopyCmdAnswer(result);
}
final File snapFile = new File(snapshotDestPath + "/" + descName);
if (snapFile.exists()) {
size = snapFile.length();
}
}
final SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
newSnapshot.setPath(snapshotRelPath + File.separator + descName);
newSnapshot.setPhysicalSize(size);
return new CopyCmdAnswer(newSnapshot);
} catch (final LibvirtException e) {
s_logger.debug("Failed to backup snapshot: ", e);
return new CopyCmdAnswer(e.toString());
} catch (final CloudRuntimeException e) {
s_logger.debug("Failed to backup snapshot: ", e);
return new CopyCmdAnswer(e.toString());
} finally {
if (isCreatedFromVmSnapshot) {
s_logger.debug("Ignoring removal of vm snapshot on primary as this snapshot is created from vm snapshot");
} else {
try {
/* Delete the snapshot on primary */
DomainInfo.DomainState state = null;
Domain vm = null;
if (vmName != null) {
try {
vm = resource.getDomain(conn, vmName);
state = vm.getInfo().state;
} catch (final LibvirtException e) {
s_logger.trace("Ignoring libvirt error.", e);
}
}
final KVMStoragePool primaryStorage = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid());
if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING && !primaryStorage.isExternalSnapshot()) {
final DomainSnapshot snap = vm.snapshotLookupByName(snapshotName);
try {
s_logger.info(String.format("Suspending VM '%s' to delete snapshot,", vm.getName()));
vm.suspend();
} catch (final LibvirtException e) {
s_logger.error("Failed to suspend the VM", e);
throw e;
}
snap.delete(0);
/*
* libvirt on RHEL6 doesn't handle resume event emitted from
* qemu
*/
vm = resource.getDomain(conn, vmName);
state = vm.getInfo().state;
if (state == DomainInfo.DomainState.VIR_DOMAIN_PAUSED) {
vm.resume();
}
} else {
if (primaryPool.getType() != StoragePoolType.RBD) {
deleteSnapshotViaManageSnapshotScript(snapshotName, snapshotDisk);
}
}
} catch (final Exception ex) {
s_logger.error("Failed to delete snapshots on primary", ex);
}
}
try {
if (secondaryStoragePool != null) {
secondaryStoragePool.delete();
}
} catch (final Exception ex) {
s_logger.debug("Failed to delete secondary storage", ex);
}
}
}
use of org.apache.cloudstack.storage.to.PrimaryDataStoreTO in project cloudstack by apache.
the class KVMStorageProcessor method createVolume.
@Override
public Answer createVolume(final CreateObjectCommand cmd) {
final VolumeObjectTO volume = (VolumeObjectTO) cmd.getData();
final PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) volume.getDataStore();
KVMStoragePool primaryPool = null;
KVMPhysicalDisk vol = null;
long disksize;
try {
primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid());
disksize = volume.getSize();
PhysicalDiskFormat format;
if (volume.getFormat() == null || StoragePoolType.RBD.equals(primaryStore.getPoolType())) {
format = primaryPool.getDefaultFormat();
} else {
format = PhysicalDiskFormat.valueOf(volume.getFormat().toString().toUpperCase());
}
MigrationOptions migrationOptions = volume.getMigrationOptions();
if (migrationOptions != null) {
String srcStoreUuid = migrationOptions.getSrcPoolUuid();
StoragePoolType srcPoolType = migrationOptions.getSrcPoolType();
KVMStoragePool srcPool = storagePoolMgr.getStoragePool(srcPoolType, srcStoreUuid);
int timeout = migrationOptions.getTimeout();
if (migrationOptions.getType() == MigrationOptions.Type.LinkedClone) {
vol = createLinkedCloneVolume(migrationOptions, srcPool, primaryPool, volume, format, timeout);
} else if (migrationOptions.getType() == MigrationOptions.Type.FullClone) {
vol = createFullCloneVolume(migrationOptions, volume, primaryPool, format);
}
} else {
vol = primaryPool.createPhysicalDisk(volume.getUuid(), format, volume.getProvisioningType(), disksize);
}
final VolumeObjectTO newVol = new VolumeObjectTO();
if (vol != null) {
newVol.setPath(vol.getName());
}
newVol.setSize(volume.getSize());
newVol.setFormat(ImageFormat.valueOf(format.toString().toUpperCase()));
return new CreateObjectAnswer(newVol);
} catch (final Exception e) {
s_logger.debug("Failed to create volume: ", e);
return new CreateObjectAnswer(e.toString());
}
}
Aggregations