From f8778ea4c6748d85710c5175e034af5d98dfc262 Mon Sep 17 00:00:00 2001 From: Edison Su Date: Fri, 28 Jan 2011 04:37:18 -0500 Subject: [PATCH] add sharedmountpoint storage pool to support all kinds of clustered file system --- .../computing/LibvirtCapXMLParser.java | 1 + .../computing/LibvirtComputingResource.java | 482 +++--------------- .../computing/LibvirtStoragePoolDef.java | 24 +- .../LibvirtStoragePoolXMLParser.java | 97 ++++ .../computing/LibvirtStorageResource.java | 382 ++++++++++++++ api/src/com/cloud/storage/Storage.java | 1 + .../com/cloud/storage/StorageManagerImpl.java | 19 +- 7 files changed, 591 insertions(+), 415 deletions(-) create mode 100644 agent/src/com/cloud/agent/resource/computing/LibvirtStoragePoolXMLParser.java create mode 100644 agent/src/com/cloud/agent/resource/computing/LibvirtStorageResource.java diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtCapXMLParser.java b/agent/src/com/cloud/agent/resource/computing/LibvirtCapXMLParser.java index d9a063b920b..6d3c1cf6f25 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtCapXMLParser.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtCapXMLParser.java @@ -26,6 +26,7 @@ import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; + /** * @author chiradeep * diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java index 8598b9fa29b..f520faad07d 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java @@ -292,15 +292,12 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv protected String _linkLocalBridgeName; protected String _publicBridgeName; protected String _privateBridgeIp; - protected String _domrArch; - protected String _domrKernel; - protected String _domrRamdisk; protected String _pool; protected String _localGateway; private boolean _can_bridge_firewall; private Pair _pifs; private final Map _vmStats = new ConcurrentHashMap(); - private final Map _storagePools = new ConcurrentHashMap(); + protected boolean _disconnected = true; protected int _timeout; @@ -318,10 +315,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv protected HashMap _vms = new HashMap(20); protected List _vmsKilled = new ArrayList(); - - protected BitSet _domrIndex; private VirtualRoutingResource _virtRouterResource; + private LibvirtStorageResource _storageResource; private String _pingTestPath; @@ -393,8 +389,18 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv if (! success) { return false; } + + try { + Class clazz = Class.forName("com.cloud.storage.JavaStorageLayer"); + _storage = (StorageLayer)ComponentLocator.inject(clazz); + _storage.configure("StorageLayer", params); + } catch (ClassNotFoundException e) { + throw new ConfigurationException("Unable to find class " + "com.cloud.storage.JavaStorageLayer"); + } + _virtRouterResource = new VirtualRoutingResource(); + // Set the domr scripts directory params.put("domr.scripts.dir", "scripts/network/domr/kvm"); @@ -550,13 +556,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv value = (String)params.get("stop.script.timeout"); _stopTimeout = NumbersUtil.parseInt(value, 120) * 1000; - - _domrArch = (String)params.get("domr.arch"); - if (_domrArch == null ) { - _domrArch = "i686"; - } else if (!"i686".equalsIgnoreCase(_domrArch) && !"x86_64".equalsIgnoreCase(_domrArch)) { - throw new ConfigurationException("Invalid architecture (domr.arch) -- needs to be i686 or x86_64"); - } value = (String)params.get("host.reserved.mem.mb"); _dom0MinMem = NumbersUtil.parseInt(value, 0)*1024*1024; @@ -586,21 +585,12 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } catch (LibvirtException e) { } - String[] info = NetUtils.getNetworkParams(_privateNic); + _monitor = new KVMHAMonitor(null, info[0], _heartBeatPath); Thread ha = new Thread(_monitor); ha.start(); - - - try { - Class clazz = Class.forName("com.cloud.storage.JavaStorageLayer"); - _storage = (StorageLayer)ComponentLocator.inject(clazz); - _storage.configure("StorageLayer", params); - } catch (ClassNotFoundException e) { - throw new ConfigurationException("Unable to find class " + "com.cloud.storage.JavaStorageLayer"); - } _sysvmISOPath = (String)params.get("systemvm.iso.path"); if (_sysvmISOPath == null) { @@ -642,6 +632,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv s_logger.debug("Failed to found the local gateway"); } + _storageResource = new LibvirtStorageResource(this, _storage, _createvmPath, _timeout, _mountPoint, _monitor); + + return true; } @@ -674,8 +667,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } } - - boolean isDirectAttachedNetwork(String type) { if ("untagged".equalsIgnoreCase(type)) { return true; @@ -885,21 +876,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv protected Answer execute(DeleteStoragePoolCommand cmd) { try { Connect conn = LibvirtConnection.getConnection(); - StoragePool pool = getStoragePool(conn, cmd.getPool().getUuid()); - - synchronized (getStoragePool(pool.getUUIDString())) { - pool.destroy(); - pool.undefine(); - } - - KVMHABase.NfsStoragePool sp = new KVMHABase.NfsStoragePool(cmd.getPool().getUuid(), - cmd.getPool().getHost(), - cmd.getPool().getPath(), - _mountPoint + File.separator + cmd.getPool().getUuid(), - PoolType.PrimaryStorage); - _monitor.removeStoragePool(sp); - rmStoragePool(cmd.getPool().getUuid()); - + _storageResource.deleteStoragePool(conn, cmd.getPool()); return new Answer(cmd); } catch (LibvirtException e) { return new Answer(cmd, false, e.toString()); @@ -941,17 +918,12 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv long disksize; try { Connect conn = LibvirtConnection.getConnection(); - primaryPool = getStoragePool(conn, pool.getUuid()); + primaryPool = _storageResource.getStoragePool(conn, pool.getUuid()); if (cmd.getTemplateUrl() != null) { - tmplVol = getVolume(conn, primaryPool, cmd.getTemplateUrl()); - if (tmplVol == null) { - String result = "Failed to get tmpl vol"; - s_logger.debug(result); - return new CreateAnswer(cmd, result); - } + tmplVol = _storageResource.getVolume(conn, primaryPool, cmd.getTemplateUrl()); - vol = createVolume(primaryPool, tmplVol); + vol = _storageResource.createVolumeFromTempl(primaryPool, tmplVol); if (vol == null) { return new Answer(cmd, false, " Can't create storage volume on storage pool"); @@ -959,10 +931,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv disksize = tmplVol.getInfo().capacity; } else { disksize = dskch.getSize(); - LibvirtStorageVolumeDef volDef = new LibvirtStorageVolumeDef(UUID.randomUUID().toString(), disksize, volFormat.QCOW2, null, null); - s_logger.debug(volDef.toString()); - vol = primaryPool.storageVolCreateXML(volDef.toString(), 0); - + vol = _storageResource.createVolume(conn, primaryPool, UUID.randomUUID().toString(), dskch.getSize(), volFormat.QCOW2); } VolumeTO volume = new VolumeTO(cmd.getVolumeId(), dskch.getType(), getStorageResourceType(), pool.getType(), pool.getUuid(), pool.getPath(), vol.getName(),vol.getKey(), disksize, null); @@ -993,18 +962,15 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv try { Connect conn = LibvirtConnection.getConnection(); - StorageVol volume = getVolumeFromPath(conn, vol.getPath()); - if (volume == null) { - s_logger.debug("Failed to find the volume: " + vol.getPath()); - return new Answer(cmd, true, "Success"); - } + StoragePool pool = _storageResource.getStoragePool(conn, vol.getPoolUuid()); + StorageVol volume = _storageResource.getVolume(conn, pool, vol.getPath()); volume.delete(0); volume.free(); + return new Answer(cmd, true, "Success"); } catch (LibvirtException e) { s_logger.debug("Failed to delete volume: " + e.toString()); return new Answer(cmd, false, e.toString()); } - return new Answer(cmd, true, "Success"); } protected ManageSnapshotAnswer execute(final ManageSnapshotCommand cmd) { @@ -1078,8 +1044,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv try { Connect conn = LibvirtConnection.getConnection(); - StoragePool secondaryStoragePool = getNfsSPbyURI(conn, new URI(secondaryStoragePoolURL)); - String ssPmountPath = _mountPoint + File.separator + secondaryStoragePool.getUUIDString(); + StoragePool secondaryStoragePool = _storageResource.getStoragePoolbyURI(conn, new URI(secondaryStoragePoolURL)); + LibvirtStoragePoolDef spd = _storageResource.getStoragePoolDef(conn, secondaryStoragePool); + String ssPmountPath = spd.getTargetPath(); snapshotDestPath = ssPmountPath + File.separator + "snapshots" + File.separator + dcId + File.separator + accountId + File.separator + volumeId; Script command = new Script(_manageSnapshotPath, 1800000, s_logger); command.add("-b", snapshotPath); @@ -1142,8 +1109,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv Long volumeId = cmd.getVolumeId(); try { Connect conn = LibvirtConnection.getConnection(); - StoragePool secondaryStoragePool = getNfsSPbyURI(conn, new URI(cmd.getSecondaryStoragePoolURL())); - String ssPmountPath = _mountPoint + File.separator + secondaryStoragePool.getUUIDString(); + StoragePool secondaryStoragePool = _storageResource.getStoragePoolbyURI(conn, new URI(cmd.getSecondaryStoragePoolURL())); + LibvirtStoragePoolDef spd = _storageResource.getStoragePoolDef(conn, secondaryStoragePool); + String ssPmountPath = spd.getTargetPath(); String snapshotDestPath = ssPmountPath + File.separator + "snapshots" + File.separator + dcId + File.separator + accountId + File.separator + volumeId; final Script command = new Script(_manageSnapshotPath, _timeout, s_logger); @@ -1165,8 +1133,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv Long volumeId = cmd.getVolumeId(); try { Connect conn = LibvirtConnection.getConnection(); - StoragePool secondaryStoragePool = getNfsSPbyURI(conn, new URI(cmd.getSecondaryStoragePoolURL())); - String ssPmountPath = _mountPoint + File.separator + secondaryStoragePool.getUUIDString(); + StoragePool secondaryStoragePool = _storageResource.getStoragePoolbyURI(conn, new URI(cmd.getSecondaryStoragePoolURL())); + LibvirtStoragePoolDef spd = _storageResource.getStoragePoolDef(conn, secondaryStoragePool); + String ssPmountPath = spd.getTargetPath(); String snapshotDestPath = ssPmountPath + File.separator + "snapshots" + File.separator + dcId + File.separator + accountId + File.separator + volumeId; final Script command = new Script(_manageSnapshotPath, _timeout, s_logger); @@ -1186,11 +1155,13 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv try { Connect conn = LibvirtConnection.getConnection(); /*Make sure secondary storage is mounted*/ - getNfsSPbyURI(conn, new URI(cmd.getSecondaryStoragePoolURL())); - + _storageResource.getStoragePoolbyURI(conn, new URI(cmd.getSecondaryStoragePoolURL())); + String snapshotPath = cmd.getSnapshotUuid(); String primaryUuid = cmd.getPrimaryStoragePoolNameLabel(); - String primaryPath = _mountPoint + File.separator + primaryUuid; + 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); @@ -1216,9 +1187,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv StoragePool secondaryPool; try { Connect conn = LibvirtConnection.getConnection(); - secondaryPool = getNfsSPbyURI(conn, new URI(cmd.getSecondaryStoragePoolURL())); - /*TODO: assuming all the storage pools mounted under _mountPoint, the mount point should be got from pool.dumpxml*/ - String templatePath = _mountPoint + File.separator + secondaryPool.getUUIDString() + File.separator + templateInstallFolder; + secondaryPool = _storageResource.getStoragePoolbyURI(conn, new URI(cmd.getSecondaryStoragePoolURL())); + LibvirtStoragePoolDef spd = _storageResource.getStoragePoolDef(conn, secondaryPool); + String templatePath = spd.getTargetPath() + File.separator + templateInstallFolder; _storage.mkdirs(templatePath); String tmplPath = templateInstallFolder + File.separator + tmplFileName; @@ -1259,7 +1230,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv StoragePoolInfo spi = null; try { Connect conn = LibvirtConnection.getConnection(); - sp = getStoragePool(conn, cmd.getStorageId()); + sp = _storageResource.getStoragePool(conn, cmd.getStorageId()); spi = sp.getInfo(); return new GetStorageStatsAnswer(cmd, spi.capacity, spi.allocation); } catch (LibvirtException e) { @@ -1276,9 +1247,10 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv String templateFolder = cmd.getAccountId() + File.separator + cmd.getTemplateId() + File.separator; String templateInstallFolder = "/template/tmpl/" + templateFolder; - secondaryStorage = getNfsSPbyURI(conn, new URI(secondaryStorageURL)); - /*TODO: assuming all the storage pools mounted under _mountPoint, the mount point should be got from pool.dumpxml*/ - String tmpltPath = _mountPoint + File.separator + secondaryStorage.getUUIDString() + templateInstallFolder; + secondaryStorage = _storageResource.getStoragePoolbyURI(conn, new URI(secondaryStorageURL)); + + LibvirtStoragePoolDef spd = _storageResource.getStoragePoolDef(conn, secondaryStorage); + String tmpltPath = spd.getTargetPath() + File.separator + templateInstallFolder; _storage.mkdirs(tmpltPath); Script command = new Script(_createTmplPath, _timeout, s_logger); @@ -1329,56 +1301,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } } - private StoragePool getNfsSPbyURI(Connect conn, URI uri) throws LibvirtException { - String sourcePath = uri.getPath(); - sourcePath = sourcePath.replace("//", "/"); - String sourceHost = uri.getHost(); - String uuid = UUID.nameUUIDFromBytes(new String(sourceHost + sourcePath).getBytes()).toString(); - String targetPath = _mountPoint + File.separator + uuid; - StoragePool sp = null; - try { - sp = conn.storagePoolLookupByUUIDString(uuid); - } catch (LibvirtException e) { - } - - if (sp == null) { - try { - _storage.mkdir(targetPath); - LibvirtStoragePoolDef spd = new LibvirtStoragePoolDef(poolType.NFS, uuid, uuid, - sourceHost, sourcePath, targetPath); - s_logger.debug(spd.toString()); - addStoragePool(uuid); - - 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; - } - } protected PrimaryStorageDownloadAnswer execute(final PrimaryStorageDownloadCommand cmd) { String tmplturl = cmd.getUrl(); int index = tmplturl.lastIndexOf("/"); @@ -1393,17 +1315,15 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv StorageVol tmplVol = null; StorageVol primaryVol = null; String result; + Connect conn = null; try { - Connect conn = LibvirtConnection.getConnection(); - secondaryPool = getNfsSPbyURI(conn, new URI(mountpoint)); - if (secondaryPool == null) { - return new PrimaryStorageDownloadAnswer(" Failed to create storage pool"); - } + conn = LibvirtConnection.getConnection(); + secondaryPool = _storageResource.getStoragePoolbyURI(conn, new URI(mountpoint)); + + /*Get template vol*/ if (tmpltname == null) { /*Hack: server just pass the directory of system vm template, need to scan the folder */ - synchronized (getStoragePool(secondaryPool.getUUIDString())) { - secondaryPool.refresh(0); - } + _storageResource.storagePoolRefresh(secondaryPool); String[] volumes = secondaryPool.listVolumes(); if (volumes == null) { return new PrimaryStorageDownloadAnswer("Failed to get volumes from pool: " + secondaryPool.getName()); @@ -1418,25 +1338,21 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return new PrimaryStorageDownloadAnswer("Failed to get template from pool: " + secondaryPool.getName()); } } - tmplVol = getVolume(conn, secondaryPool, getPathOfStoragePool(secondaryPool) + tmpltname); - if (tmplVol == null) { - return new PrimaryStorageDownloadAnswer(" Can't find volume"); - } - primaryPool = getStoragePool(conn, cmd.getPoolUuid()); + 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 = copyVolume(primaryPool, vol, tmplVol); - if (primaryVol == null) { - return new PrimaryStorageDownloadAnswer(" Can't create storage volume on storage pool"); - } + primaryVol = _storageResource.copyVolume(primaryPool, vol, tmplVol); + StorageVolInfo priVolInfo = primaryVol.getInfo(); return new PrimaryStorageDownloadAnswer(primaryVol.getKey(), priVolInfo.allocation); } catch (LibvirtException e) { - result = "Failed to download template: " + e.toString(); - s_logger.debug(result); - return new PrimaryStorageDownloadAnswer(result); + s_logger.debug(e.toString()); + return new PrimaryStorageDownloadAnswer(e.toString()); } catch (URISyntaxException e) { - // TODO Auto-generated catch block return new PrimaryStorageDownloadAnswer(e.toString()); } finally { try { @@ -1451,16 +1367,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv if (tmplVol != null) { tmplVol.free(); } + + _storageResource.deleteStoragePool(conn, secondaryPool); - if (secondaryPool != null) { - String uuid = secondaryPool.getUUIDString(); - synchronized (getStoragePool(uuid)) { - secondaryPool.destroy(); - secondaryPool.undefine(); - secondaryPool.free(); - } - rmStoragePool(uuid); - } } catch (LibvirtException l) { } @@ -1468,68 +1377,11 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } - private StoragePool createNfsStoragePool(Connect conn, StorageFilerTO pool) { - String targetPath = _mountPoint + File.separator + pool.getUuid(); - LibvirtStoragePoolDef spd = new LibvirtStoragePoolDef(poolType.NFS, pool.getUuid(), pool.getUuid(), - pool.getHost(), pool.getPath(), targetPath); - _storage.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 getStoragePool(Connect conn, StorageFilerTO pool) { - StoragePool sp = null; - try { - sp = conn.storagePoolLookupByUUIDString(pool.getUuid()); - } catch (LibvirtException e) { - - } - - if (sp == null) { - if (pool.getType() == StoragePoolType.NetworkFilesystem) { - sp = createNfsStoragePool(conn, pool); - } - 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) { - - } - return sp; - } - + protected Answer execute(ModifyStoragePoolCommand cmd) { try { Connect conn = LibvirtConnection.getConnection(); - StoragePool storagePool = getStoragePool(conn, cmd.getPool()); + StoragePool storagePool = _storageResource.getStoragePool(conn, cmd.getPool()); if (storagePool == null) { return new Answer(cmd, false, " Failed to create storage pool"); } @@ -1544,14 +1396,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv spi.allocation, tInfo); - KVMHABase.NfsStoragePool pool = new KVMHABase.NfsStoragePool(cmd.getPool().getUuid(), - cmd.getPool().getHost(), - cmd.getPool().getPath(), - _mountPoint + File.separator + cmd.getPool().getUuid(), - PoolType.PrimaryStorage); - _monitor.addStoragePool(pool); - addStoragePool(cmd.getPool().getUuid()); - storagePool.free(); return answer; } catch (LibvirtException e) { @@ -1670,26 +1514,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return new AttachVolumeAnswer(cmd, cmd.getDeviceId()); } - protected static List findVolumes(final List volumes, final Volume.VolumeType vType, boolean singleVolume) { - List filteredVolumes = new ArrayList(); - - if (volumes == null) { - return filteredVolumes; - } - - for (final VolumeVO v: volumes) { - if (v.getVolumeType() == vType) { - filteredVolumes.add(v); - - if(singleVolume) { - return filteredVolumes; - } - } - } - - return filteredVolumes; - } - private Answer execute(ReadyCommand cmd) { return new ReadyAnswer(cmd); } @@ -2115,30 +1939,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } } - private 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 = getNfsSPbyURI(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) { - - } - } - } + private void handleVmStartFailure(Connect conn, String vmName, LibvirtVMDef vm) { if (vm != null && vm.getDevices() != null) { @@ -2272,7 +2073,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv private String getVolumePath(Connect conn, VolumeTO volume) throws LibvirtException, URISyntaxException { if (volume.getType() == Volume.VolumeType.ISO && volume.getPath() != null) { - StorageVol vol = getVolumeFromURI(conn, volume.getPath()); + StorageVol vol = _storageResource.getVolumeFromURI(conn, volume.getPath()); return vol.getPath(); } else { return volume.getPath(); @@ -2322,7 +2123,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv List disks = vm.getDevices().getDisks(); DiskDef rootDisk = disks.get(0); - StorageVol tmplVol = createTmplDataDisk(conn, rootDisk.getDiskPath(), 10L * 1024 * 1024); + StorageVol tmplVol = _storageResource.createTmplDataDisk(conn, rootDisk.getDiskPath(), 10L * 1024 * 1024); String datadiskPath = tmplVol.getKey(); /*add patch disk*/ @@ -2409,10 +2210,9 @@ 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 = getVolumeFromURI(conn, isoPath); - + StorageVol isoVol = _storageResource.getVolumeFromURI(conn, isoPath); isoPath = isoVol.getPath(); - + DiskDef iso = new DiskDef(); iso.defFileBasedDisk(isoPath, "hdc", DiskDef.diskBus.IDE, DiskDef.diskFmtType.RAW); iso.setDeviceType(DiskDef.deviceType.CDROM); @@ -3134,7 +2934,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } } - private boolean isCentosHost() { + public boolean isCentosHost() { if (_hvVersion <=9 ) { return true; } else { @@ -3142,24 +2942,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } } - private StorageVol createTmplDataDisk(Connect conn, String rootkPath, long size) throws LibvirtException, InternalErrorException { - /*create a templ data disk, to contain patches*/ - StorageVol rootVol = getVolumeFromPath(conn, rootkPath); - StoragePool rootPool = rootVol.storagePoolLookupByVolume(); - LibvirtStorageVolumeDef volDef = new LibvirtStorageVolumeDef(UUID.randomUUID().toString(), size, volFormat.RAW, null, null); - StorageVol dataVol = rootPool.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; - } - private InterfaceDef.nicModel getGuestNicModel(String guestOSType) { if (isGuestPVEnabled(guestOSType)) { return InterfaceDef.nicModel.VIRTIO; @@ -3320,114 +3102,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } } - private StorageVol copyVolume(StoragePool destPool, LibvirtStorageVolumeDef destVol, StorageVol srcVol) throws LibvirtException { - if (isCentosHost()) { - /*define a volume, then override the file*/ - - StorageVol vol = destPool.storageVolCreateXML(destVol.toString(), 0); - String srcPath = srcVol.getKey(); - String destPath = vol.getKey(); - Script.runSimpleBashScript("cp " + srcPath + " " + destPath ); - return vol; - } else { - return destPool.storageVolCreateXMLFrom(destVol.toString(), srcVol, 0); - } - } - - private StorageVol createVolume(StoragePool destPool, StorageVol tmplVol) throws LibvirtException { - if (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 StorageVol getVolume(Connect conn, StoragePool pool, String volKey) { - StorageVol vol = null; - try { - vol = conn.storageVolLookupByKey(volKey); - } catch (LibvirtException e) { - - } - if (vol == null) { - try { - synchronized (getStoragePool(pool.getUUIDString())) { - pool.refresh(0); - } - } catch (LibvirtException e) { - - } - try { - vol = conn.storageVolLookupByKey(volKey); - } catch (LibvirtException e) { - - } - } - return vol; - } - - private StorageVol getVolumeFromPath(Connect conn, String volKey) throws LibvirtException{ - StorageVol vol = null; - - try { - vol = conn.storageVolLookupByKey(volKey); - } catch (LibvirtException e) { - - } - if (vol == null) { - StoragePool pool = null; - String token[] = volKey.split("/"); - if (token.length <= 2) { - s_logger.debug("what the heck of volkey: " + volKey); - return null; - } - String poolUUID = token[token.length - 2]; - pool = getStoragePool(conn, poolUUID); - synchronized (getStoragePool(poolUUID)) { - pool.refresh(0); - } - vol = conn.storageVolLookupByKey(volKey); - - } - return vol; - } - private String getPathOfStoragePool(StoragePool pool) throws LibvirtException { - return _mountPoint + File.separator + pool.getUUIDString() + File.separator; - } - - 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); - } - } - private boolean can_bridge_firewall(String prvNic) { Script cmd = new Script(_securityGroupPath, _timeout, s_logger); cmd.add("can_bridge_firewall"); @@ -3611,19 +3285,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } } - private 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; - } + private Answer execute(NetworkRulesSystemVmCommand cmd) { boolean success = false; diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtStoragePoolDef.java b/agent/src/com/cloud/agent/resource/computing/LibvirtStoragePoolDef.java index 5b86525a932..4c93877c25f 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtStoragePoolDef.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtStoragePoolDef.java @@ -21,7 +21,7 @@ package com.cloud.agent.resource.computing; public class LibvirtStoragePoolDef { public enum poolType { ISCSI("iscsi"), - NFS("netfs"), + NETFS("netfs"), DIR("dir"); String _poolType; poolType(String poolType) { @@ -48,6 +48,26 @@ public class LibvirtStoragePoolDef { _targetPath = targetPath; } + public String getPoolName() { + return _poolName; + } + + public poolType getPoolType() { + return _poolType; + } + + public String getSourceHost() { + return _sourceHost; + } + + public String getSourceDir() { + return _sourceDir; + } + + public String getTargetPath() { + return _targetPath; + } + @Override public String toString() { StringBuilder storagePoolBuilder = new StringBuilder(); @@ -55,7 +75,7 @@ public class LibvirtStoragePoolDef { storagePoolBuilder.append("" + _poolName + "\n"); if (_uuid != null) storagePoolBuilder.append("" + _uuid + "\n"); - if (_poolType == poolType.NFS) { + if (_poolType == poolType.NETFS) { storagePoolBuilder.append("\n"); storagePoolBuilder.append("\n"); storagePoolBuilder.append("\n"); diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtStoragePoolXMLParser.java b/agent/src/com/cloud/agent/resource/computing/LibvirtStoragePoolXMLParser.java new file mode 100644 index 00000000000..af063703a54 --- /dev/null +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtStoragePoolXMLParser.java @@ -0,0 +1,97 @@ +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.*; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + + + +public class LibvirtStoragePoolXMLParser{ + private static final Logger s_logger = Logger.getLogger(LibvirtStoragePoolXMLParser.class); + public LibvirtStoragePoolDef parseStoragePoolXML(String poolXML) { + DocumentBuilder builder; + try { + builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + + InputSource is = new InputSource(); + is.setCharacterStream(new StringReader(poolXML)); + Document doc = builder.parse(is); + + Element rootElement = doc.getDocumentElement(); + String type = rootElement.getAttribute("type"); + + String uuid = getTagValue("uuid", rootElement); + + String poolName = getTagValue("name", rootElement); + + Element source = (Element)rootElement.getElementsByTagName("source").item(0); + String host = getAttrValue("host", "name", source); + String path = getAttrValue("dir", "path", source); + + Element target = (Element)rootElement.getElementsByTagName("target").item(0); + String targetPath = getTagValue("path", target); + + return new LibvirtStoragePoolDef(LibvirtStoragePoolDef.poolType.valueOf(type.toUpperCase()), poolName, uuid, host, path, targetPath); + } 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 = "" + + "test" + + "bf723c83-4b95-259c-7089-60776e61a11f" + + "20314165248" + + "1955450880" + + "18358714368" + + "" + + "" + + "" + + "" + + "" + + "" + + "/media" + + "" + + "0700" + + "0" + + "0" + + "" + + "" + + ""; + + LibvirtStoragePoolXMLParser parser = new LibvirtStoragePoolXMLParser(); + LibvirtStoragePoolDef pool = parser.parseStoragePoolXML(storagePool); + s_logger.debug(pool.toString()); + } +} diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtStorageResource.java b/agent/src/com/cloud/agent/resource/computing/LibvirtStorageResource.java new file mode 100644 index 00000000000..07950c9f88f --- /dev/null +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtStorageResource.java @@ -0,0 +1,382 @@ +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.to.StorageFilerTO; +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.storage.Storage.StoragePoolType; +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 _storagePools = new ConcurrentHashMap(); + 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()); + + synchronized (getStoragePool(pool.getUUIDString())) { + pool.destroy(); + pool.undefine(); + } + + LibvirtStoragePoolDef spd = getStoragePoolDef(conn, pool); + + 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, String rootkPath, long size) throws LibvirtException, InternalErrorException { + /*create a templ data disk, to contain patches*/ + StorageVol rootVol = conn.storageVolLookupByKey(rootkPath); + StoragePool rootPool = rootVol.storagePoolLookupByVolume(); + LibvirtStorageVolumeDef volDef = new LibvirtStorageVolumeDef(UUID.randomUUID().toString(), size, volFormat.RAW, null, null); + StorageVol dataVol = rootPool.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 = uri.getPath(); + sourcePath = sourcePath.replace("//", "/"); + String sourceHost = uri.getHost(); + String uuid = UUID.nameUUIDFromBytes(new String(sourceHost + sourcePath).getBytes()).toString(); + String targetPath = _mountPoint + File.separator + uuid; + StoragePool sp = null; + try { + sp = conn.storagePoolLookupByUUIDString(uuid); + } catch (LibvirtException e) { + } + + if (sp == null) { + try { + _storageLayer.mkdir(targetPath); + LibvirtStoragePoolDef spd = new LibvirtStoragePoolDef(poolType.NETFS, uuid, uuid, + sourceHost, sourcePath, targetPath); + s_logger.debug(spd.toString()); + addStoragePool(uuid); + + 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 { + 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) throws LibvirtException { + if (_computingResource.isCentosHost()) { + /*define a volume, then override the file*/ + + StorageVol vol = destPool.storageVolCreateXML(destVol.toString(), 0); + String srcPath = srcVol.getKey(); + String destPath = vol.getKey(); + Script.runSimpleBashScript("cp " + srcPath + " " + destPath ); + return vol; + } else { + return destPool.storageVolCreateXMLFrom(destVol.toString(), srcVol, 0); + } + } + + 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) { + + } + } + } + +} diff --git a/api/src/com/cloud/storage/Storage.java b/api/src/com/cloud/storage/Storage.java index 8d53d335eac..3d4f73cb3cc 100644 --- a/api/src/com/cloud/storage/Storage.java +++ b/api/src/com/cloud/storage/Storage.java @@ -93,6 +93,7 @@ public class Storage { Iscsi(true), //for e.g., ZFS Comstar ISO(false), // for iso image LVM(false), // XenServer local LVM SR + SharedMountPoint(true), VMFS(true); // VMware VMFS storage boolean shared; diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index c5d763dbc88..1de507adab3 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -1039,6 +1039,11 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag if (uriHost == null || uriPath == null || uriHost.trim().isEmpty() || uriPath.trim().isEmpty()) { throw new ServerApiException(BaseCmd.PARAM_ERROR, "host or path is null, should be nfs://hostname/path"); } + } else if (uri.getScheme().equalsIgnoreCase("sharedMountPoint")) { + String uriPath = uri.getPath(); + if (uriPath == null) { + throw new ServerApiException(BaseCmd.PARAM_ERROR, "host or path is null, should be sharedmountpoint://localhost/path"); + } } } catch (URISyntaxException e) { throw new ServerApiException(BaseCmd.PARAM_ERROR, cmd.getUrl() + " is not a valid uri"); @@ -1078,6 +1083,8 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag port = 0; } pool = new StoragePoolVO(StoragePoolType.Filesystem, "localhost", 0, hostPath); + } else if (scheme.equalsIgnoreCase("sharedMountPoint")) { + pool = new StoragePoolVO(StoragePoolType.SharedMountPoint, storageHost, 0, hostPath); } else if (scheme.equalsIgnoreCase("iscsi")) { String[] tokens = hostPath.split("/"); int lun = NumbersUtil.parseInt(tokens[tokens.length - 1], -1); @@ -1125,7 +1132,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag } List pools = _storagePoolDao.listPoolByHostPath(storageHost, hostPath); - if (!pools.isEmpty()) { + if (!pools.isEmpty() && !scheme.equalsIgnoreCase("sharedmountpoint")) { Long oldPodId = pools.get(0).getPodId(); throw new ResourceInUseException("Storage pool " + uri + " already in use by another pod (id=" + oldPodId + ")", "StoragePool", uri.toASCIIString()); } @@ -1139,7 +1146,12 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag throw new ResourceAllocationException("No host exists to associate a storage pool with"); } long poolId = _storagePoolDao.getNextInSequence(Long.class, "id"); - String uuid = UUID.nameUUIDFromBytes(new String(storageHost + hostPath).getBytes()).toString(); + String uuid = null; + if (scheme.equalsIgnoreCase("sharedmountpoint")) { + uuid = UUID.randomUUID().toString(); + } else { + uuid = UUID.nameUUIDFromBytes(new String(storageHost + hostPath).getBytes()).toString(); + } List spHandles = _storagePoolDao.findIfDuplicatePoolsExistByUUID(uuid); if ((spHandles != null) && (spHandles.size() > 0)) { @@ -1315,7 +1327,8 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag public boolean addPoolToHost(long hostId, StoragePoolVO pool) { s_logger.debug("Adding pool " + pool.getName() + " to host " + hostId); if (pool.getPoolType() != StoragePoolType.NetworkFilesystem && pool.getPoolType() != StoragePoolType.Filesystem - && pool.getPoolType() != StoragePoolType.IscsiLUN && pool.getPoolType() != StoragePoolType.Iscsi && pool.getPoolType() != StoragePoolType.VMFS) { + && pool.getPoolType() != StoragePoolType.IscsiLUN && pool.getPoolType() != StoragePoolType.Iscsi && pool.getPoolType() != StoragePoolType.VMFS + && pool.getPoolType() != StoragePoolType.SharedMountPoint) { return true; }