bug 10330: refactor storage code befor merge clvm code

This commit is contained in:
Edison Su 2011-10-31 20:13:58 -07:00
parent 2bfcb3e27b
commit dd6ed6b108
15 changed files with 1266 additions and 722 deletions

View File

@ -82,6 +82,9 @@ import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
import com.cloud.agent.api.CreateStoragePoolCommand;
import com.cloud.agent.api.CreateVolumeFromSnapshotAnswer;
import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
import com.cloud.agent.api.DeleteSnapshotBackupAnswer;
import com.cloud.agent.api.DeleteSnapshotBackupCommand;
import com.cloud.agent.api.DeleteSnapshotsDirCommand;
import com.cloud.agent.api.DeleteStoragePoolCommand;
import com.cloud.agent.api.FenceAnswer;
import com.cloud.agent.api.FenceCommand;
@ -164,6 +167,10 @@ import com.cloud.agent.resource.computing.LibvirtVMDef.InterfaceDef.hostNicType;
import com.cloud.agent.resource.computing.LibvirtVMDef.SerialDef;
import com.cloud.agent.resource.computing.LibvirtVMDef.TermPolicy;
import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource;
import com.cloud.agent.storage.KVMPhysicalDisk;
import com.cloud.agent.storage.KVMStoragePool;
import com.cloud.agent.storage.KVMStoragePoolManager;
import com.cloud.agent.storage.LibvirtStorageAdaptor;
import com.cloud.dc.Vlan;
import com.cloud.exception.InternalErrorException;
import com.cloud.host.Host.Type;
@ -175,6 +182,7 @@ import com.cloud.resource.ServerResource;
import com.cloud.resource.ServerResourceBase;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StorageLayer;
import com.cloud.storage.Volume;
import com.cloud.storage.template.Processor;
@ -239,6 +247,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
private final String _SSHPUBKEYPATH = _SSHKEYSPATH + File.separator + "id_rsa.pub.cloud";
private String _mountPoint = "/mnt";
StorageLayer _storage;
private KVMStoragePoolManager _storagePoolMgr;
private static final class KeyValueInterpreter extends OutputInterpreter {
private final Map<String, String> map = new HashMap<String, String>();
@ -318,7 +327,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
protected List<String> _vmsKilled = new ArrayList<String>();
private VirtualRoutingResource _virtRouterResource;
protected LibvirtStorageResource _storageResource;
private String _pingTestPath;
@ -416,6 +424,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
return false;
}
try {
Class<?> clazz = Class.forName("com.cloud.storage.JavaStorageLayer");
_storage = (StorageLayer)ComponentLocator.inject(clazz);
@ -424,6 +434,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
throw new ConfigurationException("Unable to find class " + "com.cloud.storage.JavaStorageLayer");
}
_storagePoolMgr = new KVMStoragePoolManager(_storage);
_virtRouterResource = new VirtualRoutingResource();
@ -681,8 +693,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
_mountPoint = "/mnt";
}
_storageResource = new LibvirtStorageResource(this, _storage, _createvmPath, _timeout, _mountPoint, _monitor);
saveProperties(params);
return true;
@ -932,47 +942,33 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
String volumePath = cmd.getVolumePath();
StorageFilerTO pool = cmd.getPool();
String secondaryStorageUrl = cmd.getSecondaryStorageURL();
StoragePool primaryPool = null;
Connect conn;
try {
conn = LibvirtConnection.getConnection();
primaryPool = _storageResource.getStoragePool(conn, pool.getUuid());
LibvirtStoragePoolDef primary = _storageResource.getStoragePoolDef(conn, primaryPool);
String primaryMountPath = primary.getTargetPath();
try {
KVMStoragePool primaryPool = _storagePoolMgr.getStoragePool(pool.getUuid());
String volumeName = UUID.randomUUID().toString();
StoragePool secondaryStoragePool = _storageResource.getStoragePoolbyURI(conn, new URI(secondaryStorageUrl));
LibvirtStoragePoolDef spd = _storageResource.getStoragePoolDef(conn, secondaryStoragePool);
String ssPmountPath = spd.getTargetPath();
String volumeName = UUID.randomUUID().toString();
if (copyToSecondary) {
StorageVol volume = _storageResource.getVolume(conn, primaryPool, volumePath);
String volumeDestPath = ssPmountPath + File.separator + "volumes/" + cmd.getVolumeId() + File.separator;
_storageResource.copyVolume(volumePath, volumeDestPath, volumeName, _cmdsTimeout);
return new CopyVolumeAnswer(cmd, true, null, null, volumeName);
} else {
volumePath = ssPmountPath + File.separator + "volumes/" + cmd.getVolumeId() + File.separator + volumePath;
_storageResource.copyVolume(volumePath, primaryMountPath, volumeName, _cmdsTimeout);
return new CopyVolumeAnswer(cmd, true, null, null, primaryMountPath + File.separator + volumeName);
}
} catch (LibvirtException e) {
return new CopyVolumeAnswer(cmd, false, e.toString(), null, null);
} catch (URISyntaxException e) {
return new CopyVolumeAnswer(cmd, false, e.toString(), null, null);
} catch (InternalErrorException e) {
return new CopyVolumeAnswer(cmd, false, e.toString(), null, null);
}
}
if (copyToSecondary) {
KVMPhysicalDisk volume = primaryPool.getPhysicalDisk(cmd.getVolumePath());
String volumeDestPath = "/volumes/" + cmd.getVolumeId() + File.separator;
KVMStoragePool secondaryStoragePool = _storagePoolMgr.getStoragePoolByURI(secondaryStorageUrl + volumeDestPath);
_storagePoolMgr.copyPhysicalDisk(volume, volumeName, secondaryStoragePool);
return new CopyVolumeAnswer(cmd, true, null, null, volumeName);
} else {
volumePath = "/volumes/" + cmd.getVolumeId() + File.separator + volumePath;
KVMStoragePool secondaryStoragePool = _storagePoolMgr.getStoragePoolByURI(secondaryStorageUrl + volumePath);
KVMPhysicalDisk volume = secondaryStoragePool.getPhysicalDisk(cmd.getVolumePath());
_storagePoolMgr.copyPhysicalDisk(volume, volumeName, primaryPool);
return new CopyVolumeAnswer(cmd, true, null, null, volumeName);
}
} catch (CloudRuntimeException e) {
return new CopyVolumeAnswer(cmd, false, e.toString(), null, null);
}
}
protected Answer execute(DeleteStoragePoolCommand cmd) {
try {
Connect conn = LibvirtConnection.getConnection();
_storageResource.deleteStoragePool(conn, cmd.getPool());
_storagePoolMgr.deleteStoragePool(cmd.getPool().getUuid());
return new Answer(cmd);
} catch (LibvirtException e) {
} catch (CloudRuntimeException e) {
return new Answer(cmd, false, e.toString());
}
}
@ -1006,48 +1002,32 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
protected Answer execute(CreateCommand cmd) {
StorageFilerTO pool = cmd.getPool();
DiskProfile dskch = cmd.getDiskCharacteristics();
StorageVol tmplVol = null;
StoragePool primaryPool = null;
StorageVol vol = null;
KVMPhysicalDisk BaseVol = null;
KVMStoragePool primaryPool = null;
KVMPhysicalDisk vol = null;
long disksize;
try {
Connect conn = LibvirtConnection.getConnection();
primaryPool = _storageResource.getStoragePool(conn, pool.getUuid());
primaryPool = _storagePoolMgr.getStoragePool(pool.getUuid());
if (cmd.getTemplateUrl() != null) {
tmplVol = _storageResource.getVolume(conn, primaryPool, cmd.getTemplateUrl());
vol = _storageResource.createVolumeFromTempl(primaryPool, tmplVol);
BaseVol = primaryPool.getPhysicalDisk(cmd.getTemplateUrl());
vol = _storagePoolMgr.createDiskFromTemplate(BaseVol, UUID.randomUUID().toString(), primaryPool);
if (vol == null) {
return new Answer(cmd, false, " Can't create storage volume on storage pool");
}
disksize = tmplVol.getInfo().capacity;
disksize = vol.getSize();
} else {
disksize = dskch.getSize();
vol = _storageResource.createVolume(conn, primaryPool, UUID.randomUUID().toString(), dskch.getSize(), volFormat.QCOW2);
vol = primaryPool.createPhysicalDisk(UUID.randomUUID().toString(), dskch.getSize());
}
VolumeTO volume = new VolumeTO(cmd.getVolumeId(), dskch.getType(), pool.getType(), pool.getUuid(),
pool.getPath(), vol.getName(), vol.getKey(),disksize, null);
pool.getPath(), vol.getName(), vol.getName(), disksize, null);
return new CreateAnswer(cmd, volume);
} catch (LibvirtException e) {
} catch (CloudRuntimeException e) {
s_logger.debug("Failed to create volume: " + e.toString());
return new CreateAnswer(cmd, e);
} finally {
try {
if (vol != null) {
vol.free();
}
if (tmplVol != null) {
tmplVol.free();
}
if (primaryPool != null) {
primaryPool.free();
}
} catch (LibvirtException e) {
}
}
}
@ -1055,13 +1035,11 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
VolumeTO vol = cmd.getVolume();
try {
Connect conn = LibvirtConnection.getConnection();
StoragePool pool = _storageResource.getStoragePool(conn, vol.getPoolUuid());
StorageVol volume = _storageResource.getVolume(conn, pool, vol.getPath());
volume.delete(0);
volume.free();
KVMStoragePool pool = _storagePoolMgr.getStoragePool(vol.getPoolUuid());
pool.deletePhysicalDisk(vol.getName());
return new Answer(cmd, true, "Success");
} catch (LibvirtException e) {
} catch (CloudRuntimeException e) {
s_logger.debug("Failed to delete volume: " + e.toString());
return new Answer(cmd, false, e.toString());
}
@ -1171,7 +1149,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
}
}
if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING) {
KVMStoragePool primaryPool = _storagePoolMgr.getStoragePool(cmd.getPool().getUuid());
if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING && !primaryPool.isExternalSnapshot()) {
String vmUuid = vm.getUUIDString();
Object[] args = new Object[] {snapshotName, vmUuid};
String snapshot = SnapshotXML.format(args);
@ -1220,13 +1199,17 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
String snapshotName = cmd.getSnapshotName();
String snapshotPath = cmd.getVolumePath();
String snapshotDestPath = null;
String snapshotRelPath = null;
String vmName = cmd.getVmName();
try {
Connect conn = LibvirtConnection.getConnection();
StoragePool secondaryStoragePool = _storageResource.getStoragePoolbyURI(conn, new URI(secondaryStoragePoolUrl));
LibvirtStoragePoolDef spd = _storageResource.getStoragePoolDef(conn, secondaryStoragePool);
String ssPmountPath = spd.getTargetPath();
KVMStoragePool secondaryStoragePool = _storagePoolMgr.getStoragePoolByURI(secondaryStoragePoolUrl);
String ssPmountPath = secondaryStoragePool.getLocalPath();
snapshotRelPath = File.separator + "snapshots" + File.separator + dcId + File.separator + accountId + File.separator + volumeId;
snapshotDestPath = ssPmountPath + File.separator + "snapshots" + File.separator + dcId + File.separator + accountId + File.separator + volumeId;
Script command = new Script(_manageSnapshotPath, _cmdsTimeout, s_logger);
command.add("-b", snapshotPath);
@ -1251,7 +1234,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
}
}
if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING) {
KVMStoragePool primaryStorage = _storagePoolMgr.getStoragePool(cmd.getPool().getUuid());
if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING && !primaryStorage.isExternalSnapshot()) {
String vmUuid = vm.getUUIDString();
Object[] args = new Object[] {snapshotName, vmUuid};
String snapshot = SnapshotXML.format(args);
@ -1277,37 +1261,72 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
}
} catch (LibvirtException e) {
return new BackupSnapshotAnswer(cmd, false, e.toString(), null, true);
} catch (URISyntaxException e) {
} catch (CloudRuntimeException e) {
return new BackupSnapshotAnswer(cmd, false, e.toString(), null, true);
}
return new BackupSnapshotAnswer(cmd, true, null, snapshotDestPath + File.separator + snapshotName, true);
return new BackupSnapshotAnswer(cmd, true, null, snapshotRelPath + File.separator + snapshotName, true);
}
protected DeleteSnapshotBackupAnswer execute(final DeleteSnapshotBackupCommand cmd) {
Long dcId = cmd.getDataCenterId();
Long accountId = cmd.getAccountId();
Long volumeId = cmd.getVolumeId();
try {
KVMStoragePool secondaryStoragePool = _storagePoolMgr.getStoragePoolByURI(cmd.getSecondaryStorageUrl());
String ssPmountPath = secondaryStoragePool.getLocalPath();
String snapshotDestPath = ssPmountPath + File.separator + "snapshots" + File.separator + dcId + File.separator + accountId + File.separator + volumeId;
final Script command = new Script(_manageSnapshotPath, _cmdsTimeout, s_logger);
command.add("-d", snapshotDestPath);
command.add("-n", cmd.getSnapshotName());
command.execute();
} catch (CloudRuntimeException e) {
return new DeleteSnapshotBackupAnswer(cmd, false, e.toString());
}
return new DeleteSnapshotBackupAnswer(cmd, true, null);
}
protected Answer execute(DeleteSnapshotsDirCommand cmd) {
Long dcId = cmd.getDcId();
Long accountId = cmd.getAccountId();
Long volumeId = cmd.getVolumeId();
try {
KVMStoragePool secondaryStoragePool = _storagePoolMgr.getStoragePoolByURI(cmd.getSecondaryStorageUrl());
String ssPmountPath = secondaryStoragePool.getLocalPath();
String snapshotDestPath = ssPmountPath + File.separator + "snapshots" + File.separator + dcId + File.separator + accountId + File.separator + volumeId;
final Script command = new Script(_manageSnapshotPath, _cmdsTimeout, s_logger);
command.add("-d", snapshotDestPath);
command.add("-f");
command.execute();
} catch (CloudRuntimeException e) {
return new Answer(cmd, false, e.toString());
}
return new Answer(cmd, true, null);
}
protected CreateVolumeFromSnapshotAnswer execute(final CreateVolumeFromSnapshotCommand cmd) {
try {
Connect conn = LibvirtConnection.getConnection();
/*Make sure secondary storage is mounted*/
_storageResource.getStoragePoolbyURI(conn, new URI(cmd.getSecondaryStorageUrl()));
String snapshotPath = cmd.getSnapshotUuid();
String primaryUuid = cmd.getPrimaryStoragePoolNameLabel();
StoragePool primaryPool = _storageResource.getStoragePool(conn, primaryUuid);
LibvirtStoragePoolDef spd = _storageResource.getStoragePoolDef(conn, primaryPool);
String primaryPath = spd.getTargetPath();
String volUuid = UUID.randomUUID().toString();
String volPath = primaryPath + File.separator + volUuid;
String result = executeBashScript("cp " + snapshotPath + " " + volPath);
if (result != null) {
return new CreateVolumeFromSnapshotAnswer(cmd, false, result, null);
}
return new CreateVolumeFromSnapshotAnswer(cmd, true, "", volPath);
} catch (LibvirtException e) {
return new CreateVolumeFromSnapshotAnswer(cmd, false, e.toString(), null);
} catch (URISyntaxException e) {
return new CreateVolumeFromSnapshotAnswer(cmd, false, e.toString(), null);
} finally {
int index = snapshotPath.lastIndexOf("/");
snapshotPath = snapshotPath.substring(0, index);
KVMStoragePool secondaryPool = _storagePoolMgr.getStoragePoolByURI(cmd.getSecondaryStorageUrl() + snapshotPath);
KVMPhysicalDisk snapshot = secondaryPool.getPhysicalDisk(cmd.getSnapshotName());
String primaryUuid = cmd.getPrimaryStoragePoolNameLabel();
KVMStoragePool primaryPool = _storagePoolMgr.getStoragePool(primaryUuid);
String volUuid = UUID.randomUUID().toString();
KVMPhysicalDisk disk = _storagePoolMgr.createDiskFromSnapshot(snapshot, cmd.getSnapshotName(), volUuid, primaryPool);
return new CreateVolumeFromSnapshotAnswer(cmd, true, "", disk.getPath());
} catch (CloudRuntimeException e) {
return new CreateVolumeFromSnapshotAnswer(cmd, false, e.toString(), null);
}
}
@ -1323,12 +1342,14 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
String snapshotPath = cmd.getSnapshotUuid();
String tmplName = UUID.randomUUID().toString();
String tmplFileName = tmplName + ".qcow2";
StoragePool secondaryPool;
KVMStoragePool secondaryPool;
try {
Connect conn = LibvirtConnection.getConnection();
secondaryPool = _storageResource.getStoragePoolbyURI(conn, new URI(cmd.getSecondaryStorageUrl()));
LibvirtStoragePoolDef spd = _storageResource.getStoragePoolDef(conn, secondaryPool);
String templatePath = spd.getTargetPath() + File.separator + templateInstallFolder;
secondaryPool = _storagePoolMgr.getStoragePoolByURI(cmd.getSecondaryStorageUrl());
String templatePath = secondaryPool.getLocalPath() + File.separator + templateInstallFolder;
_storage.mkdirs(templatePath);
String tmplPath = templateInstallFolder + File.separator + tmplFileName;
@ -1350,47 +1371,23 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
loc.save();
return new CreatePrivateTemplateAnswer(cmd, true, "", tmplPath, info.virtualSize, info.size, tmplName, info.format);
} catch (LibvirtException e) {
return new CreatePrivateTemplateAnswer(cmd, false, e.getMessage());
} catch (URISyntaxException e) {
return new CreatePrivateTemplateAnswer(cmd, false, e.getMessage());
} catch (ConfigurationException e) {
return new CreatePrivateTemplateAnswer(cmd, false, e.getMessage());
} catch (InternalErrorException e) {
return new CreatePrivateTemplateAnswer(cmd, false, e.getMessage());
} catch (IOException e) {
return new CreatePrivateTemplateAnswer(cmd, false, e.getMessage());
} catch (CloudRuntimeException e) {
return new CreatePrivateTemplateAnswer(cmd, false, e.getMessage());
}
}
protected GetStorageStatsAnswer execute(final GetStorageStatsCommand cmd) {
StoragePool sp = null;
try {
Connect conn = LibvirtConnection.getConnection();
sp = _storageResource.getStoragePool(conn, cmd.getStorageId());
LibvirtStoragePoolDef spd = _storageResource.getStoragePoolDef(conn, sp);
String mountPoint = spd.getTargetPath();
Script statsScript = new Script("/bin/bash", s_logger);
statsScript.add("-c");
statsScript.add("stats=$(df --total " + mountPoint + " |grep total|awk '{print $2,$3}');echo $stats");
final OutputInterpreter.OneLineParser statsParser = new OutputInterpreter.OneLineParser();
String result = statsScript.execute(statsParser);
if (result != null) {
return new GetStorageStatsAnswer(cmd, result);
}
String stats = statsParser.getLine();
if (stats != null && !stats.isEmpty()) {
String sizes[] = stats.trim().split(" ");
if (sizes.length != 2) {
return new GetStorageStatsAnswer(cmd, "Failed to parse the result: " + stats);
}
return new GetStorageStatsAnswer(cmd, Long.parseLong(sizes[0]) * 1024, Long.parseLong(sizes[1]) * 1024);
} else {
return new GetStorageStatsAnswer(cmd, "Failed to parse result from df");
}
} catch (LibvirtException e) {
KVMStoragePool sp = _storagePoolMgr.getStoragePool(cmd.getStorageId());
return new GetStorageStatsAnswer(cmd, sp.getCapacity(), sp.getUsed());
} catch (CloudRuntimeException e) {
return new GetStorageStatsAnswer(cmd, e.toString());
}
}
@ -1398,16 +1395,16 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
protected CreatePrivateTemplateAnswer execute(CreatePrivateTemplateFromVolumeCommand cmd) {
String secondaryStorageURL = cmd.getSecondaryStorageUrl();
StoragePool secondaryStorage = null;
KVMStoragePool secondaryStorage = null;
try {
Connect conn = LibvirtConnection.getConnection();
String templateFolder = cmd.getAccountId() + File.separator + cmd.getTemplateId() + File.separator;
String templateInstallFolder = "/template/tmpl/" + templateFolder;
secondaryStorage = _storageResource.getStoragePoolbyURI(conn, new URI(secondaryStorageURL));
secondaryStorage = _storagePoolMgr.getStoragePoolByURI(secondaryStorageURL);
LibvirtStoragePoolDef spd = _storageResource.getStoragePoolDef(conn, secondaryStorage);
String tmpltPath = spd.getTargetPath() + File.separator + templateInstallFolder;
String tmpltPath = secondaryStorage.getLocalPath() + File.separator + templateInstallFolder;
_storage.mkdirs(tmpltPath);
Script command = new Script(_createTmplPath, _timeout, s_logger);
@ -1443,8 +1440,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
info.size,
cmd.getUniqueName(),
ImageFormat.QCOW2);
} catch (URISyntaxException e) {
return new CreatePrivateTemplateAnswer(cmd, false, e.toString());
} catch (LibvirtException e) {
s_logger.debug("Failed to get secondary storage pool: " + e.toString());
return new CreatePrivateTemplateAnswer(cmd, false, e.toString());
@ -1452,9 +1447,10 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
return new CreatePrivateTemplateAnswer(cmd, false, e.toString());
} catch (IOException e) {
return new CreatePrivateTemplateAnswer(cmd, false, e.toString());
} catch (ConfigurationException e) {
return new CreatePrivateTemplateAnswer(cmd, false, e.toString());
} catch (CloudRuntimeException e) {
return new CreatePrivateTemplateAnswer(cmd, false, e.toString());
}
}
@ -1467,70 +1463,38 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
tmpltname = tmplturl.substring(index + 1);
}
StoragePool secondaryPool = null;
StoragePool primaryPool = null;
StorageVol tmplVol = null;
StorageVol primaryVol = null;
Connect conn = null;
KVMPhysicalDisk tmplVol = null;
try {
conn = LibvirtConnection.getConnection();
secondaryPool = _storageResource.getStoragePoolbyURI(conn, new URI(mountpoint));
KVMStoragePool secondaryPool = _storagePoolMgr.getStoragePoolByURI(mountpoint);
/*Get template vol*/
if (tmpltname == null) {
/*Hack: server just pass the directory of system vm template, need to scan the folder */
_storageResource.storagePoolRefresh(secondaryPool);
String[] volumes = secondaryPool.listVolumes();
if (volumes == null) {
return new PrimaryStorageDownloadAnswer("Failed to get volumes from pool: " + secondaryPool.getName());
secondaryPool.refresh();
List<KVMPhysicalDisk> disks = secondaryPool.listPhysicalDisks();
if (disks == null || disks.isEmpty()) {
return new PrimaryStorageDownloadAnswer("Failed to get volumes from pool: " + secondaryPool.getUuid());
}
for (String volumeName : volumes) {
if (volumeName.endsWith("qcow2")) {
tmpltname = volumeName;
for (KVMPhysicalDisk disk : disks) {
if (disk.getName().endsWith("qcow2")) {
tmplVol = disk;
break;
}
}
if (tmpltname == null) {
return new PrimaryStorageDownloadAnswer("Failed to get template from pool: " + secondaryPool.getName());
if (tmplVol == null) {
return new PrimaryStorageDownloadAnswer("Failed to get template from pool: " + secondaryPool.getUuid());
}
}
LibvirtStoragePoolDef poolDef = _storageResource.getStoragePoolDef(conn, secondaryPool);
tmplVol = _storageResource.getVolume(conn, secondaryPool, poolDef.getTargetPath() + File.separator + tmpltname);
/*Copy volume to primary storage*/
primaryPool = _storageResource.getStoragePool(conn, cmd.getPoolUuid());
LibvirtStorageVolumeDef vol = new LibvirtStorageVolumeDef(UUID.randomUUID().toString(), tmplVol.getInfo().capacity, volFormat.QCOW2, null, null);
s_logger.debug(vol.toString());
primaryVol = _storageResource.copyVolume(primaryPool, vol, tmplVol, _cmdsTimeout);
KVMStoragePool primaryPool = _storagePoolMgr.getStoragePool(cmd.getPoolUuid());
StorageVolInfo priVolInfo = primaryVol.getInfo();
return new PrimaryStorageDownloadAnswer(primaryVol.getKey(), priVolInfo.allocation);
} catch (LibvirtException e) {
s_logger.debug(e.toString());
KVMPhysicalDisk primaryVol = _storagePoolMgr.copyPhysicalDisk(tmplVol, UUID.randomUUID().toString(), primaryPool);
return new PrimaryStorageDownloadAnswer(primaryVol.getName(), primaryVol.getSize());
} catch (CloudRuntimeException e) {
return new PrimaryStorageDownloadAnswer(e.toString());
} catch (URISyntaxException e) {
return new PrimaryStorageDownloadAnswer(e.toString());
} finally {
try {
if (primaryVol != null) {
primaryVol.free();
}
if (primaryPool != null) {
primaryPool.free();
}
if (tmplVol != null) {
tmplVol.free();
}
_storageResource.deleteStoragePool(conn, secondaryPool);
} catch (LibvirtException l) {
}
}
}
protected Answer execute(CreateStoragePoolCommand cmd) {
@ -1538,29 +1502,18 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
}
protected Answer execute(ModifyStoragePoolCommand cmd) {
try {
Connect conn = LibvirtConnection.getConnection();
StoragePool storagePool = _storageResource.getStoragePool(conn, cmd.getPool());
if (storagePool == null) {
return new Answer(cmd, false, " Failed to create storage pool");
}
StoragePoolInfo spi = null;
spi = storagePool.getInfo();
Map<String, TemplateInfo> tInfo = new HashMap<String, TemplateInfo>();
ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd,
spi.capacity,
spi.allocation,
tInfo);
storagePool.free();
return answer;
} catch (LibvirtException e) {
return new Answer(cmd, false, e.getMessage());
KVMStoragePool storagepool = _storagePoolMgr.createStoragePool(cmd.getPool().getUuid(), cmd.getPool().getHost(), cmd.getPool().getPath(), cmd.getPool().getType());
if (storagepool == null) {
return new Answer(cmd, false, " Failed to create storage pool");
}
Map<String, TemplateInfo> tInfo = new HashMap<String, TemplateInfo>();
ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd,
storagepool.getCapacity(),
storagepool.getUsed(),
tInfo);
return answer;
}
private Answer execute(SecurityIngressRulesCmd cmd) {
@ -2261,8 +2214,13 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
private String getVolumePath(Connect conn, VolumeTO volume) throws LibvirtException, URISyntaxException {
if (volume.getType() == Volume.Type.ISO && volume.getPath() != null) {
StorageVol vol = _storageResource.getVolumeFromURI(conn, volume.getPath());
return vol.getPath();
String isoPath = volume.getPath();
int index = isoPath.lastIndexOf("/");
String path = isoPath.substring(0, index);
String name = isoPath.substring(index + 1);
KVMStoragePool secondaryPool = _storagePoolMgr.getStoragePoolByURI(path);
KVMPhysicalDisk isoVol = secondaryPool.getPhysicalDisk(name);
return isoVol.getPath();
} else {
return volume.getPath();
}
@ -2270,7 +2228,21 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
protected void createVbd(Connect conn, VirtualMachineTO vmSpec, String vmName, LibvirtVMDef vm) throws InternalErrorException, LibvirtException, URISyntaxException{
for (VolumeTO volume : vmSpec.getDisks()) {
String volPath = getVolumePath(conn, volume);
KVMPhysicalDisk physicalDisk = null;
KVMStoragePool pool = null;
if (volume.getType() == Volume.Type.ISO && volume.getPath() != null) {
String volPath = volume.getPath();
int index = volPath.lastIndexOf("/");
String volDir = volPath.substring(0, index);
String volName = volPath.substring(index + 1);
KVMStoragePool secondaryStorage = _storagePoolMgr.getStoragePoolByURI(volDir);
physicalDisk = secondaryStorage.getPhysicalDisk(volName);
} else {
pool = _storagePoolMgr.getStoragePool(volume.getPoolUuid());
physicalDisk = pool.getPhysicalDisk(volume.getPath());
}
String volPath = physicalDisk.getPath();
DiskDef.diskBus diskBusType = getGuestDiskModel(vmSpec.getOs());
DiskDef disk = new DiskDef();
@ -2283,8 +2255,11 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
}
} else {
int devId = (int)volume.getDeviceId();
disk.defFileBasedDisk(volume.getPath(), devId, diskBusType, DiskDef.diskFmtType.QCOW2);
if (pool.getType() == StoragePoolType.CLVM) {
disk.defBlockBasedDisk(physicalDisk.getPath(), devId, diskBusType);
} else {
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusType, DiskDef.diskFmtType.QCOW2);
}
}
//Centos doesn't support scsi hotplug. For other host OSes, we attach the disk after the vm is running, so that we can hotplug it.
@ -2323,20 +2298,30 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
List<DiskDef> disks = vm.getDevices().getDisks();
DiskDef rootDisk = disks.get(0);
VolumeTO rootVol = getVolume(vmSpec, Volume.Type.ROOT);
StoragePool pool = _storageResource.getStoragePool(conn, rootVol.getPoolUuid());
StorageVol tmplVol = _storageResource.createTmplDataDisk(conn, pool, 10L * 1024 * 1024);
String datadiskPath = tmplVol.getKey();
KVMStoragePool pool = _storagePoolMgr.getStoragePool(rootVol.getPoolUuid());
KVMPhysicalDisk disk = pool.createPhysicalDisk(UUID.randomUUID().toString(), KVMPhysicalDisk.PhysicalDiskFormat.RAW, 10L * 1024 * 1024);
/*Format/create fs on this disk*/
final Script command = new Script(_createvmPath, _timeout, s_logger);
command.add("-f", disk.getPath());
String result = command.execute();
if (result != null) {
s_logger.debug("Failed to create data disk: " + result);
throw new InternalErrorException("Failed to create data disk: " + result);
}
String datadiskPath = disk.getPath();
/*add patch disk*/
DiskDef patchDisk = new DiskDef();
patchDisk.defFileBasedDisk(rootDisk.getDiskPath(), 1, rootDisk.getBusType(), DiskDef.diskFmtType.RAW);
if (pool.getType() == StoragePoolType.CLVM) {
patchDisk.defBlockBasedDisk(datadiskPath, 1, rootDisk.getBusType());
} else {
patchDisk.defFileBasedDisk(datadiskPath, 1, rootDisk.getBusType(), DiskDef.diskFmtType.RAW);
}
disks.add(patchDisk);
patchDisk.setDiskPath(datadiskPath);
String bootArgs = vmSpec.getBootArgs();
patchSystemVm(bootArgs, datadiskPath, vmName);
}
private String createVlanBr(String vlanId, String nic) throws InternalErrorException{
@ -2412,7 +2397,11 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
protected synchronized String attachOrDetachISO(Connect conn, String vmName, String isoPath, boolean isAttach) throws LibvirtException, URISyntaxException, InternalErrorException {
String isoXml = null;
if (isoPath != null && isAttach) {
StorageVol isoVol = _storageResource.getVolumeFromURI(conn, isoPath);
int index = isoPath.lastIndexOf("/");
String path = isoPath.substring(0, index);
String name = isoPath.substring(index + 1);
KVMStoragePool secondaryPool = _storagePoolMgr.getStoragePoolByURI(path);
KVMPhysicalDisk isoVol = secondaryPool.getPhysicalDisk(name);
isoPath = isoVol.getPath();
DiskDef iso = new DiskDef();
@ -2548,14 +2537,16 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
StartupStorageCommand sscmd = null;
try {
Connect conn = LibvirtConnection.getConnection();
com.cloud.agent.api.StoragePoolInfo pi = _storageResource.initializeLocalStorage(conn, _localStoragePath, cmd.getPrivateIpAddress(), _localStorageUUID);
KVMStoragePool localStoragePool = _storagePoolMgr.createStoragePool(_localStorageUUID, "localhost", _localStoragePath, StoragePoolType.Filesystem);
com.cloud.agent.api.StoragePoolInfo pi = new com.cloud.agent.api.StoragePoolInfo(localStoragePool.getUuid(), cmd.getPrivateIpAddress(), _localStoragePath, _localStoragePath, StoragePoolType.Filesystem, localStoragePool.getCapacity(), localStoragePool.getUsed());
sscmd = new StartupStorageCommand();
sscmd.setPoolInfo(pi);
sscmd.setGuid(pi.getUuid());
sscmd.setDataCenter(_dcId);
sscmd.setResourceType(Storage.StorageResourceType.STORAGE_POOL);
} catch (LibvirtException e) {
} catch (CloudRuntimeException e) {
}

View File

@ -22,6 +22,8 @@ import org.apache.log4j.Logger;
import org.libvirt.Connect;
import org.libvirt.LibvirtException;
import com.cloud.agent.kvm.KVMConnection;
public class LibvirtConnection {
private static final Logger s_logger = Logger.getLogger(LibvirtConnection.class);
static private Connect _connection;

View File

@ -22,6 +22,7 @@ public class LibvirtStoragePoolDef {
public enum poolType {
ISCSI("iscsi"),
NETFS("netfs"),
LOGICAL("logical"),
DIR("dir");
String _poolType;
poolType(String poolType) {

View File

@ -1,491 +0,0 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.agent.resource.computing;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.log4j.Logger;
import org.libvirt.Connect;
import org.libvirt.LibvirtException;
import org.libvirt.StoragePool;
import org.libvirt.StoragePoolInfo;
import org.libvirt.StorageVol;
import org.libvirt.StoragePoolInfo.StoragePoolState;
import com.cloud.agent.api.StartupStorageCommand;
import com.cloud.agent.api.to.StorageFilerTO;
import com.cloud.agent.api.to.VolumeTO;
import com.cloud.agent.resource.computing.KVMHABase.PoolType;
import com.cloud.agent.resource.computing.LibvirtStoragePoolDef.poolType;
import com.cloud.agent.resource.computing.LibvirtStorageVolumeDef.volFormat;
import com.cloud.exception.InternalErrorException;
import com.cloud.hypervisor.xen.resource.CitrixResourceBase.SRType;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Storage;
import com.cloud.storage.StorageLayer;
import com.cloud.utils.script.Script;
public class LibvirtStorageResource {
private static final Logger s_logger = Logger.getLogger(LibvirtStorageResource.class);
private LibvirtComputingResource _computingResource;
private final Map<String, Object> _storagePools = new ConcurrentHashMap<String, Object>();
private StorageLayer _storageLayer;
private String _createvmPath;
private int _timeout;
private String _mountPoint;
private KVMHAMonitor _monitor;
public LibvirtStorageResource(LibvirtComputingResource resource, StorageLayer storage, String createDiskScript, int timeout,
String mountPoint, KVMHAMonitor monitor) {
_computingResource = resource;
_storageLayer = storage;
_createvmPath = createDiskScript;
_timeout = timeout;
_mountPoint = mountPoint;
_monitor = monitor;
}
public StoragePool getStoragePool(Connect conn, String uuid) throws LibvirtException {
StoragePool storage = null;
try {
storage = conn.storagePoolLookupByUUIDString(uuid);
} catch (LibvirtException e) {
throw e;
}
if ( storage.getInfo().state != StoragePoolState.VIR_STORAGE_POOL_RUNNING) {
storage.create(0);
}
return storage;
}
public boolean deleteStoragePool(Connect conn, StorageFilerTO spt) throws LibvirtException {
StoragePool pool = getStoragePool(conn, spt.getUuid());
LibvirtStoragePoolDef spd = getStoragePoolDef(conn, pool);
synchronized (getStoragePool(pool.getUUIDString())) {
pool.destroy();
pool.undefine();
}
if (spd.getPoolType() == poolType.NETFS) {
KVMHABase.NfsStoragePool sp = new KVMHABase.NfsStoragePool(spt.getUuid(),
spt.getHost(),
spt.getPath(),
spd.getTargetPath(),
PoolType.PrimaryStorage);
_monitor.removeStoragePool(sp);
}
rmStoragePool(spt.getUuid());
return true;
}
public boolean deleteStoragePool(Connect conn, StoragePool pool) throws LibvirtException {
if (pool != null) {
String uuid = pool.getUUIDString();
synchronized (getStoragePool(uuid)) {
pool.destroy();
pool.undefine();
pool.free();
}
rmStoragePool(uuid);
}
return true;
}
public StorageVol getVolume(Connect conn, StoragePool pool, String volPath) throws LibvirtException {
StorageVol vol = null;
try {
vol = conn.storageVolLookupByKey(volPath);
} catch (LibvirtException e) {
}
if (vol == null) {
storagePoolRefresh(pool);
vol = conn.storageVolLookupByKey(volPath);
}
return vol;
}
public StorageVol createVolumeFromTempl(StoragePool destPool, StorageVol tmplVol) throws LibvirtException {
if (_computingResource.isCentosHost()) {
LibvirtStorageVolumeDef volDef = new LibvirtStorageVolumeDef(UUID.randomUUID().toString(), tmplVol.getInfo().capacity, volFormat.QCOW2, null, null);
s_logger.debug(volDef.toString());
StorageVol vol = destPool.storageVolCreateXML(volDef.toString(), 0);
/*create qcow2 image based on the name*/
Script.runSimpleBashScript("qemu-img create -f qcow2 -b " + tmplVol.getPath() + " " + vol.getPath() );
return vol;
} else {
LibvirtStorageVolumeDef volDef = new LibvirtStorageVolumeDef(UUID.randomUUID().toString(), tmplVol.getInfo().capacity, volFormat.QCOW2, tmplVol.getPath(), volFormat.QCOW2);
s_logger.debug(volDef.toString());
return destPool.storageVolCreateXML(volDef.toString(), 0);
}
}
private void addStoragePool(String uuid) {
synchronized (_storagePools) {
if (!_storagePools.containsKey(uuid)) {
_storagePools.put(uuid, new Object());
}
}
}
private void rmStoragePool(String uuid) {
synchronized (_storagePools) {
if (_storagePools.containsKey(uuid)) {
_storagePools.remove(uuid);
}
}
}
private Object getStoragePool(String uuid) {
synchronized (_storagePools) {
if (!_storagePools.containsKey(uuid)) {
addStoragePool(uuid);
}
return _storagePools.get(uuid);
}
}
public StorageVol createTmplDataDisk(Connect conn, StoragePool pool, long size) throws LibvirtException, InternalErrorException {
/*create a templ data disk, to contain patches*/
LibvirtStorageVolumeDef volDef = new LibvirtStorageVolumeDef(UUID.randomUUID().toString(), size, volFormat.RAW, null, null);
StorageVol dataVol = pool.storageVolCreateXML(volDef.toString(), 0);
/*Format/create fs on this disk*/
final Script command = new Script(_createvmPath, _timeout, s_logger);
command.add("-f", dataVol.getKey());
String result = command.execute();
if (result != null) {
s_logger.debug("Failed to create data disk: " + result);
throw new InternalErrorException("Failed to create data disk: " + result);
}
return dataVol;
}
public StorageVol createVolume(Connect conn, StoragePool pool, String uuid, long size, volFormat format) throws LibvirtException {
LibvirtStorageVolumeDef volDef = new LibvirtStorageVolumeDef(UUID.randomUUID().toString(), size, format, null, null);
s_logger.debug(volDef.toString());
return pool.storageVolCreateXML(volDef.toString(), 0);
}
public StoragePool getStoragePoolbyURI(Connect conn, URI uri) throws LibvirtException {
String sourcePath;
String uuid;
String sourceHost = "";
String protocal;
if (uri.getScheme().equalsIgnoreCase("local")) {
sourcePath = _mountPoint + File.separator + uri.toString().replace("local:///", "");
sourcePath = sourcePath.replace("//", "/");
uuid = UUID.nameUUIDFromBytes(new String(sourcePath).getBytes()).toString();
protocal = "DIR";
} else {
sourcePath = uri.getPath();
sourcePath = sourcePath.replace("//", "/");
sourceHost = uri.getHost();
uuid = UUID.nameUUIDFromBytes(new String(sourceHost + sourcePath).getBytes()).toString();
protocal = "NFS";
}
String targetPath = _mountPoint + File.separator + uuid;
StoragePool sp = null;
try {
sp = conn.storagePoolLookupByUUIDString(uuid);
} catch (LibvirtException e) {
}
if (sp == null) {
try {
LibvirtStoragePoolDef spd = null;
if (protocal.equalsIgnoreCase("NFS")) {
_storageLayer.mkdir(targetPath);
spd = new LibvirtStoragePoolDef(poolType.NETFS, uuid, uuid,
sourceHost, sourcePath, targetPath);
s_logger.debug(spd.toString());
addStoragePool(uuid);
} else if (protocal.equalsIgnoreCase("DIR")) {
_storageLayer.mkdir(targetPath);
spd = new LibvirtStoragePoolDef(poolType.DIR, uuid, uuid,
null, null, sourcePath);
}
synchronized (getStoragePool(uuid)) {
sp = conn.storagePoolDefineXML(spd.toString(), 0);
if (sp == null) {
s_logger.debug("Failed to define storage pool");
return null;
}
sp.create(0);
}
return sp;
} catch (LibvirtException e) {
try {
if (sp != null) {
sp.undefine();
sp.free();
}
} catch (LibvirtException l) {
}
throw e;
}
} else {
StoragePoolInfo spi = sp.getInfo();
if (spi.state != StoragePoolState.VIR_STORAGE_POOL_RUNNING) {
sp.create(0);
}
return sp;
}
}
public void storagePoolRefresh(StoragePool pool) {
try {
synchronized (getStoragePool(pool.getUUIDString())) {
pool.refresh(0);
}
} catch (LibvirtException e) {
}
}
private StoragePool createNfsStoragePool(Connect conn, StorageFilerTO pool) {
String targetPath = _mountPoint + File.separator + pool.getUuid();
LibvirtStoragePoolDef spd = new LibvirtStoragePoolDef(poolType.NETFS, pool.getUuid(), pool.getUuid(),
pool.getHost(), pool.getPath(), targetPath);
_storageLayer.mkdir(targetPath);
StoragePool sp = null;
try {
s_logger.debug(spd.toString());
addStoragePool(pool.getUuid());
synchronized (getStoragePool(pool.getUuid())) {
sp = conn.storagePoolDefineXML(spd.toString(), 0);
sp.create(0);
}
return sp;
} catch (LibvirtException e) {
s_logger.debug(e.toString());
if (sp != null) {
try {
sp.undefine();
sp.free();
} catch (LibvirtException l) {
s_logger.debug("Failed to define nfs storage pool with: " + l.toString());
}
}
return null;
}
}
private StoragePool CreateSharedStoragePool(Connect conn, StorageFilerTO pool) {
String mountPoint = pool.getPath();
if (!_storageLayer.exists(mountPoint)) {
return null;
}
LibvirtStoragePoolDef spd = new LibvirtStoragePoolDef(poolType.DIR, pool.getUuid(), pool.getUuid(),
pool.getHost(), pool.getPath(), pool.getPath());
StoragePool sp = null;
try {
s_logger.debug(spd.toString());
addStoragePool(pool.getUuid());
synchronized (getStoragePool(pool.getUuid())) {
sp = conn.storagePoolDefineXML(spd.toString(), 0);
sp.create(0);
}
return sp;
} catch (LibvirtException e) {
s_logger.debug(e.toString());
if (sp != null) {
try {
sp.undefine();
sp.free();
} catch (LibvirtException l) {
s_logger.debug("Failed to define shared mount point storage pool with: " + l.toString());
}
}
return null;
}
}
public StoragePool getStoragePool(Connect conn, StorageFilerTO spt) {
StoragePool sp = null;
try {
sp = conn.storagePoolLookupByUUIDString(spt.getUuid());
} catch (LibvirtException e) {
}
if (sp == null) {
if (spt.getType() == StoragePoolType.NetworkFilesystem) {
sp = createNfsStoragePool(conn, spt);
} else if (spt.getType() == StoragePoolType.SharedMountPoint) {
sp = CreateSharedStoragePool(conn, spt);
}
if (sp == null) {
s_logger.debug("Failed to create storage Pool");
return null;
}
}
try {
StoragePoolInfo spi = sp.getInfo();
if (spi.state != StoragePoolState.VIR_STORAGE_POOL_RUNNING) {
sp.create(0);
}
} catch (LibvirtException e) {
}
if (spt.getType() == StoragePoolType.NetworkFilesystem) {
KVMHABase.NfsStoragePool pool = new KVMHABase.NfsStoragePool(spt.getUuid(),
spt.getHost(),
spt.getPath(),
_mountPoint + File.separator + spt.getUuid(),
PoolType.PrimaryStorage);
_monitor.addStoragePool(pool);
}
addStoragePool(spt.getUuid());
return sp;
}
public StorageVol copyVolume(StoragePool destPool, LibvirtStorageVolumeDef destVol, StorageVol srcVol, int timeout) throws LibvirtException {
StorageVol vol = destPool.storageVolCreateXML(destVol.toString(), 0);
String srcPath = srcVol.getKey();
String destPath = vol.getKey();
Script.runSimpleBashScript("cp " + srcPath + " " + destPath, timeout);
return vol;
}
public boolean copyVolume(String srcPath, String destPath, String volumeName, int timeout) throws InternalErrorException{
_storageLayer.mkdirs(destPath);
if (!_storageLayer.exists(srcPath)) {
throw new InternalErrorException("volume:" + srcPath + " is not exits");
}
String result = Script.runSimpleBashScript("cp " + srcPath + " " + destPath + File.separator + volumeName, timeout);
if (result != null) {
return false;
} else {
return true;
}
}
public LibvirtStoragePoolDef getStoragePoolDef(Connect conn, StoragePool pool) throws LibvirtException {
String poolDefXML = pool.getXMLDesc(0);
LibvirtStoragePoolXMLParser parser = new LibvirtStoragePoolXMLParser();
return parser.parseStoragePoolXML(poolDefXML);
}
public StorageVol getVolumeFromURI(Connect conn, String volPath) throws LibvirtException, URISyntaxException {
int index = volPath.lastIndexOf("/");
URI volDir = null;
StoragePool sp = null;
StorageVol vol = null;
try {
volDir = new URI(volPath.substring(0, index));
String volName = volPath.substring(index + 1);
sp = getStoragePoolbyURI(conn, volDir);
vol = sp.storageVolLookupByName(volName);
return vol;
} catch (LibvirtException e) {
s_logger.debug("Faild to get vol path: " + e.toString());
throw e;
} finally {
try {
if (sp != null) {
sp.free();
}
} catch (LibvirtException e) {
}
}
}
public com.cloud.agent.api.StoragePoolInfo initializeLocalStorage(Connect conn, String localStoragePath, String hostIp, String uuid) {
if (!(_storageLayer.exists(localStoragePath) && _storageLayer.isDirectory(localStoragePath))) {
return null;
}
File path = new File(localStoragePath);
if (!(path.canWrite() && path.canRead() && path.canExecute())) {
return null;
}
StoragePool pool = null;
try {
pool = conn.storagePoolLookupByUUIDString(uuid);
} catch (LibvirtException e) {
}
if (pool == null) {
LibvirtStoragePoolDef spd = new LibvirtStoragePoolDef(poolType.DIR, uuid, uuid,
null, null, localStoragePath);
try {
pool = conn.storagePoolDefineXML(spd.toString(), 0);
pool.create(0);
} catch (LibvirtException e) {
if (pool != null) {
try {
pool.destroy();
pool.undefine();
} catch (LibvirtException e1) {
}
pool = null;
}
}
}
if (pool == null) {
return null;
}
try {
StoragePoolInfo spi = pool.getInfo();
if (spi.state != StoragePoolState.VIR_STORAGE_POOL_RUNNING) {
pool.create(0);
}
spi = pool.getInfo();
if (spi.state != StoragePoolState.VIR_STORAGE_POOL_RUNNING) {
return null;
}
com.cloud.agent.api.StoragePoolInfo pInfo = new com.cloud.agent.api.StoragePoolInfo(uuid, hostIp, localStoragePath, localStoragePath, StoragePoolType.Filesystem, spi.capacity, spi.available);
return pInfo;
} catch (LibvirtException e) {
}
return null;
}
}

View File

@ -46,6 +46,9 @@ public class LibvirtStorageVolumeDef {
_backingFormat = tmplFormat;
}
public volFormat getFormat() {
return this._volFormat;
}
@Override
public String toString() {
StringBuilder storageVolBuilder = new StringBuilder();

View File

@ -0,0 +1,90 @@
package com.cloud.agent.resource.computing;
import java.io.IOException;
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class LibvirtStorageVolumeXMLParser{
private static final Logger s_logger = Logger.getLogger(LibvirtStorageVolumeXMLParser.class);
public LibvirtStorageVolumeDef parseStorageVolumeXML(String volXML) {
DocumentBuilder builder;
try {
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(volXML));
Document doc = builder.parse(is);
Element rootElement = doc.getDocumentElement();
String VolName = getTagValue("name", rootElement);
Element target = (Element)rootElement.getElementsByTagName("target").item(0);
String format = getAttrValue("type", "format", target);
Long capacity = Long.parseLong(getTagValue("capacity", rootElement));
return new LibvirtStorageVolumeDef(VolName, capacity, LibvirtStorageVolumeDef.volFormat.QCOW2, null, null);
} catch (ParserConfigurationException e) {
s_logger.debug(e.toString());
} catch (SAXException e) {
s_logger.debug(e.toString());
} catch (IOException e) {
s_logger.debug(e.toString());
}
return null;
}
private static String getTagValue(String tag, Element eElement){
NodeList nlList= eElement.getElementsByTagName(tag).item(0).getChildNodes();
Node nValue = (Node) nlList.item(0);
return nValue.getNodeValue();
}
private static String getAttrValue(String tag, String attr, Element eElement){
NodeList tagNode = eElement.getElementsByTagName(tag);
if (tagNode.getLength() == 0) {
return null;
}
Element node = (Element)tagNode.item(0);
return node.getAttribute(attr);
}
public static void main(String[] args) {
s_logger.addAppender(new org.apache.log4j.ConsoleAppender(new org.apache.log4j.PatternLayout(), "System.out"));
String storagePool = "<pool type='dir'>" +
"<name>test</name>" +
"<uuid>bf723c83-4b95-259c-7089-60776e61a11f</uuid>" +
"<capacity>20314165248</capacity>" +
"<allocation>1955450880</allocation>" +
"<available>18358714368</available>" +
"<source>" +
"<host name='nfs1.lab.vmops.com'/>" +
"<dir path='/export/home/edison/kvm/primary'/>" +
"<format type='auto'/>" +
"</source>" +
"<target>" +
"<path>/media</path>" +
"<permissions>" +
"<mode>0700</mode>" +
"<owner>0</owner>" +
"<group>0</group>" +
"</permissions>" +
"</target>" +
"</pool>";
LibvirtStoragePoolXMLParser parser = new LibvirtStoragePoolXMLParser();
LibvirtStoragePoolDef pool = parser.parseStoragePoolXML(storagePool);
s_logger.debug(pool.toString());
}
}

View File

@ -337,11 +337,12 @@ public class LibvirtVMDef {
_diskFmtType = diskFmtType.RAW;
_bus = diskBus.IDE;
}
public void defBlockBasedDisk(String diskName, String diskLabel, diskBus bus) {
public void defBlockBasedDisk(String diskName, int devId, diskBus bus) {
_diskType = diskType.BLOCK;
_deviceType = deviceType.DISK;
_diskFmtType = diskFmtType.RAW;
_sourcePath = diskName;
_diskLabel = diskLabel;
_diskLabel = getDevLabel(devId, bus);
_bus = bus;
}
public void setReadonly() {

View File

@ -0,0 +1,56 @@
package com.cloud.agent.storage;
public class KVMPhysicalDisk {
private String path;
private String name;
private KVMStoragePool pool;
public static enum PhysicalDiskFormat {
RAW,
QCOW2
}
private PhysicalDiskFormat format;
private long size;
private long virtualSize;
public KVMPhysicalDisk(String path, String name, KVMStoragePool pool) {
this.path = path;
this.name = name;
this.pool = pool;
}
public void setFormat(PhysicalDiskFormat format) {
this.format = format;
}
public PhysicalDiskFormat getFormat() {
return this.format;
}
public void setSize(long size) {
this.size = size;
}
public long getSize() {
return this.size;
}
public void setVirtualSize(long size) {
this.virtualSize = size;
}
public long getVirtualSize() {
return this.virtualSize;
}
public String getName() {
return this.name;
}
public String getPath() {
return this.path;
}
public KVMStoragePool getPool() {
return this.pool;
}
}

View File

@ -0,0 +1,21 @@
package com.cloud.agent.storage;
import java.util.List;
import com.cloud.agent.storage.KVMPhysicalDisk.PhysicalDiskFormat;
import com.cloud.storage.Storage.StoragePoolType;
public interface KVMStoragePool {
public KVMPhysicalDisk createPhysicalDisk(String name, PhysicalDiskFormat format, long size);
public KVMPhysicalDisk createPhysicalDisk(String name, long size);
public KVMPhysicalDisk getPhysicalDisk(String volumeUuid);
public boolean deletePhysicalDisk(String uuid);
public List<KVMPhysicalDisk> listPhysicalDisks();
public String getUuid();
public long getCapacity();
public long getUsed();
public boolean refresh();
public boolean isExternalSnapshot();
public String getLocalPath();
public StoragePoolType getType();
}

View File

@ -0,0 +1,77 @@
package com.cloud.agent.storage;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.cloud.agent.storage.KVMPhysicalDisk.PhysicalDiskFormat;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StorageLayer;
public class KVMStoragePoolManager {
private StorageAdaptor _storageAdaptor;
private final Map<String, Object> _storagePools = new ConcurrentHashMap<String, Object>();
private void addStoragePool(String uuid) {
synchronized (_storagePools) {
if (!_storagePools.containsKey(uuid)) {
_storagePools.put(uuid, new Object());
}
}
}
public KVMStoragePoolManager(StorageLayer storagelayer) {
this._storageAdaptor = new LibvirtStorageAdaptor(storagelayer);
}
public KVMStoragePool getStoragePool(String uuid) {
return this._storageAdaptor.getStoragePool(uuid);
}
public KVMStoragePool getStoragePoolByURI(String uri) {
return this._storageAdaptor.getStoragePoolByUri(uri);
}
public KVMStoragePool createStoragePool(String name, String host, String path, StoragePoolType type) {
KVMStoragePool pool = this._storageAdaptor.createStoragePool(name, host, path, type);
if (type == StoragePoolType.NetworkFilesystem || type == StoragePoolType.SharedMountPoint) {
/*
KVMHABase.NfsStoragePool pool = new KVMHABase.NfsStoragePool(spt.getUuid(),
spt.getHost(),
spt.getPath(),
_mountPoint + File.separator + spt.getUuid(),
PoolType.PrimaryStorage);
_monitor.addStoragePool(pool);
*/
}
addStoragePool(pool.getUuid());
return pool;
}
public boolean deleteStoragePool(String uuid) {
this._storageAdaptor.deleteStoragePool(uuid);
_storagePools.remove(uuid);
return true;
}
public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template, String name, KVMStoragePool destPool) {
if (destPool.getType() == StoragePoolType.CLVM) {
return this._storageAdaptor.createDiskFromTemplate(template, name, KVMPhysicalDisk.PhysicalDiskFormat.RAW, template.getSize(), destPool);
} else {
return this._storageAdaptor.createDiskFromTemplate(template, name, KVMPhysicalDisk.PhysicalDiskFormat.QCOW2, template.getSize(), destPool);
}
}
public KVMPhysicalDisk createTemplateFromDisk(KVMPhysicalDisk disk, String name, PhysicalDiskFormat format, long size, KVMStoragePool destPool) {
return this._storageAdaptor.createTemplateFromDisk(disk, name, format, size, destPool);
}
public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name, KVMStoragePool destPool) {
return this._storageAdaptor.copyPhysicalDisk(disk, name, destPool);
}
public KVMPhysicalDisk createDiskFromSnapshot(KVMPhysicalDisk snapshot, String snapshotName, String name, KVMStoragePool destPool) {
return this._storageAdaptor.createDiskFromSnapshot(snapshot, snapshotName, name, destPool);
}
public KVMPhysicalDisk getPhysicalDiskFromUrl(String url) {
return this._storageAdaptor.getPhysicalDiskFromURI(url);
}
}

View File

@ -0,0 +1,6 @@
package com.cloud.agent.storage;
public class KVMVirtualDisk {
}

View File

@ -0,0 +1,630 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.agent.storage;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.log4j.Logger;
import org.libvirt.Connect;
import org.libvirt.LibvirtException;
import org.libvirt.StoragePool;
import org.libvirt.StoragePoolInfo;
import org.libvirt.StorageVol;
import org.libvirt.StoragePoolInfo.StoragePoolState;
import com.cloud.agent.api.GetStorageStatsAnswer;
import com.cloud.agent.api.StartupStorageCommand;
import com.cloud.agent.api.to.StorageFilerTO;
import com.cloud.agent.api.to.VolumeTO;
import com.cloud.agent.resource.computing.KVMHABase;
import com.cloud.agent.resource.computing.KVMHAMonitor;
import com.cloud.agent.resource.computing.LibvirtComputingResource;
import com.cloud.agent.resource.computing.LibvirtConnection;
import com.cloud.agent.resource.computing.LibvirtStoragePoolDef;
import com.cloud.agent.resource.computing.LibvirtStoragePoolXMLParser;
import com.cloud.agent.resource.computing.LibvirtStorageVolumeDef;
import com.cloud.agent.resource.computing.KVMHABase.NfsStoragePool;
import com.cloud.agent.resource.computing.KVMHABase.PoolType;
import com.cloud.agent.resource.computing.LibvirtStoragePoolDef.poolType;
import com.cloud.agent.resource.computing.LibvirtStorageVolumeDef.volFormat;
import com.cloud.agent.resource.computing.LibvirtStorageVolumeXMLParser;
import com.cloud.agent.storage.KVMPhysicalDisk.PhysicalDiskFormat;
import com.cloud.exception.InternalErrorException;
import com.cloud.hypervisor.xen.resource.CitrixResourceBase.SRType;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Storage;
import com.cloud.storage.StorageLayer;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.OutputInterpreter;
import com.cloud.utils.script.Script;
public class LibvirtStorageAdaptor implements StorageAdaptor {
private static final Logger s_logger = Logger.getLogger(LibvirtStorageAdaptor.class);
private StorageLayer _storageLayer;
private String _mountPoint = "/mnt";
public LibvirtStorageAdaptor(StorageLayer storage
) {
_storageLayer = storage;
}
public StorageVol getVolume(StoragePool pool, String volName) {
StorageVol vol = null;
try {
vol = pool.storageVolLookupByName(volName);
} catch (LibvirtException e) {
}
if (vol == null) {
storagePoolRefresh(pool);
try {
vol = pool.storageVolLookupByName(volName);
} catch (LibvirtException e) {
throw new CloudRuntimeException(e.toString());
}
}
return vol;
}
public StorageVol createVolume(Connect conn, StoragePool pool, String uuid, long size, volFormat format) throws LibvirtException {
LibvirtStorageVolumeDef volDef = new LibvirtStorageVolumeDef(UUID.randomUUID().toString(), size, format, null, null);
s_logger.debug(volDef.toString());
return pool.storageVolCreateXML(volDef.toString(), 0);
}
public StoragePool getStoragePoolbyURI(Connect conn, URI uri) throws LibvirtException {
String sourcePath;
String uuid;
String sourceHost = "";
String protocal;
if (uri.getScheme().equalsIgnoreCase("local")) {
sourcePath = _mountPoint + File.separator + uri.toString().replace("local:///", "");
sourcePath = sourcePath.replace("//", "/");
uuid = UUID.nameUUIDFromBytes(new String(sourcePath).getBytes()).toString();
protocal = "DIR";
} else {
sourcePath = uri.getPath();
sourcePath = sourcePath.replace("//", "/");
sourceHost = uri.getHost();
uuid = UUID.nameUUIDFromBytes(new String(sourceHost + sourcePath).getBytes()).toString();
protocal = "NFS";
}
String targetPath = _mountPoint + File.separator + uuid;
StoragePool sp = null;
try {
sp = conn.storagePoolLookupByUUIDString(uuid);
} catch (LibvirtException e) {
}
if (sp == null) {
try {
LibvirtStoragePoolDef spd = null;
if (protocal.equalsIgnoreCase("NFS")) {
_storageLayer.mkdir(targetPath);
spd = new LibvirtStoragePoolDef(poolType.NETFS, uuid, uuid,
sourceHost, sourcePath, targetPath);
s_logger.debug(spd.toString());
//addStoragePool(uuid);
} else if (protocal.equalsIgnoreCase("DIR")) {
_storageLayer.mkdir(targetPath);
spd = new LibvirtStoragePoolDef(poolType.DIR, uuid, uuid,
null, null, sourcePath);
}
synchronized (getStoragePool(uuid)) {
sp = conn.storagePoolDefineXML(spd.toString(), 0);
if (sp == null) {
s_logger.debug("Failed to define storage pool");
return null;
}
sp.create(0);
}
return sp;
} catch (LibvirtException e) {
try {
if (sp != null) {
sp.undefine();
sp.free();
}
} catch (LibvirtException l) {
}
throw e;
}
} else {
StoragePoolInfo spi = sp.getInfo();
if (spi.state != StoragePoolState.VIR_STORAGE_POOL_RUNNING) {
sp.create(0);
}
return sp;
}
}
public void storagePoolRefresh(StoragePool pool) {
try {
synchronized (getStoragePool(pool.getUUIDString())) {
pool.refresh(0);
}
} catch (LibvirtException e) {
}
}
private StoragePool createNfsStoragePool(Connect conn, String uuid, String host, String path) {
String targetPath = _mountPoint + File.separator + uuid;
LibvirtStoragePoolDef spd = new LibvirtStoragePoolDef(poolType.NETFS, uuid, uuid,
host, path, targetPath);
_storageLayer.mkdir(targetPath);
StoragePool sp = null;
try {
s_logger.debug(spd.toString());
sp = conn.storagePoolDefineXML(spd.toString(), 0);
sp.create(0);
return sp;
} catch (LibvirtException e) {
s_logger.debug(e.toString());
if (sp != null) {
try {
sp.undefine();
sp.free();
} catch (LibvirtException l) {
s_logger.debug("Failed to define nfs storage pool with: " + l.toString());
}
}
return null;
}
}
private StoragePool CreateSharedStoragePool(Connect conn, String uuid, String host, String path) {
String mountPoint = path;
if (!_storageLayer.exists(mountPoint)) {
return null;
}
LibvirtStoragePoolDef spd = new LibvirtStoragePoolDef(poolType.DIR, uuid, uuid,
host, path, path);
StoragePool sp = null;
try {
s_logger.debug(spd.toString());
sp = conn.storagePoolDefineXML(spd.toString(), 0);
sp.create(0);
return sp;
} catch (LibvirtException e) {
s_logger.debug(e.toString());
if (sp != null) {
try {
sp.undefine();
sp.free();
} catch (LibvirtException l) {
s_logger.debug("Failed to define shared mount point storage pool with: " + l.toString());
}
}
return null;
}
}
public StorageVol copyVolume(StoragePool destPool, LibvirtStorageVolumeDef destVol, StorageVol srcVol, int timeout) throws LibvirtException {
StorageVol vol = destPool.storageVolCreateXML(destVol.toString(), 0);
String srcPath = srcVol.getKey();
String destPath = vol.getKey();
Script.runSimpleBashScript("cp " + srcPath + " " + destPath, timeout);
return vol;
}
public boolean copyVolume(String srcPath, String destPath, String volumeName, int timeout) throws InternalErrorException{
_storageLayer.mkdirs(destPath);
if (!_storageLayer.exists(srcPath)) {
throw new InternalErrorException("volume:" + srcPath + " is not exits");
}
String result = Script.runSimpleBashScript("cp " + srcPath + " " + destPath + File.separator + volumeName, timeout);
if (result != null) {
return false;
} else {
return true;
}
}
public LibvirtStoragePoolDef getStoragePoolDef(Connect conn, StoragePool pool) throws LibvirtException {
String poolDefXML = pool.getXMLDesc(0);
LibvirtStoragePoolXMLParser parser = new LibvirtStoragePoolXMLParser();
return parser.parseStoragePoolXML(poolDefXML);
}
public LibvirtStorageVolumeDef getStorageVolumeDef(Connect conn, StorageVol vol) throws LibvirtException {
String volDefXML = vol.getXMLDesc(0);
LibvirtStorageVolumeXMLParser parser = new LibvirtStorageVolumeXMLParser();
return parser.parseStorageVolumeXML(volDefXML);
}
public StorageVol getVolumeFromURI(Connect conn, String volPath) throws LibvirtException, URISyntaxException {
int index = volPath.lastIndexOf("/");
URI volDir = null;
StoragePool sp = null;
StorageVol vol = null;
try {
volDir = new URI(volPath.substring(0, index));
String volName = volPath.substring(index + 1);
sp = getStoragePoolbyURI(conn, volDir);
vol = sp.storageVolLookupByName(volName);
return vol;
} catch (LibvirtException e) {
s_logger.debug("Faild to get vol path: " + e.toString());
throw e;
} finally {
try {
if (sp != null) {
sp.free();
}
} catch (LibvirtException e) {
}
}
}
public StoragePool createFileBasedStoragePool(Connect conn, String localStoragePath, String uuid) {
if (!(_storageLayer.exists(localStoragePath) && _storageLayer.isDirectory(localStoragePath))) {
return null;
}
File path = new File(localStoragePath);
if (!(path.canWrite() && path.canRead() && path.canExecute())) {
return null;
}
StoragePool pool = null;
try {
pool = conn.storagePoolLookupByUUIDString(uuid);
} catch (LibvirtException e) {
}
if (pool == null) {
LibvirtStoragePoolDef spd = new LibvirtStoragePoolDef(poolType.DIR, uuid, uuid,
null, null, localStoragePath);
try {
pool = conn.storagePoolDefineXML(spd.toString(), 0);
pool.create(0);
} catch (LibvirtException e) {
if (pool != null) {
try {
pool.destroy();
pool.undefine();
} catch (LibvirtException e1) {
}
pool = null;
}
throw new CloudRuntimeException(e.toString());
}
}
try {
StoragePoolInfo spi = pool.getInfo();
if (spi.state != StoragePoolState.VIR_STORAGE_POOL_RUNNING) {
pool.create(0);
}
} catch (LibvirtException e) {
throw new CloudRuntimeException(e.toString());
}
return pool;
}
private void getStats(LibvirtStoragePool pool) {
Script statsScript = new Script("/bin/bash", s_logger);
statsScript.add("-c");
statsScript.add("stats=$(df --total " + pool.getLocalPath() + " |grep total|awk '{print $2,$3}');echo $stats");
final OutputInterpreter.OneLineParser statsParser = new OutputInterpreter.OneLineParser();
String result = statsScript.execute(statsParser);
if (result == null) {
String stats = statsParser.getLine();
if (stats != null && !stats.isEmpty()) {
String sizes[] = stats.trim().split(" ");
if (sizes.length == 2) {
pool.setCapacity(Long.parseLong(sizes[0]) * 1024);
pool.setUsed(Long.parseLong(sizes[1]) * 1024);
}
}
}
}
@Override
public KVMStoragePool getStoragePool(String uuid) {
StoragePool storage = null;
try {
Connect conn = LibvirtConnection.getConnection();
storage = conn.storagePoolLookupByUUIDString(uuid);
if (storage.getInfo().state != StoragePoolState.VIR_STORAGE_POOL_RUNNING) {
storage.create(0);
}
LibvirtStoragePoolDef spd = getStoragePoolDef(conn, storage);
StoragePoolType type = null;
if (spd.getPoolType() == LibvirtStoragePoolDef.poolType.NETFS || spd.getPoolType() == LibvirtStoragePoolDef.poolType.DIR) {
type = StoragePoolType.Filesystem;
} else if (spd.getPoolType() == LibvirtStoragePoolDef.poolType.LOGICAL) {
type = StoragePoolType.CLVM;
}
LibvirtStoragePool pool = new LibvirtStoragePool(uuid, storage.getName(), type, this, storage);
pool.setLocalPath(spd.getTargetPath());
if (pool.getType() == StoragePoolType.CLVM) {
pool.setCapacity(storage.getInfo().capacity);
pool.setUsed(storage.getInfo().allocation);
} else {
getStats(pool);
}
return pool;
} catch (LibvirtException e) {
throw new CloudRuntimeException(e.toString());
}
}
@Override
public KVMPhysicalDisk getPhysicalDisk(
String volumeUuid, KVMStoragePool pool) {
LibvirtStoragePool libvirtPool = (LibvirtStoragePool)pool;
try {
StorageVol vol = this.getVolume(libvirtPool.getPool(), volumeUuid);
KVMPhysicalDisk disk;
LibvirtStorageVolumeDef voldef = getStorageVolumeDef(libvirtPool.getPool().getConnect(), vol);
disk = new KVMPhysicalDisk(vol.getPath(), vol.getName(), pool);
disk.setSize(vol.getInfo().allocation);
disk.setVirtualSize(vol.getInfo().capacity);
if (voldef.getFormat() == LibvirtStorageVolumeDef.volFormat.QCOW2) {
disk.setFormat(KVMPhysicalDisk.PhysicalDiskFormat.QCOW2);
} else if (voldef.getFormat() == LibvirtStorageVolumeDef.volFormat.RAW) {
disk.setFormat(KVMPhysicalDisk.PhysicalDiskFormat.RAW);
}
return disk;
} catch (LibvirtException e) {
throw new CloudRuntimeException(e.toString());
}
}
@Override
public KVMStoragePool createStoragePool(String name, String host, String path, StoragePoolType type) {
StoragePool sp = null;
Connect conn = null;
try {
conn = LibvirtConnection.getConnection();
} catch (LibvirtException e) {
throw new CloudRuntimeException(e.toString());
}
try {
sp = conn.storagePoolLookupByUUIDString(name);
} catch (LibvirtException e) {
}
if (sp == null) {
if (type == StoragePoolType.NetworkFilesystem) {
sp = createNfsStoragePool(conn, name, host, path);
} else if (type == StoragePoolType.SharedMountPoint || type == StoragePoolType.Filesystem) {
sp = CreateSharedStoragePool(conn, name, host, path);
}
}
try {
StoragePoolInfo spi = sp.getInfo();
if (spi.state != StoragePoolState.VIR_STORAGE_POOL_RUNNING) {
sp.create(0);
}
LibvirtStoragePoolDef spd = getStoragePoolDef(conn, sp);
LibvirtStoragePool pool = new LibvirtStoragePool(name, sp.getName(), type, this, sp);
pool.setLocalPath(spd.getTargetPath());
if (pool.getType() == StoragePoolType.CLVM) {
pool.setCapacity(sp.getInfo().capacity);
pool.setUsed(sp.getInfo().allocation);
} else {
getStats(pool);
}
return pool;
} catch (LibvirtException e) {
throw new CloudRuntimeException(e.toString());
}
}
@Override
public boolean deleteStoragePool(String uuid) {
Connect conn = null;
try {
conn = LibvirtConnection.getConnection();
} catch (LibvirtException e) {
throw new CloudRuntimeException(e.toString());
}
StoragePool sp = null;
try {
sp = conn.storagePoolLookupByUUIDString(uuid);
} catch (LibvirtException e) {
return true;
}
try {
sp.destroy();
sp.undefine();
sp.free();
return true;
} catch (LibvirtException e) {
throw new CloudRuntimeException(e.toString());
}
}
@Override
public KVMPhysicalDisk createPhysicalDisk(String name,
KVMStoragePool pool, PhysicalDiskFormat format, long size) {
LibvirtStoragePool libvirtPool = (LibvirtStoragePool)pool;
StoragePool virtPool = libvirtPool.getPool();
LibvirtStorageVolumeDef.volFormat libvirtformat = null;
if (format == PhysicalDiskFormat.QCOW2) {
libvirtformat = LibvirtStorageVolumeDef.volFormat.QCOW2;
} else if (format == PhysicalDiskFormat.RAW) {
libvirtformat = LibvirtStorageVolumeDef.volFormat.RAW;
}
LibvirtStorageVolumeDef volDef = new LibvirtStorageVolumeDef(name, size, libvirtformat, null, null);
s_logger.debug(volDef.toString());
try {
StorageVol vol = virtPool.storageVolCreateXML(volDef.toString(), 0);
KVMPhysicalDisk disk = new KVMPhysicalDisk(vol.getPath(), vol.getName(), pool);
disk.setFormat(format);
disk.setSize(vol.getInfo().allocation);
disk.setVirtualSize(vol.getInfo().capacity);
return disk;
} catch (LibvirtException e) {
throw new CloudRuntimeException(e.toString());
}
}
@Override
public boolean deletePhysicalDisk(String uuid, KVMStoragePool pool) {
LibvirtStoragePool libvirtPool = (LibvirtStoragePool)pool;
try {
StorageVol vol = this.getVolume(libvirtPool.getPool(), uuid);
vol.delete(0);
vol.free();
return true;
} catch (LibvirtException e) {
throw new CloudRuntimeException(e.toString());
}
}
@Override
public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template,
String name, PhysicalDiskFormat format, long size,
KVMStoragePool destPool) {
KVMPhysicalDisk disk = destPool.createPhysicalDisk(UUID.randomUUID().toString(), format, template.getVirtualSize());
if (format == PhysicalDiskFormat.QCOW2) {
Script.runSimpleBashScript("qemu-img create -f qcow2 -b " + template.getPath() + " " + disk.getPath());
} else {
Script.runSimpleBashScript("cp " + template.getPath() + " " + disk.getPath());
}
return disk;
}
@Override
public KVMPhysicalDisk createTemplateFromDisk(KVMPhysicalDisk disk,
String name, PhysicalDiskFormat format, long size,
KVMStoragePool destPool) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<KVMPhysicalDisk> listPhysicalDisks(String storagePoolUuid, KVMStoragePool pool) {
LibvirtStoragePool libvirtPool = (LibvirtStoragePool)pool;
StoragePool virtPool = libvirtPool.getPool();
List<KVMPhysicalDisk> disks = new ArrayList<KVMPhysicalDisk>();
try {
String[] vols = virtPool.listVolumes();
for (String volName : vols) {
KVMPhysicalDisk disk = this.getPhysicalDisk(volName, pool);
disks.add(disk);
}
return disks;
} catch (LibvirtException e) {
throw new CloudRuntimeException(e.toString());
}
}
@Override
public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk,
String name, KVMStoragePool destPool) {
KVMPhysicalDisk newDisk = destPool.createPhysicalDisk(name, disk.getVirtualSize());
String sourcePath = disk.getPath();
String destPath = newDisk.getPath();
Script.runSimpleBashScript("qemu-img convert -f qcow2 -O qcow2 " + sourcePath + " " + destPath);
return newDisk;
}
@Override
public KVMStoragePool getStoragePoolByUri(String uri) {
URI storageUri = null;
try {
storageUri = new URI(uri);
} catch (URISyntaxException e) {
throw new CloudRuntimeException(e.toString());
}
String sourcePath = null;
String uuid = null;
String sourceHost = "";
StoragePoolType protocal = null;
if (storageUri.getScheme().equalsIgnoreCase("nfs")) {
sourcePath = storageUri.getPath();
sourcePath = sourcePath.replace("//", "/");
sourceHost = storageUri.getHost();
uuid = UUID.nameUUIDFromBytes(new String(sourceHost + sourcePath).getBytes()).toString();
protocal = StoragePoolType.NetworkFilesystem;
}
return createStoragePool(uuid, sourceHost, sourcePath, protocal);
}
@Override
public KVMPhysicalDisk getPhysicalDiskFromURI(String uri) {
// TODO Auto-generated method stub
return null;
}
@Override
public KVMPhysicalDisk createDiskFromSnapshot(KVMPhysicalDisk snapshot,
String snapshotName, String name, KVMStoragePool destPool) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean refresh(KVMStoragePool pool) {
LibvirtStoragePool libvirtPool = (LibvirtStoragePool)pool;
StoragePool virtPool = libvirtPool.getPool();
try {
virtPool.refresh(0);
} catch (LibvirtException e) {
return false;
}
return true;
}
}

View File

@ -0,0 +1,131 @@
package com.cloud.agent.storage;
import java.util.List;
import org.libvirt.StoragePool;
import com.cloud.agent.storage.KVMPhysicalDisk.PhysicalDiskFormat;
import com.cloud.storage.Storage.StoragePoolType;
public class LibvirtStoragePool implements KVMStoragePool {
protected String uuid;
protected String uri;
protected long capacity;
protected long used;
protected String name;
protected String localPath;
protected PhysicalDiskFormat defaultFormat;
protected StoragePoolType type;
protected StorageAdaptor _storageAdaptor;
protected StoragePool _pool;
public LibvirtStoragePool(String uuid, String name, StoragePoolType type, StorageAdaptor adaptor, StoragePool pool) {
this.uuid = uuid;
this.name = name;
this.type = type;
this._storageAdaptor = adaptor;
this.capacity = 0;
this.used = 0;
this._pool = pool;
}
public void setCapacity(long capacity) {
this.capacity = capacity;
}
@Override
public long getCapacity() {
return this.capacity;
}
public void setUsed(long used) {
this.used = used;
}
@Override
public long getUsed() {
return this.used;
}
public StoragePoolType getStoragePoolType() {
return this.type;
}
public String getName() {
return this.name;
}
public String getUuid() {
return this.uuid;
}
public String uri() {
return this.uri;
}
public PhysicalDiskFormat getDefaultFormat() {
if (getStoragePoolType() == StoragePoolType.CLVM) {
return PhysicalDiskFormat.RAW;
} else {
return PhysicalDiskFormat.QCOW2;
}
}
@Override
public KVMPhysicalDisk createPhysicalDisk(String name, PhysicalDiskFormat format, long size) {
return this._storageAdaptor.createPhysicalDisk(name, this, format, size);
}
@Override
public KVMPhysicalDisk createPhysicalDisk(String name, long size) {
return this._storageAdaptor.createPhysicalDisk(name, this, this.getDefaultFormat(), size);
}
@Override
public KVMPhysicalDisk getPhysicalDisk(String volumeUuid) {
return this._storageAdaptor.getPhysicalDisk(volumeUuid, this);
}
@Override
public boolean deletePhysicalDisk(String uuid) {
return this._storageAdaptor.deletePhysicalDisk(uuid, this);
}
@Override
public List<KVMPhysicalDisk> listPhysicalDisks() {
return this._storageAdaptor.listPhysicalDisks(this.uuid, this);
}
@Override
public boolean refresh() {
return this._storageAdaptor.refresh(this);
}
@Override
public boolean isExternalSnapshot() {
if (this.type == StoragePoolType.Filesystem) {
return false;
}
return true;
}
@Override
public String getLocalPath() {
return this.localPath;
}
public void setLocalPath(String localPath) {
this.localPath = localPath;
}
@Override
public StoragePoolType getType() {
return this.type;
}
public StoragePool getPool() {
return this._pool;
}
}

View File

@ -0,0 +1,25 @@
package com.cloud.agent.storage;
import java.util.List;
import com.cloud.agent.storage.KVMPhysicalDisk.PhysicalDiskFormat;
import com.cloud.storage.Storage.StoragePoolType;
public interface StorageAdaptor {
public KVMStoragePool getStoragePool(String uuid);
public KVMPhysicalDisk getPhysicalDisk(String volumeUuid, KVMStoragePool pool);
public KVMStoragePool createStoragePool(String name, String host, String path, StoragePoolType type);
public boolean deleteStoragePool(String uuid);
public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, PhysicalDiskFormat format, long size);
public boolean deletePhysicalDisk(String uuid, KVMStoragePool pool);
public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template, String name, PhysicalDiskFormat format, long size, KVMStoragePool destPool);
public KVMPhysicalDisk createTemplateFromDisk(KVMPhysicalDisk disk, String name, PhysicalDiskFormat format, long size, KVMStoragePool destPool);
public List<KVMPhysicalDisk> listPhysicalDisks(String storagePoolUuid, KVMStoragePool pool);
public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name, KVMStoragePool destPools);
public KVMPhysicalDisk createDiskFromSnapshot(KVMPhysicalDisk snapshot, String snapshotName, String name, KVMStoragePool destPool);
public KVMStoragePool getStoragePoolByUri(String uri);
public KVMPhysicalDisk getPhysicalDiskFromURI(String uri);
boolean refresh(KVMStoragePool pool);
}

View File

@ -97,6 +97,7 @@ public class Storage {
Iscsi(true), //for e.g., ZFS Comstar
ISO(false), // for iso image
LVM(false), // XenServer local LVM SR
CLVM(true),
SharedMountPoint(true),
VMFS(true), // VMware VMFS storage
PreSetup(true), // for XenServer, Storage Pool is set up by customers.