From 6841e265d3ed19f4fe7bc9244b39f534ac35bbbe Mon Sep 17 00:00:00 2001 From: Edison Su Date: Wed, 2 Nov 2011 18:02:00 -0700 Subject: [PATCH] bug 10330: finally merge Rommer's CLVM patch status 10330: resolved fixed --- .../agent/manager/MockStorageManagerImpl.java | 6 +- .../CloudZonesComputingResource.java | 2 +- .../computing/LibvirtComputingResource.java | 337 +++++++++++------- .../computing/LibvirtDomainXMLParser.java | 4 + .../computing/LibvirtStorageVolumeDef.java | 12 + .../LibvirtStorageVolumeXMLParser.java | 2 +- .../resource/computing/LibvirtVMDef.java | 8 + .../cloud/agent/storage/KVMPhysicalDisk.java | 11 +- .../cloud/agent/storage/KVMStoragePool.java | 2 + .../agent/storage/KVMStoragePoolManager.java | 2 + .../agent/storage/LibvirtStorageAdaptor.java | 88 +++-- .../agent/storage/LibvirtStoragePool.java | 6 + .../cloud/agent/storage/StorageAdaptor.java | 3 +- .../classes/resources/messages.properties | 2 + .../classes/resources/messages_es.properties | 4 +- .../classes/resources/messages_ja.properties | 2 + .../resources/messages_zh_CN.properties | 4 +- .../VirtualRoutingResource.java | 2 +- scripts/storage/qcow2/createtmplt.sh | 9 +- scripts/storage/qcow2/managesnapshot.sh | 173 ++++++--- scripts/vm/hypervisor/kvm/rundomrpre.sh | 12 +- .../com/cloud/storage/StorageManagerImpl.java | 11 +- ui/index.jsp | 1 + ui/jsp/cluster.jsp | 7 + ui/jsp/pod.jsp | 7 + ui/jsp/primarystorage.jsp | 7 + ui/jsp/resource.jsp | 7 + ui/jsp/zone.jsp | 7 + ui/scripts/cloud.core.pod.js | 15 + ui/scripts/cloud.core.resource.js | 23 ++ ui/scripts/cloud.core.zone.js | 6 + 31 files changed, 565 insertions(+), 217 deletions(-) diff --git a/agent-simulator/src/com/cloud/agent/manager/MockStorageManagerImpl.java b/agent-simulator/src/com/cloud/agent/manager/MockStorageManagerImpl.java index 94e1f067248..d295e212108 100644 --- a/agent-simulator/src/com/cloud/agent/manager/MockStorageManagerImpl.java +++ b/agent-simulator/src/com/cloud/agent/manager/MockStorageManagerImpl.java @@ -416,7 +416,7 @@ public class MockStorageManagerImpl implements MockStorageManager { return new BackupSnapshotAnswer(cmd, false, "can't find snapshot" + snapshotPath, null, true); } - String secStorageUrl = cmd.getSecondaryStoragePoolURL(); + String secStorageUrl = cmd.getSecondaryStorageUrl(); MockSecStorageVO secStorage = _mockSecStorageDao.findByUrl(secStorageUrl); if (secStorage == null) { return new BackupSnapshotAnswer(cmd, false, "can't find sec storage" + snapshotPath, null, true); @@ -613,7 +613,7 @@ public class MockStorageManagerImpl implements MockStorageManager { } } - MockSecStorageVO sec = _mockSecStorageDao.findByUrl(cmd.getSecondaryStoragePoolURL()); + MockSecStorageVO sec = _mockSecStorageDao.findByUrl(cmd.getSecondaryStorageUrl()); if (sec == null) { return new CreatePrivateTemplateAnswer(cmd, false, "can't find secondary storage"); } @@ -654,7 +654,7 @@ public class MockStorageManagerImpl implements MockStorageManager { return new CreatePrivateTemplateAnswer(cmd, false, "cant' find volume" + cmd.getVolumePath()); } - MockSecStorageVO sec = _mockSecStorageDao.findByUrl(cmd.getSecondaryStoragePoolURL()); + MockSecStorageVO sec = _mockSecStorageDao.findByUrl(cmd.getSecondaryStorageUrl()); if (sec == null) { return new CreatePrivateTemplateAnswer(cmd, false, "can't find secondary storage"); } diff --git a/agent/src/com/cloud/agent/resource/computing/CloudZonesComputingResource.java b/agent/src/com/cloud/agent/resource/computing/CloudZonesComputingResource.java index 1144f75cb77..84212ef34cc 100644 --- a/agent/src/com/cloud/agent/resource/computing/CloudZonesComputingResource.java +++ b/agent/src/com/cloud/agent/resource/computing/CloudZonesComputingResource.java @@ -194,7 +194,7 @@ public class CloudZonesComputingResource extends LibvirtComputingResource { // Attach each data volume to the VM, if there is a deferred attached disk for (DiskDef disk : vm.getDevices().getDisks()) { if (disk.isAttachDeferred()) { - attachOrDetachDisk(conn, true, vmName, disk.getDiskPath(), disk.getDiskSeq()); + attachOrDetachDevice(conn, true, vmName, disk.toString()); } } diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java index ed812b18f89..d434f1181ef 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java @@ -168,6 +168,7 @@ 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.KVMPhysicalDisk.PhysicalDiskFormat; import com.cloud.agent.storage.KVMStoragePool; import com.cloud.agent.storage.KVMStoragePoolManager; import com.cloud.agent.storage.LibvirtStorageAdaptor; @@ -202,6 +203,7 @@ import com.cloud.vm.DiskProfile; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.VirtualMachineName; +import com.xensource.xenapi.Connection; /** @@ -235,6 +237,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv private String _createTmplPath; private String _heartBeatPath; private String _securityGroupPath; + private String _networkUsagePath; private String _host; private String _dcId; private String _pod; @@ -521,6 +524,11 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv throw new ConfigurationException("Unable to find the security_group.py"); } + _networkUsagePath = Script.findScript("scripts/network/domr/", "networkUsage.sh"); + if (_networkUsagePath == null) { + throw new ConfigurationException("Unable to find the networkUsage.sh"); + } + String value = (String)params.get("developer"); boolean isDeveloper = Boolean.parseBoolean(value); @@ -942,6 +950,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv String volumePath = cmd.getVolumePath(); StorageFilerTO pool = cmd.getPool(); String secondaryStorageUrl = cmd.getSecondaryStorageURL(); + KVMStoragePool secondaryStoragePool = null; try { KVMStoragePool primaryPool = _storagePoolMgr.getStoragePool(pool.getUuid()); String volumeName = UUID.randomUUID().toString(); @@ -949,18 +958,22 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv if (copyToSecondary) { KVMPhysicalDisk volume = primaryPool.getPhysicalDisk(cmd.getVolumePath()); String volumeDestPath = "/volumes/" + cmd.getVolumeId() + File.separator; - KVMStoragePool secondaryStoragePool = _storagePoolMgr.getStoragePoolByURI(secondaryStorageUrl + volumeDestPath); + 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); + 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); + } finally { + if (secondaryStoragePool != null) { + secondaryStoragePool.delete(); + } } } @@ -1036,7 +1049,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv try { KVMStoragePool pool = _storagePoolMgr.getStoragePool(vol.getPoolUuid()); - pool.deletePhysicalDisk(vol.getName()); + pool.deletePhysicalDisk(vol.getPath()); return new Answer(cmd, true, "Success"); } catch (CloudRuntimeException e) { @@ -1112,6 +1125,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv vlanAllocatedToVM.put(ip.getVlanId(), nicPos++); } nicNum = vlanAllocatedToVM.get(ip.getVlanId()); + networkUsage(routerIp, "addVif", "eth" + nicNum); result = _virtRouterResource.assignPublicIpAddress(routerName, routerIp, ip.getPublicIp(), ip.isAdd(), ip.isFirstIP(), ip.isSourceNat(), ip.getVlanId(), ip.getVlanGateway(), ip.getVlanNetmask(), @@ -1125,15 +1139,14 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } return new IpAssocAnswer(cmd, results); } catch (LibvirtException e) { - return new ManageSnapshotAnswer(cmd, false, e.toString()); + return new IpAssocAnswer(cmd, results); } catch (InternalErrorException e) { - return new ManageSnapshotAnswer(cmd, false, e.toString()); + return new IpAssocAnswer(cmd, results); } } protected ManageSnapshotAnswer execute(final ManageSnapshotCommand cmd) { String snapshotName = cmd.getSnapshotName(); - String VolPath = cmd.getVolumePath(); String snapshotPath = cmd.getSnapshotPath(); String vmName = cmd.getVmName(); try { @@ -1150,6 +1163,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } KVMStoragePool primaryPool = _storagePoolMgr.getStoragePool(cmd.getPool().getUuid()); + KVMPhysicalDisk disk = primaryPool.getPhysicalDisk(cmd.getVolumePath()); if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING && !primaryPool.isExternalSnapshot()) { String vmUuid = vm.getUUIDString(); Object[] args = new Object[] {snapshotName, vmUuid}; @@ -1169,10 +1183,11 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv vm.resume(); } } else { + /*VM is not running, create a snapshot by ourself*/ final Script command = new Script(_manageSnapshotPath, _cmdsTimeout, s_logger); if (cmd.getCommandSwitch().equalsIgnoreCase(ManageSnapshotCommand.CREATE_SNAPSHOT)) { - command.add("-c", VolPath); + command.add("-c", disk.getPath()); } else { command.add("-d", snapshotPath); } @@ -1184,11 +1199,12 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return new ManageSnapshotAnswer(cmd, false, "Failed to manage snapshot: " + result); } } + return new ManageSnapshotAnswer(cmd, cmd.getSnapshotId(), disk.getPath() + File.separator + snapshotName, true, null); } catch (LibvirtException e) { s_logger.debug("Failed to manage snapshot: " + e.toString()); return new ManageSnapshotAnswer(cmd, false, "Failed to manage snapshot: " + e.toString()); } - return new ManageSnapshotAnswer(cmd, cmd.getSnapshotId(), cmd.getVolumePath() + File.separator + snapshotName, true, null); + } protected BackupSnapshotAnswer execute(final BackupSnapshotCommand cmd) { @@ -1201,81 +1217,85 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv String snapshotDestPath = null; String snapshotRelPath = null; String vmName = cmd.getVmName(); - + KVMStoragePool secondaryStoragePool = null; try { Connect conn = LibvirtConnection.getConnection(); - KVMStoragePool secondaryStoragePool = _storagePoolMgr.getStoragePoolByURI(secondaryStoragePoolUrl); - - String ssPmountPath = secondaryStoragePool.getLocalPath(); - snapshotRelPath = File.separator + "snapshots" + File.separator + dcId + File.separator + accountId + File.separator + volumeId; + secondaryStoragePool = _storagePoolMgr.getStoragePoolByURI(secondaryStoragePoolUrl); - 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); - command.add("-n", snapshotName); - command.add("-p", snapshotDestPath); - command.add("-t", snapshotName); - String result = command.execute(); - if (result != null) { - s_logger.debug("Failed to backup snaptshot: " + result); - return new BackupSnapshotAnswer(cmd, false, result, null, true); - } - /*Delete the snapshot on primary*/ - - DomainInfo.DomainState state = null; - Domain vm = null; - if (vmName != null) { - try { - vm = getDomain(conn, cmd.getVmName()); - state = vm.getInfo().state; - } catch (LibvirtException e) { - - } - } - - 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); - s_logger.debug(snapshot); - DomainSnapshot snap = vm.snapshotLookupByName(snapshotName); - snap.delete(0); - - /*libvirt on RHEL6 doesn't handle resume event emitted from qemu*/ - vm = getDomain(conn, cmd.getVmName()); - state = vm.getInfo().state; - if (state == DomainInfo.DomainState.VIR_DOMAIN_PAUSED) { - vm.resume(); - } - } else { - command = new Script(_manageSnapshotPath, _cmdsTimeout, s_logger); - command.add("-d", snapshotPath); - command.add("-n", snapshotName); - result = command.execute(); - if (result != null) { - s_logger.debug("Failed to backup snapshot: " + result); - return new BackupSnapshotAnswer(cmd, false, "Failed to backup snapshot: " + result, null, true); - } - } - } catch (LibvirtException e) { - return new BackupSnapshotAnswer(cmd, false, e.toString(), null, true); - } catch (CloudRuntimeException e) { - return new BackupSnapshotAnswer(cmd, false, e.toString(), null, true); - } - return new BackupSnapshotAnswer(cmd, true, null, snapshotRelPath + File.separator + snapshotName, true); + 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; + KVMStoragePool primaryPool = _storagePoolMgr.getStoragePool(cmd.getPrimaryStoragePoolNameLabel()); + KVMPhysicalDisk snapshotDisk = primaryPool.getPhysicalDisk(cmd.getVolumePath()); + Script command = new Script(_manageSnapshotPath, _cmdsTimeout, s_logger); + command.add("-b", snapshotDisk.getPath()); + command.add("-n", snapshotName); + command.add("-p", snapshotDestPath); + command.add("-t", snapshotName); + String result = command.execute(); + if (result != null) { + s_logger.debug("Failed to backup snaptshot: " + result); + return new BackupSnapshotAnswer(cmd, false, result, null, true); + } + /*Delete the snapshot on primary*/ + + DomainInfo.DomainState state = null; + Domain vm = null; + if (vmName != null) { + try { + vm = getDomain(conn, cmd.getVmName()); + state = vm.getInfo().state; + } catch (LibvirtException e) { + + } + } + + 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); + s_logger.debug(snapshot); + DomainSnapshot snap = vm.snapshotLookupByName(snapshotName); + snap.delete(0); + + /*libvirt on RHEL6 doesn't handle resume event emitted from qemu*/ + vm = getDomain(conn, cmd.getVmName()); + state = vm.getInfo().state; + if (state == DomainInfo.DomainState.VIR_DOMAIN_PAUSED) { + vm.resume(); + } + } else { + command = new Script(_manageSnapshotPath, _cmdsTimeout, s_logger); + command.add("-d", snapshotDisk.getPath()); + command.add("-n", snapshotName); + result = command.execute(); + if (result != null) { + s_logger.debug("Failed to backup snapshot: " + result); + return new BackupSnapshotAnswer(cmd, false, "Failed to backup snapshot: " + result, null, true); + } + } + } catch (LibvirtException e) { + return new BackupSnapshotAnswer(cmd, false, e.toString(), null, true); + } catch (CloudRuntimeException e) { + return new BackupSnapshotAnswer(cmd, false, e.toString(), null, true); + } finally { + if (secondaryStoragePool != null) { + secondaryStoragePool.delete(); + } + } + 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(); + KVMStoragePool secondaryStoragePool = null; try { - KVMStoragePool secondaryStoragePool = _storagePoolMgr.getStoragePoolByURI(cmd.getSecondaryStorageUrl()); + secondaryStoragePool = _storagePoolMgr.getStoragePoolByURI(cmd.getSecondaryStorageUrl()); String ssPmountPath = secondaryStoragePool.getLocalPath(); String snapshotDestPath = ssPmountPath + File.separator + "snapshots" + File.separator + dcId + File.separator + accountId + File.separator + volumeId; @@ -1287,6 +1307,10 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv command.execute(); } catch (CloudRuntimeException e) { return new DeleteSnapshotBackupAnswer(cmd, false, e.toString()); + } finally { + if (secondaryStoragePool != null) { + secondaryStoragePool.delete(); + } } return new DeleteSnapshotBackupAnswer(cmd, true, null); } @@ -1295,8 +1319,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv Long dcId = cmd.getDcId(); Long accountId = cmd.getAccountId(); Long volumeId = cmd.getVolumeId(); + KVMStoragePool secondaryStoragePool = null; try { - KVMStoragePool secondaryStoragePool = _storagePoolMgr.getStoragePoolByURI(cmd.getSecondaryStorageUrl()); + secondaryStoragePool = _storagePoolMgr.getStoragePoolByURI(cmd.getSecondaryStorageUrl()); String ssPmountPath = secondaryStoragePool.getLocalPath(); String snapshotDestPath = ssPmountPath + File.separator + "snapshots" + File.separator + dcId + File.separator + accountId + File.separator + volumeId; @@ -1307,6 +1332,11 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv command.execute(); } catch (CloudRuntimeException e) { return new Answer(cmd, false, e.toString()); + } finally { + if (secondaryStoragePool != null) { + secondaryStoragePool.delete(); + } + } return new Answer(cmd, true, null); } @@ -1323,8 +1353,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv 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()); + KVMPhysicalDisk disk = _storagePoolMgr.copyPhysicalDisk(snapshot, volUuid, primaryPool); + return new CreateVolumeFromSnapshotAnswer(cmd, true, "", disk.getName()); } catch (CloudRuntimeException e) { return new CreateVolumeFromSnapshotAnswer(cmd, false, e.toString(), null); } @@ -1339,24 +1369,28 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv protected CreatePrivateTemplateAnswer execute(final CreatePrivateTemplateFromSnapshotCommand cmd) { String templateFolder = cmd.getAccountId() + File.separator + cmd.getNewTemplateId(); String templateInstallFolder = "template/tmpl/" + templateFolder; - String snapshotPath = cmd.getSnapshotUuid(); String tmplName = UUID.randomUUID().toString(); String tmplFileName = tmplName + ".qcow2"; - KVMStoragePool secondaryPool; + KVMStoragePool secondaryPool = null; + KVMStoragePool snapshotPool = null; try { + String snapshotPath = cmd.getSnapshotUuid(); + int index = snapshotPath.lastIndexOf("/"); + snapshotPath = snapshotPath.substring(0, index); + snapshotPool = _storagePoolMgr.getStoragePoolByURI(cmd.getSecondaryStorageUrl() + snapshotPath); + KVMPhysicalDisk snapshot = snapshotPool.getPhysicalDisk(cmd.getSnapshotName()); - secondaryPool = _storagePoolMgr.getStoragePoolByURI(cmd.getSecondaryStorageUrl()); - + String templatePath = secondaryPool.getLocalPath() + File.separator + templateInstallFolder; _storage.mkdirs(templatePath); - + String tmplPath = templateInstallFolder + File.separator + tmplFileName; Script command = new Script(_createTmplPath, _timeout, s_logger); command.add("-t", templatePath); command.add("-n", tmplFileName); - command.add("-f", snapshotPath); + command.add("-f", snapshot.getPath()); command.execute(); Map params = new HashMap(); @@ -1379,6 +1413,13 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return new CreatePrivateTemplateAnswer(cmd, false, e.getMessage()); } catch (CloudRuntimeException e) { return new CreatePrivateTemplateAnswer(cmd, false, e.getMessage()); + } finally { + if (secondaryPool != null) { + secondaryPool.delete(); + } + if (snapshotPool != null) { + snapshotPool.delete(); + } } } @@ -1403,12 +1444,13 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv secondaryStorage = _storagePoolMgr.getStoragePoolByURI(secondaryStorageURL); - + KVMStoragePool primary = _storagePoolMgr.getStoragePool(cmd.getPrimaryStoragePoolNameLabel()); + KVMPhysicalDisk disk = primary.getPhysicalDisk(cmd.getVolumePath()); String tmpltPath = secondaryStorage.getLocalPath() + File.separator + templateInstallFolder; _storage.mkdirs(tmpltPath); Script command = new Script(_createTmplPath, _timeout, s_logger); - command.add("-f", cmd.getVolumePath()); + command.add("-f", disk.getPath()); command.add("-t", tmpltPath); command.add("-n", cmd.getUniqueName() + ".qcow2"); @@ -1451,6 +1493,10 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return new CreatePrivateTemplateAnswer(cmd, false, e.toString()); } catch (CloudRuntimeException e) { return new CreatePrivateTemplateAnswer(cmd, false, e.toString()); + } finally { + if (secondaryStorage != null) { + secondaryStorage.delete(); + } } } @@ -1464,9 +1510,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } KVMPhysicalDisk tmplVol = null; - + KVMStoragePool secondaryPool = null; try { - KVMStoragePool secondaryPool = _storagePoolMgr.getStoragePoolByURI(mountpoint); + secondaryPool = _storagePoolMgr.getStoragePoolByURI(mountpoint); /*Get template vol*/ if (tmpltname == null) { @@ -1484,6 +1530,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv if (tmplVol == null) { return new PrimaryStorageDownloadAnswer("Failed to get template from pool: " + secondaryPool.getUuid()); } + } else { + tmplVol = secondaryPool.getPhysicalDisk(tmpltname); } /*Copy volume to primary storage*/ @@ -1494,6 +1542,10 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return new PrimaryStorageDownloadAnswer(primaryVol.getName(), primaryVol.getSize()); } catch (CloudRuntimeException e) { return new PrimaryStorageDownloadAnswer(e.toString()); + } finally { + if (secondaryPool != null) { + secondaryPool.delete(); + } } } @@ -1627,7 +1679,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv private AttachVolumeAnswer execute(AttachVolumeCommand cmd) { try { Connect conn = LibvirtConnection.getConnection(); - attachOrDetachDisk(conn, cmd.getAttach(), cmd.getVmName(), cmd.getVolumePath(), cmd.getDeviceId().intValue()); + KVMStoragePool primary = _storagePoolMgr.getStoragePool(cmd.getPoolUuid()); + KVMPhysicalDisk disk = primary.getPhysicalDisk(cmd.getVolumePath()); + attachOrDetachDisk(conn, cmd.getAttach(), cmd.getVmName(), disk, cmd.getDeviceId().intValue()); } catch (LibvirtException e) { return new AttachVolumeAnswer(cmd, e.toString()); } catch (InternalErrorException e) { @@ -1885,26 +1939,54 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return new GetHostStatsAnswer(cmd, hostStats); } - private Answer execute(NetworkUsageCommand cmd) { - String vmName = cmd.getDomRName(); - try { - Connect conn = LibvirtConnection.getConnection(); - Domain dm = getDomain(conn, vmName); - LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); - String xml = dm.getXMLDesc(0); - parser.parseDomainXML(xml); - List nics = parser.getInterfaces(); - if (nics.size() != 3) { - return new Answer(cmd, false, vmName + " doesn't have public nic"); + protected String networkUsage(final String privateIpAddress, final String option, final String vif) { + Script getUsage = new Script(_networkUsagePath, s_logger); + if (option.equals("get")) { + getUsage.add("-g"); + } else if (option.equals("create")) { + getUsage.add("-c"); + } else if (option.equals("reset")) { + getUsage.add("-r"); + } else if (option.equals("addVif")) { + getUsage.add("-a", vif); + } else if (option.equals("deleteVif")) { + getUsage.add("-d", vif); + } + + getUsage.add(" -i ", privateIpAddress); + final OutputInterpreter.OneLineParser usageParser = new OutputInterpreter.OneLineParser(); + String result = getUsage.execute(usageParser); + if (result != null) { + s_logger.debug("Failed to execute networkUsage:" + result); + return null; + } + return usageParser.getLine(); + } + + protected long[] getNetworkStats(String privateIP) { + String result = networkUsage(privateIP, "get", null); + long[] stats = new long[2]; + if (result != null) { + String[] splitResult = result.split(":"); + int i = 0; + while (i < splitResult.length - 1) { + stats[0] += (new Long(splitResult[i++])).longValue(); + stats[1] += (new Long(splitResult[i++])).longValue(); } - InterfaceDef pubNic = nics.get(2); - Pair nicStats = getNicStats(pubNic.getBrName()); - /*Note: received means bytes received by all the vms, but from host kernel's pov, it's tx*/ - return new NetworkUsageAnswer(cmd, "", nicStats.first().longValue(), nicStats.second().longValue()); - } catch (LibvirtException e) { - return new Answer(cmd, false, e.toString()); } + return stats; } + + private Answer execute(NetworkUsageCommand cmd) { + if(cmd.getOption()!=null && cmd.getOption().equals("create") ){ + String result = networkUsage(cmd.getPrivateIP(), "create", null); + NetworkUsageAnswer answer = new NetworkUsageAnswer(cmd, result, 0L, 0L); + return answer; + } + long[] stats = getNetworkStats(cmd.getPrivateIP()); + NetworkUsageAnswer answer = new NetworkUsageAnswer(cmd, "", stats[0], stats[1]); + return answer; + } private Answer execute(RebootCommand cmd) { Long bytesReceived = null; @@ -1939,9 +2021,19 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } protected Answer execute(RebootRouterCommand cmd) { + Long bytesSent = 0L; + Long bytesRcvd = 0L; + if (VirtualMachineName.isValidRouterName(cmd.getVmName())) { + long[] stats = getNetworkStats(cmd.getPrivateIpAddress()); + bytesSent = stats[0]; + bytesRcvd = stats[1]; + } RebootAnswer answer = (RebootAnswer) execute((RebootCommand) cmd); + answer.setBytesSent(bytesSent); + answer.setBytesReceived(bytesRcvd); String result = _virtRouterResource.connect(cmd.getPrivateIpAddress()); if (result == null) { + networkUsage(cmd.getPrivateIpAddress(), "create", null); return answer; } else { return new Answer(cmd, false, result); @@ -2189,7 +2281,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv // Attach each data volume to the VM, if there is a deferred attached disk for (DiskDef disk : vm.getDevices().getDisks()) { if (disk.isAttachDeferred()) { - attachOrDetachDisk(conn, true, vmName, disk.getDiskPath(), disk.getDiskSeq()); + attachOrDetachDevice(conn, true, vmName, disk.toString()); } } @@ -2237,12 +2329,15 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv String volName = volPath.substring(index + 1); KVMStoragePool secondaryStorage = _storagePoolMgr.getStoragePoolByURI(volDir); physicalDisk = secondaryStorage.getPhysicalDisk(volName); - } else { + } else if (volume.getType() != Volume.Type.ISO) { pool = _storagePoolMgr.getStoragePool(volume.getPoolUuid()); physicalDisk = pool.getPhysicalDisk(volume.getPath()); } - String volPath = physicalDisk.getPath(); + String volPath = null; + if (physicalDisk != null) { + volPath = physicalDisk.getPath(); + } DiskDef.diskBus diskBusType = getGuestDiskModel(vmSpec.getOs()); DiskDef disk = new DiskDef(); @@ -2416,10 +2511,10 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return attachOrDetachDevice(conn, true, vmName, isoXml); } - protected synchronized String attachOrDetachDisk(Connect conn, boolean attach, String vmName, String sourceFile, int devId) throws LibvirtException, InternalErrorException { + protected synchronized String attachOrDetachDisk(Connect conn, boolean attach, String vmName, KVMPhysicalDisk attachingDisk, int devId) throws LibvirtException, InternalErrorException { List disks = null; Domain dm = null; - int deviceId = devId; + DiskDef diskdef = null; try { if (!attach) { dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName.getBytes())); @@ -2428,24 +2523,26 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv parser.parseDomainXML(xml); disks = parser.getDisks(); - boolean diskAttached = false; - for (DiskDef disk : disks) { String file = disk.getDiskPath(); - if (file != null && file.equalsIgnoreCase(sourceFile)) { - deviceId = disk.getDiskSeq(); - diskAttached = true; + if (file != null && file.equalsIgnoreCase(attachingDisk.getPath())) { + diskdef = disk; break; } } - if (!diskAttached) { - throw new InternalErrorException("disk: " + sourceFile + " is not attached before"); + if (diskdef == null) { + throw new InternalErrorException("disk: " + attachingDisk.getPath() + " is not attached before"); } + } else { + diskdef = new DiskDef(); + if (attachingDisk.getFormat() == PhysicalDiskFormat.QCOW2) { + diskdef.defFileBasedDisk(attachingDisk.getPath(), devId, DiskDef.diskBus.VIRTIO, DiskDef.diskFmtType.QCOW2); + } else if (attachingDisk.getFormat() == PhysicalDiskFormat.RAW) { + diskdef.defBlockBasedDisk(attachingDisk.getPath(), devId, DiskDef.diskBus.VIRTIO); + } } - - DiskDef disk = new DiskDef(); - disk.defFileBasedDisk(sourceFile, deviceId, DiskDef.diskBus.VIRTIO, DiskDef.diskFmtType.QCOW2); - String xml = disk.toString(); + + String xml = diskdef.toString(); return attachOrDetachDevice(conn, attach, vmName, xml); } finally { if (dm != null) { @@ -2454,7 +2551,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } } - private synchronized String attachOrDetachDevice(Connect conn, boolean attach, String vmName, String xml) throws LibvirtException, InternalErrorException{ + protected synchronized String attachOrDetachDevice(Connect conn, boolean attach, String vmName, String xml) throws LibvirtException, InternalErrorException{ Domain dm = null; try { dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes((vmName.getBytes()))); diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtDomainXMLParser.java b/agent/src/com/cloud/agent/resource/computing/LibvirtDomainXMLParser.java index 2e5e8e1c276..b435a8bfecd 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtDomainXMLParser.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtDomainXMLParser.java @@ -71,6 +71,8 @@ public class LibvirtDomainXMLParser { Element disk = (Element)disks.item(i); String diskFmtType = getAttrValue("driver", "type", disk); String diskFile = getAttrValue("source", "file", disk); + String diskDev = getAttrValue("source", "dev", disk); + String diskLabel = getAttrValue("target", "dev", disk); String bus = getAttrValue("target", "bus", disk); String type = disk.getAttribute("type"); @@ -87,6 +89,8 @@ public class LibvirtDomainXMLParser { } else if (device.equalsIgnoreCase("cdrom")) { def.defISODisk(diskFile); } + } else if (type.equalsIgnoreCase("block")) { + def.defBlockBasedDisk(diskDev, diskLabel, DiskDef.diskBus.valueOf(bus.toUpperCase())); } diskDefs.add(def); } diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtStorageVolumeDef.java b/agent/src/com/cloud/agent/resource/computing/LibvirtStorageVolumeDef.java index 1769a26ac4e..7fc6a0df993 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtStorageVolumeDef.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtStorageVolumeDef.java @@ -31,6 +31,18 @@ public class LibvirtStorageVolumeDef { public String toString() { return _format; } + + public static volFormat getFormat(String format) { + if (format == null) { + return null; + } + if (format.equalsIgnoreCase("raw")) { + return RAW; + } else if (format.equalsIgnoreCase("qcow2")) { + return QCOW2; + } + return null; + } } private String _volName; private Long _volSize; diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtStorageVolumeXMLParser.java b/agent/src/com/cloud/agent/resource/computing/LibvirtStorageVolumeXMLParser.java index 42dbd890549..43995090823 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtStorageVolumeXMLParser.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtStorageVolumeXMLParser.java @@ -32,7 +32,7 @@ public class LibvirtStorageVolumeXMLParser{ 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); + return new LibvirtStorageVolumeDef(VolName, capacity, LibvirtStorageVolumeDef.volFormat.getFormat(format), null, null); } catch (ParserConfigurationException e) { s_logger.debug(e.toString()); } catch (SAXException e) { diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtVMDef.java b/agent/src/com/cloud/agent/resource/computing/LibvirtVMDef.java index 9fc99428dc4..89473a22b0c 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtVMDef.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtVMDef.java @@ -345,6 +345,14 @@ public class LibvirtVMDef { _diskLabel = getDevLabel(devId, bus); _bus = bus; } + public void defBlockBasedDisk(String diskName, String diskLabel, diskBus bus) { + _diskType = diskType.BLOCK; + _deviceType = deviceType.DISK; + _diskFmtType = diskFmtType.RAW; + _sourcePath = diskName; + _diskLabel = diskLabel; + _bus = bus; + } public void setReadonly() { _readonly = true; } diff --git a/agent/src/com/cloud/agent/storage/KVMPhysicalDisk.java b/agent/src/com/cloud/agent/storage/KVMPhysicalDisk.java index 282a14feb21..a4cc44d04c8 100644 --- a/agent/src/com/cloud/agent/storage/KVMPhysicalDisk.java +++ b/agent/src/com/cloud/agent/storage/KVMPhysicalDisk.java @@ -5,8 +5,15 @@ public class KVMPhysicalDisk { private String name; private KVMStoragePool pool; public static enum PhysicalDiskFormat { - RAW, - QCOW2 + RAW("raw"), + QCOW2("qcow2"); + String format; + private PhysicalDiskFormat(String format) { + this.format = format; + } + public String toString() { + return this.format; + } } private PhysicalDiskFormat format; private long size; diff --git a/agent/src/com/cloud/agent/storage/KVMStoragePool.java b/agent/src/com/cloud/agent/storage/KVMStoragePool.java index 19d5486c8ac..7bdbb2a6a9a 100644 --- a/agent/src/com/cloud/agent/storage/KVMStoragePool.java +++ b/agent/src/com/cloud/agent/storage/KVMStoragePool.java @@ -18,4 +18,6 @@ public interface KVMStoragePool { public boolean isExternalSnapshot(); public String getLocalPath(); public StoragePoolType getType(); + public boolean delete(); + PhysicalDiskFormat getDefaultFormat(); } diff --git a/agent/src/com/cloud/agent/storage/KVMStoragePoolManager.java b/agent/src/com/cloud/agent/storage/KVMStoragePoolManager.java index 99e62d9aaf2..6e10ce8eed3 100644 --- a/agent/src/com/cloud/agent/storage/KVMStoragePoolManager.java +++ b/agent/src/com/cloud/agent/storage/KVMStoragePoolManager.java @@ -74,4 +74,6 @@ public class KVMStoragePoolManager { public KVMPhysicalDisk getPhysicalDiskFromUrl(String url) { return this._storageAdaptor.getPhysicalDiskFromURI(url); } + + } diff --git a/agent/src/com/cloud/agent/storage/LibvirtStorageAdaptor.java b/agent/src/com/cloud/agent/storage/LibvirtStorageAdaptor.java index 247d289c450..e729220be3b 100644 --- a/agent/src/com/cloud/agent/storage/LibvirtStorageAdaptor.java +++ b/agent/src/com/cloud/agent/storage/LibvirtStorageAdaptor.java @@ -23,10 +23,7 @@ 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; @@ -35,27 +32,17 @@ 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.api.ManageSnapshotCommand; 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; @@ -65,12 +52,12 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { private static final Logger s_logger = Logger.getLogger(LibvirtStorageAdaptor.class); private StorageLayer _storageLayer; private String _mountPoint = "/mnt"; - + private String _manageSnapshotPath; public LibvirtStorageAdaptor(StorageLayer storage ) { _storageLayer = storage; - + _manageSnapshotPath = Script.findScript("scripts/storage/qcow2/", "managesnapshot.sh"); } @@ -235,6 +222,33 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { } } + private StoragePool createCLVMStoragePool(Connect conn, String uuid, String host, String path) { + + String volgroupPath = "/dev/" + path; + + LibvirtStoragePoolDef spd = new LibvirtStoragePoolDef(poolType.LOGICAL, uuid, uuid, + host, volgroupPath, volgroupPath); + 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 clvm 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(); @@ -405,7 +419,9 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { disk = new KVMPhysicalDisk(vol.getPath(), vol.getName(), pool); disk.setSize(vol.getInfo().allocation); disk.setVirtualSize(vol.getInfo().capacity); - if (voldef.getFormat() == LibvirtStorageVolumeDef.volFormat.QCOW2) { + if (voldef.getFormat() == null) { + disk.setFormat(pool.getDefaultFormat()); + } else if (voldef.getFormat() == LibvirtStorageVolumeDef.volFormat.QCOW2) { disk.setFormat(KVMPhysicalDisk.PhysicalDiskFormat.QCOW2); } else if (voldef.getFormat() == LibvirtStorageVolumeDef.volFormat.RAW) { disk.setFormat(KVMPhysicalDisk.PhysicalDiskFormat.RAW); @@ -416,6 +432,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { } } + @Override public KVMStoragePool createStoragePool(String name, String host, String path, StoragePoolType type) { StoragePool sp = null; @@ -437,6 +454,8 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { sp = createNfsStoragePool(conn, name, host, path); } else if (type == StoragePoolType.SharedMountPoint || type == StoragePoolType.Filesystem) { sp = CreateSharedStoragePool(conn, name, host, path); + } else if (type == StoragePoolType.CLVM) { + sp = createCLVMStoragePool(conn, name, host, path); } } @@ -534,18 +553,15 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { 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()); + Script.runSimpleBashScript("qemu-img create -f " + template.getFormat() + " -b " + template.getPath() + " " + disk.getPath()); + } else if (format == PhysicalDiskFormat.RAW) { + Script.runSimpleBashScript("qemu-img convert -f " + template.getFormat()+ " -O raw " + 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 + public KVMPhysicalDisk createTemplateFromDisk(KVMPhysicalDisk disk, String name, PhysicalDiskFormat format, long size, KVMStoragePool destPool) { return null; } @@ -572,7 +588,9 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { 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); + + Script.runSimpleBashScript("qemu-img convert -f " + disk.getFormat() + " -O " + newDisk.getFormat() + " " + sourcePath + " " + destPath); + return newDisk; } @@ -594,7 +612,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { sourcePath = storageUri.getPath(); sourcePath = sourcePath.replace("//", "/"); sourceHost = storageUri.getHost(); - uuid = UUID.nameUUIDFromBytes(new String(sourceHost + sourcePath).getBytes()).toString(); + uuid = UUID.randomUUID().toString(); protocal = StoragePoolType.NetworkFilesystem; } @@ -610,7 +628,6 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { @Override public KVMPhysicalDisk createDiskFromSnapshot(KVMPhysicalDisk snapshot, String snapshotName, String name, KVMStoragePool destPool) { - // TODO Auto-generated method stub return null; } @@ -625,6 +642,21 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { } return true; } - + + + @Override + public boolean deleteStoragePool(KVMStoragePool pool) { + LibvirtStoragePool libvirtPool = (LibvirtStoragePool)pool; + StoragePool virtPool = libvirtPool.getPool(); + try { + virtPool.destroy(); + virtPool.undefine(); + virtPool.free(); + } catch (LibvirtException e) { + return false; + } + + return true; + } } diff --git a/agent/src/com/cloud/agent/storage/LibvirtStoragePool.java b/agent/src/com/cloud/agent/storage/LibvirtStoragePool.java index e94a1d0b828..cefd93d69aa 100644 --- a/agent/src/com/cloud/agent/storage/LibvirtStoragePool.java +++ b/agent/src/com/cloud/agent/storage/LibvirtStoragePool.java @@ -64,6 +64,7 @@ public class LibvirtStoragePool implements KVMStoragePool { return this.uri; } + @Override public PhysicalDiskFormat getDefaultFormat() { if (getStoragePoolType() == StoragePoolType.CLVM) { return PhysicalDiskFormat.RAW; @@ -128,4 +129,9 @@ public class LibvirtStoragePool implements KVMStoragePool { public StoragePool getPool() { return this._pool; } + + @Override + public boolean delete() { + return this._storageAdaptor.deleteStoragePool(this); + } } diff --git a/agent/src/com/cloud/agent/storage/StorageAdaptor.java b/agent/src/com/cloud/agent/storage/StorageAdaptor.java index e5ed91918fe..c966c6ad1b5 100644 --- a/agent/src/com/cloud/agent/storage/StorageAdaptor.java +++ b/agent/src/com/cloud/agent/storage/StorageAdaptor.java @@ -20,6 +20,7 @@ public interface StorageAdaptor { 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); + public boolean refresh(KVMStoragePool pool); + public boolean deleteStoragePool(KVMStoragePool pool); } diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties index 2da3d5fd55f..aa7d2fe4841 100644 --- a/client/WEB-INF/classes/resources/messages.properties +++ b/client/WEB-INF/classes/resources/messages.properties @@ -71,6 +71,8 @@ force.stop.instance.warning=Warning: Forcing a stop on this instance should be y label.PreSetup=PreSetup label.SR.name = SR Name-Label label.SharedMountPoint=SharedMountPoint +label.clvm=CLVM +label.volgroup=Volume Group label.VMFS.datastore=VMFS datastore label.network.device=Network Device diff --git a/client/WEB-INF/classes/resources/messages_es.properties b/client/WEB-INF/classes/resources/messages_es.properties index 8a3f217c81b..5c85b30b47e 100644 --- a/client/WEB-INF/classes/resources/messages_es.properties +++ b/client/WEB-INF/classes/resources/messages_es.properties @@ -71,6 +71,8 @@ force.stop.instance.warning=Advertencia: Obligar a una parada en este caso deber label.PreSetup=PreSetup label.SR.name = SR Nombre de etiqueta label.SharedMountPoint = SharedMountPoint +label.clvm=CLVM +label.volgroup=Volume Group label.VMFS.datastore=VMFS de datos tienda label.network.device=De dispositivos de red @@ -856,4 +858,4 @@ error.login = Su nombre de usuario / contraseña no coincide con nuestros regist error.menu.select = No se puede realizar la acción debido a que no los artículos que son seleccionados. error.mgmt.server.inaccessible = El Servidor de Gestión es inaccesible. Por favor, inténtelo de nuevo más tarde. error.session.expired = Su sesión ha caducado. -error.unresolved.internet.name = El nombre de Internet no se puede resolver. \ No newline at end of file +error.unresolved.internet.name = El nombre de Internet no se puede resolver. diff --git a/client/WEB-INF/classes/resources/messages_ja.properties b/client/WEB-INF/classes/resources/messages_ja.properties index 62df746ef54..8dca7e00644 100644 --- a/client/WEB-INF/classes/resources/messages_ja.properties +++ b/client/WEB-INF/classes/resources/messages_ja.properties @@ -71,6 +71,8 @@ force.stop.instance.warning=警告:このインスタンスの停止を強制 label.PreSetup=PreSetup label.SR.name=SR名-ラベル label.SharedMountPoint = SharedMountPoint +label.clvm=CLVM +label.volgroup=Volume Group label.VMFS.datastore=VMFSデータストア label.network.device=ネットワークデバイス diff --git a/client/WEB-INF/classes/resources/messages_zh_CN.properties b/client/WEB-INF/classes/resources/messages_zh_CN.properties index f059905ff03..8bfac32f54a 100644 --- a/client/WEB-INF/classes/resources/messages_zh_CN.properties +++ b/client/WEB-INF/classes/resources/messages_zh_CN.properties @@ -71,6 +71,8 @@ force.stop.instance.warning=警告:强制停止在这个实例应该是你最 label.PreSetup=PreSetup label.SR.name=简名称标签 label.SharedMountPoint = SharedMountPoint +label.clvm=CLVM +label.volgroup=Volume Group label.VMFS.datastore=VMFS 数据存储 label.network.device=网络设备 @@ -855,4 +857,4 @@ error.login=您的用户名/密码与我们的记录不匹配。 error.menu.select=无法执行动作,因为没有选项被选中。 error.mgmt.server.inaccessible=管理服务器无法访问。请稍后再试。 error.session.expired=您的会话已过期。 -error.unresolved.internet.name=您的网际网路名称无法得到解析。 \ No newline at end of file +error.unresolved.internet.name=您的网际网路名称无法得到解析。 diff --git a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java index ab7c5a42825..d10e25da40b 100755 --- a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java +++ b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java @@ -858,7 +858,7 @@ public class VirtualRoutingResource implements Manager { _getDomRVersionPath = findScript("getDomRVersion.sh"); if(_getDomRVersionPath == null) { - throw new ConfigurationException("Unable to find getRouterStatus.sh"); + throw new ConfigurationException("Unable to find getDomRVersion.sh"); } return true; diff --git a/scripts/storage/qcow2/createtmplt.sh b/scripts/storage/qcow2/createtmplt.sh index 3674856acac..67a3c647368 100755 --- a/scripts/storage/qcow2/createtmplt.sh +++ b/scripts/storage/qcow2/createtmplt.sh @@ -100,8 +100,11 @@ create_from_file() { local tmpltfs=$1 local tmpltimg=$2 local tmpltname=$3 - - $qemu_img convert -f qcow2 -O qcow2 $tmpltimg /$tmpltfs/$tmpltname >& /dev/null + if [ -b $tmpltimg ]; then + $qemu-img convert -f raw -O qcow2 $tmpltimg /$tmpltfs/$tmpltname + else + $qemu_img convert -f qcow2 -O qcow2 $tmpltimg /$tmpltfs/$tmpltname >& /dev/null + fi if [ "$cleanup" == "true" ] then @@ -177,7 +180,7 @@ then fi fi -if [ ! -f $tmpltimg ] +if [ ! -f $tmpltimg -a ! -b $tmpltimg ] then printf "root disk file $tmpltimg doesn't exist\n" exit 3 diff --git a/scripts/storage/qcow2/managesnapshot.sh b/scripts/storage/qcow2/managesnapshot.sh index b6f1c442778..4d777bba157 100755 --- a/scripts/storage/qcow2/managesnapshot.sh +++ b/scripts/storage/qcow2/managesnapshot.sh @@ -48,26 +48,79 @@ create_snapshot() { local snapshotname=$2 local failed=0 - if [ ! -f $disk ] - then - failed=1 - printf "No disk $disk exist\n" >&2 - return $failed - fi + if [ -b "${disk}" ] && lvm lvs "${disk}" >/dev/null 2>&1; then + local lv=$( lvm lvs --noheadings --unbuffered --separator=/ "${disk}" 2>/dev/null | sed 's|^[[:space:]]\+||' ) + local lvname=$( echo "${lv}" | awk -F/ '{ print $1 }' ) + local vgname=$( echo "${lv}" | awk -F/ '{ print $2 }' ) + local lvdmname=$( echo "${lvname}" | sed 's|-|--|g' ) + local vgdmname=$( echo "${vgname}" | sed 's|-|--|g' ) + local blockdevname="/dev/mapper/${vgdmname}-${lvdmname}" + local blockdevsnap="/dev/mapper/${vgdmname}-${snapshotname}" + local blockdevsize=$( blockdev --getsz "${blockdevname}" ) + + lvm lvcreate --name "${snapshotname}-cow" --size "$(blockdev --getsize64 ${blockdevname})b" "${vgname}" >&2 || return 1 + dmsetup suspend "${vgdmname}-${lvdmname}" >&2 + [ $? -ne 0 ] && destroy_snapshot "${disk}" "${snapshotname}" && return 1 + if dmsetup table | awk -v e=1 -v tbl="${vgdmname}-${lvdmname}-real:" '$1 == tbl { e=0 }; END { exit e }'; then + dmsetup create "${vgdmname}-${snapshotname}" --notable >&2 + [ $? -ne 0 ] && destroy_snapshot "${disk}" "${snapshotname}" && return 1 + + echo "0 ${blockdevsize} snapshot ${blockdevname}-real ${blockdevsnap}--cow p 64" | \ + dmsetup load "${vgdmname}-${snapshotname}" >&2 + [ $? -ne 0 ] && destroy_snapshot "${disk}" "${snapshotname}" && return 1 + + dmsetup resume "${vgdmname}-${snapshotname}" >&2 + [ $? -ne 0 ] && destroy_snapshot "${disk}" "${snapshotname}" && return 1 + + else + + dmsetup create "${vgdmname}-${lvdmname}-real" --notable >&2 + [ $? -ne 0 ] && destroy_snapshot "${disk}" "${snapshotname}" && return 1 + + dmsetup table "${vgdmname}-${lvdmname}" | dmsetup load "${vgdmname}-${lvdmname}-real" >&2 + [ $? -ne 0 ] && destroy_snapshot "${disk}" "${snapshotname}" && return 1 + + dmsetup resume "${vgdmname}-${lvdmname}-real" >&2 + [ $? -ne 0 ] && destroy_snapshot "${disk}" "${snapshotname}" && return 1 + + dmsetup create "${vgdmname}-${snapshotname}" --notable >&2 + [ $? -ne 0 ] && destroy_snapshot "${disk}" "${snapshotname}" && return 1 + + echo "0 ${blockdevsize} snapshot ${blockdevname}-real ${blockdevsnap}--cow p 64" | \ + dmsetup load "${vgdmname}-${snapshotname}" >&2 + [ $? -ne 0 ] && destroy_snapshot "${disk}" "${snapshotname}" && return 1 + + echo "0 ${blockdevsize} snapshot-origin ${blockdevname}-real" | \ + dmsetup load "${vgdmname}-${lvdmname}" + [ $? -ne 0 ] && destroy_snapshot "${disk}" "${snapshotname}" && return 1 + + dmsetup resume "${vgdmname}-${snapshotname}" >&2 + [ $? -ne 0 ] && destroy_snapshot "${disk}" "${snapshotname}" && return 1 + + fi + + dmsetup resume "${vgdmname}-${lvdmname}" >&2 + [ $? -ne 0 ] && destroy_snapshot "${disk}" "${snapshotname}" && return 1 + + elif [ -f "${disk}" ]; then + $qemu_img snapshot -c $snapshotname $disk - $qemu_img snapshot -c $snapshotname $disk - if [ $? -gt 0 ] - then - failed=2 - printf "***Failed to create snapshot $snapshotname for path $disk\n" >&2 - $qemu_img snapshot -d $snapshotname $disk + if [ $? -gt 0 ] + then + failed=2 + printf "***Failed to create snapshot $snapshotname for path $disk\n" >&2 + $qemu_img snapshot -d $snapshotname $disk - if [ $? -gt 0 ] - then - printf "***Failed to delete snapshot $snapshotname for path $disk\n" >&2 - fi - fi + if [ $? -gt 0 ] + then + printf "***Failed to delete snapshot $snapshotname for path $disk\n" >&2 + fi + fi + else + failed=3 + printf "***Failed to create snapshot $snapshotname, undefined type $disk\n" >&2 + fi return $failed } @@ -76,31 +129,34 @@ destroy_snapshot() { local disk=$1 local snapshotname=$2 local failed=0 + if [ -b ${disk} ]; then + local lvname=$( echo "${disk}" | awk -F/ '{ print $(NF) }' ) # ' + local vgname=$( echo "${disk}" | awk -F/ '{ print $(NF-1) }' ) # ' + local lvdmname=$( echo "${lvname}" | sed 's|-|--|g' ) + local vgdmname=$( echo "${vgname}" | sed 's|-|--|g' ) - if [ -d $disk ] - then - if [ -f $disk/$snapshotname ] - then - rm -rf $disk/$snapshotname >& /dev/null + if [ $( dmsetup --columns --noheadings --separator=: info "${vgdmname}-${lvdmname}-real" | awk -F: '{ print $5 }' ) -le 2 ]; then + dmsetup suspend "${vgdmname}-${lvdmname}" >&2 + dmsetup table "${vgdmname}-${lvdmname}-real" | dmsetup load "${vgdmname}-${lvdmname}" >&2 + dmsetup resume "${vgdmname}-${lvdmname}" >&2 + dmsetup remove "${vgdmname}-${snapshotname}" >&2 + dmsetup remove "${vgdmname}-${lvdmname}-real" >&2 + else + dmsetup remove "${vgdmname}-${snapshotname}" >&2 fi + lvm lvremove -f "${vgname}/${snapshotname}-cow" >&2 - return $failed + elif [ -f $disk ]; then + $qemu_img snapshot -d $snapshotname $disk + if [ $? -gt 0 ] + then + failed=2 + printf "Failed to delete snapshot $snapshotname for path $disk\n" >&2 + fi + else + failed=3 + printf "***Failed to delete snapshot $snapshotname, undefined type $disk\n" >&2 fi - - if [ ! -f $disk ] - then - failed=1 - printf "No disk $disk exist\n" >&2 - return $failed - fi - - $qemu_img snapshot -d $snapshotname $disk - if [ $? -gt 0 ] - then - failed=2 - printf "Failed to delete snapshot $snapshotname for path $disk\n" >&2 - fi - return $failed } @@ -135,19 +191,35 @@ backup_snapshot() { fi fi - # Does the snapshot exist? - $qemu_img snapshot -l $disk|grep -w "$snapshotname" >& /dev/null - if [ $? -gt 0 ] - then - printf "there is no $snapshotname on disk $disk" >&2 - return 1 - fi + if [ -b ${disk} ] && lvm lvs "${disk}" >/dev/null 2>&1; then + local lv=$( lvm lvs --noheadings --unbuffered --separator=/ "${disk}" 2>/dev/null | sed 's|^[[:space:]]\+||' ) + local vgname=$( echo "${lv}" | awk -F/ '{ print $2 }' ) + local vgdmname=$( echo "${vgname}" | sed 's|-|--|g' ) - $qemu_img convert -f qcow2 -O qcow2 -s $snapshotname $disk $destPath/$destName >& /dev/null - if [ $? -gt 0 ] - then - printf "Failed to backup $snapshotname for disk $disk to $destPath" >&2 - return 2 + if [ -x "$( dirname $0 )/raw2qcow2.sh" ]; then + "$( dirname $0 )/raw2qcow2.sh" "/dev/mapper/${vgdmname}-${snapshotname}" "${destPath}/${destName}" + else + $qemu_img convert -f raw -O qcow2 "/dev/mapper/${vgdmname}-${snapshotname}" "${destPath}/${destName}" + fi + return 0 + elif [ -f ${disk} ]; then + # Does the snapshot exist? + $qemu_img snapshot -l $disk|grep -w "$snapshotname" >& /dev/null + if [ $? -gt 0 ] + then + printf "there is no $snapshotname on disk $disk" >&2 + return 1 + fi + + $qemu_img convert -f qcow2 -O qcow2 -s $snapshotname $disk $destPath/$destName >& /dev/null + if [ $? -gt 0 ] + then + printf "Failed to backup $snapshotname for disk $disk to $destPath" >&2 + return 2 + fi + else + printf "***Failed to backup snapshot $snapshotname, undefined type $disk\n" >&2 + return 3 fi return 0 } @@ -192,6 +264,7 @@ do esac done +[ -b "$pathval" ] && snapshot=`echo "${snapshot}" | md5sum -t | awk '{ print $1 }'` if [ "$cflag" == "1" ] then diff --git a/scripts/vm/hypervisor/kvm/rundomrpre.sh b/scripts/vm/hypervisor/kvm/rundomrpre.sh index 8af15c43e12..6e7dbe5ce51 100755 --- a/scripts/vm/hypervisor/kvm/rundomrpre.sh +++ b/scripts/vm/hypervisor/kvm/rundomrpre.sh @@ -37,7 +37,7 @@ mount_raw_disk() { local vmname=$1 local datadisk=$2 local path=$(mntpath $vmname) - if [ ! -f $datadisk ] + if [ ! -f $datadisk -a ! -b $datadisk ] then printf "$datadisk doesn't exist" >&2 return 2 @@ -46,9 +46,15 @@ mount_raw_disk() { retry=10 while [ $retry -gt 0 ] do - mount $datadisk $path -o loop &>/dev/null + if [ -b $datadisk ]; then + mount $datadisk $path &>/dev/null + ret=$? + else + mount $datadisk $path -o loop &>/dev/null + ret=$? + fi sleep 10 - if [ $? -gt 0 ] + if [ $ret -gt 0 ] then sleep 5 else diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index f2481e0e7ba..2da24e40ff0 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -1156,6 +1156,11 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag if (uriPath == null) { throw new InvalidParameterValueException("host or path is null, should be sharedmountpoint://localhost/path"); } + } else if (uri.getScheme().equalsIgnoreCase("clvm")) { + String uriPath = uri.getPath(); + if (uriPath == null) { + throw new InvalidParameterValueException("host or path is null, should be clvm://localhost/path"); + } } } catch (URISyntaxException e) { throw new InvalidParameterValueException(cmd.getUrl() + " is not a valid uri"); @@ -1197,6 +1202,8 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag 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("clvm")) { + pool = new StoragePoolVO(StoragePoolType.CLVM, storageHost, 0, hostPath.replaceFirst("/", "")); } else if (scheme.equalsIgnoreCase("PreSetup")) { pool = new StoragePoolVO(StoragePoolType.PreSetup, storageHost, 0, hostPath); } else if (scheme.equalsIgnoreCase("iscsi")) { @@ -1256,7 +1263,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag long poolId = _storagePoolDao.getNextInSequence(Long.class, "id"); String uuid = null; - if (scheme.equalsIgnoreCase("sharedmountpoint")) { + if (scheme.equalsIgnoreCase("sharedmountpoint") || scheme.equalsIgnoreCase("clvm")) { uuid = UUID.randomUUID().toString(); } else if (scheme.equalsIgnoreCase("PreSetup")) { uuid = hostPath.replace("/", ""); @@ -1480,7 +1487,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag s_logger.debug("creating pool " + pool.getName() + " on 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.SharedMountPoint - && pool.getPoolType() != StoragePoolType.PreSetup && pool.getPoolType() != StoragePoolType.OCFS2) { + && pool.getPoolType() != StoragePoolType.PreSetup && pool.getPoolType() != StoragePoolType.OCFS2 && pool.getPoolType() != StoragePoolType.CLVM) { s_logger.warn(" Doesn't support storage pool type " + pool.getPoolType()); return false; } diff --git a/ui/index.jsp b/ui/index.jsp index 3c478800061..a22fdc4d589 100644 --- a/ui/index.jsp +++ b/ui/index.jsp @@ -95,6 +95,7 @@ 'label.SharedMountPoint': '', 'label.PreSetup': '', 'label.iscsi': '', + 'label.clvm': '', 'label.VMFS.datastore': '', 'label.theme.default': '', 'label.none': '', diff --git a/ui/jsp/cluster.jsp b/ui/jsp/cluster.jsp index e13ad9a3d9b..22ec67d67f2 100644 --- a/ui/jsp/cluster.jsp +++ b/ui/jsp/cluster.jsp @@ -377,6 +377,13 @@ dictionary = { +
  • diff --git a/ui/jsp/pod.jsp b/ui/jsp/pod.jsp index b8c34429e75..91496b59101 100644 --- a/ui/jsp/pod.jsp +++ b/ui/jsp/pod.jsp @@ -688,6 +688,13 @@ dictionary = {
  • +
  • diff --git a/ui/jsp/primarystorage.jsp b/ui/jsp/primarystorage.jsp index 4e4c0bbe559..98f1c9eecf2 100644 --- a/ui/jsp/primarystorage.jsp +++ b/ui/jsp/primarystorage.jsp @@ -270,6 +270,13 @@ dictionary = {
  • +
  • diff --git a/ui/jsp/resource.jsp b/ui/jsp/resource.jsp index c106a25b00d..9bc5a8c8e86 100644 --- a/ui/jsp/resource.jsp +++ b/ui/jsp/resource.jsp @@ -1096,6 +1096,13 @@
  • +
  • diff --git a/ui/jsp/zone.jsp b/ui/jsp/zone.jsp index 0594176ea68..4238e3bba7a 100644 --- a/ui/jsp/zone.jsp +++ b/ui/jsp/zone.jsp @@ -675,6 +675,13 @@ dictionary = {
  • +
  • diff --git a/ui/scripts/cloud.core.pod.js b/ui/scripts/cloud.core.pod.js index 027d413c6fc..6dfcc65e82d 100644 --- a/ui/scripts/cloud.core.pod.js +++ b/ui/scripts/cloud.core.pod.js @@ -814,6 +814,8 @@ function bindAddPrimaryStorageButton($leftmenuItem1) { isValid &= validateString("Server", $thisDialog.find("#add_pool_nfs_server"), $thisDialog.find("#add_pool_nfs_server_errormsg")); isValid &= validateString("Target IQN", $thisDialog.find("#add_pool_iqn"), $thisDialog.find("#add_pool_iqn_errormsg")); isValid &= validateString("LUN #", $thisDialog.find("#add_pool_lun"), $thisDialog.find("#add_pool_lun_errormsg")); + } else if(protocol == "clvm") { + isValid &= validateString("Volume Group", $thisDialog.find("#add_pool_clvm_vg"), $thisDialog.find("#add_pool_clvm_vg_errormsg")); } else if(protocol == "vmfs") { isValid &= validateString("vCenter Datacenter", $thisDialog.find("#add_pool_vmfs_dc"), $thisDialog.find("#add_pool_vmfs_dc_errormsg")); isValid &= validateString("vCenter Datastore", $thisDialog.find("#add_pool_vmfs_ds"), $thisDialog.find("#add_pool_vmfs_ds_errormsg")); @@ -861,6 +863,10 @@ function bindAddPrimaryStorageButton($leftmenuItem1) { path = "/" + path; url = SharedMountPointURL(server, path); } + else if (protocol == "clvm") { + var vg = trim($thisDialog.find("#add_pool_clvm_vg").val()); + url = clvmURL(vg); + } else if (protocol == "vmfs") { var path = trim($thisDialog.find("#add_pool_vmfs_dc").val()); if(path.substring(0,1)!="/") @@ -1129,6 +1135,15 @@ function SharedMountPointURL(server, path) { return url; } +function clvmURL(vgname) { + var url; + if(vgname.indexOf("://")==-1) + url = "clvm://localhost/" + vgname; + else + url = vgname; + return url; +} + function vmfsURL(server, path) { var url; if(server.indexOf("://")==-1) diff --git a/ui/scripts/cloud.core.resource.js b/ui/scripts/cloud.core.resource.js index af14e15840c..75fd1497726 100644 --- a/ui/scripts/cloud.core.resource.js +++ b/ui/scripts/cloud.core.resource.js @@ -1824,6 +1824,8 @@ function initAddPrimaryStorageShortcut($midmenuAddLink2, currentPageInRightPanel isValid &= validateString("Server", $thisDialog.find("#add_pool_nfs_server"), $thisDialog.find("#add_pool_nfs_server_errormsg")); isValid &= validateString("Target IQN", $thisDialog.find("#add_pool_iqn"), $thisDialog.find("#add_pool_iqn_errormsg")); isValid &= validateString("LUN #", $thisDialog.find("#add_pool_lun"), $thisDialog.find("#add_pool_lun_errormsg")); + } else if(protocol == "clvm") { + isValid &= validateString("Volume Group", $thisDialog.find("#add_pool_clvm_vg"), $thisDialog.find("#add_pool_clvm_vg_errormsg")); } else if(protocol == "vmfs") { isValid &= validateString("vCenter Datacenter", $thisDialog.find("#add_pool_vmfs_dc"), $thisDialog.find("#add_pool_vmfs_dc_errormsg")); isValid &= validateString("vCenter Datastore", $thisDialog.find("#add_pool_vmfs_ds"), $thisDialog.find("#add_pool_vmfs_ds_errormsg")); @@ -1880,6 +1882,10 @@ function initAddPrimaryStorageShortcut($midmenuAddLink2, currentPageInRightPanel path = "/" + path; url = SharedMountPointURL(server, path); } + else if (protocol == "clvm") { + var vg = trim($thisDialog.find("#add_pool_clvm_vg").val()); + url = clvmURL(vg); + } else if(protocol == "vmfs") { var path = trim($thisDialog.find("#add_pool_vmfs_dc").val()); if(path.substring(0,1)!="/") @@ -1951,6 +1957,7 @@ function bindEventHandlerToDialogAddPool($dialogAddPool) { $protocolSelector.empty(); $protocolSelector.append(''); $protocolSelector.append(''); + $protocolSelector.append(''); } else if(clusterObj.hypervisortype == "XenServer") { $protocolSelector.empty(); @@ -1980,6 +1987,7 @@ function bindEventHandlerToDialogAddPool($dialogAddPool) { $("#add_pool_server_container", $dialogAddPool).show(); $('li[input_group="nfs"]', $dialogAddPool).show(); $('li[input_group="iscsi"]', $dialogAddPool).hide(); + $('li[input_group="clvm"]', $dialogAddPool).hide(); $('li[input_group="vmfs"]', $dialogAddPool).hide(); $dialogAddPool.find("#add_pool_path_container").find("label").text(g_dictionary["label.path"]+":"); @@ -1999,6 +2007,7 @@ function bindEventHandlerToDialogAddPool($dialogAddPool) { $("#add_pool_server_container", $dialogAddPool).show(); $('li[input_group="nfs"]', $dialogAddPool).show(); $('li[input_group="iscsi"]', $dialogAddPool).hide(); + $('li[input_group="clvm"]', $dialogAddPool).hide(); $('li[input_group="vmfs"]', $dialogAddPool).hide(); $dialogAddPool.find("#add_pool_path_container").find("label").text(g_dictionary["label.SR.name"]+":"); @@ -2009,15 +2018,27 @@ function bindEventHandlerToDialogAddPool($dialogAddPool) { $("#add_pool_server_container", $dialogAddPool).show(); $('li[input_group="nfs"]', $dialogAddPool).hide(); $('li[input_group="iscsi"]', $dialogAddPool).show(); + $('li[input_group="clvm"]', $dialogAddPool).hide(); $('li[input_group="vmfs"]', $dialogAddPool).hide(); $dialogAddPool.find("#add_pool_nfs_server").val(""); $dialogAddPool.find("#add_pool_server_container").show(); } + else if($(this).val() == "clvm") { + $("#add_pool_server_container", $dialogAddPool).hide(); + $('li[input_group="nfs"]', $dialogAddPool).hide(); + $('li[input_group="iscsi"]', $dialogAddPool).hide(); + $('li[input_group="clvm"]', $dialogAddPool).show(); + $('li[input_group="vmfs"]', $dialogAddPool).hide(); + + $dialogAddPool.find("#add_pool_nfs_server").val("localhost"); + $dialogAddPool.find("#add_pool_server_container").hide() + } else if($(this).val() == "vmfs") { $("#add_pool_server_container", $dialogAddPool).hide(); $('li[input_group="nfs"]', $dialogAddPool).hide(); $('li[input_group="iscsi"]', $dialogAddPool).hide(); + $('li[input_group="clvm"]', $dialogAddPool).hide(); $('li[input_group="vmfs"]', $dialogAddPool).show(); $dialogAddPool.find("#add_pool_nfs_server").val(""); @@ -2027,6 +2048,7 @@ function bindEventHandlerToDialogAddPool($dialogAddPool) { $("#add_pool_server_container", $dialogAddPool).show(); $('li[input_group="nfs"]', $dialogAddPool).show(); $('li[input_group="iscsi"]', $dialogAddPool).hide(); + $('li[input_group="clvm"]', $dialogAddPool).hide(); $('li[input_group="vmfs"]', $dialogAddPool).hide(); $dialogAddPool.find("#add_pool_nfs_server").val("localhost"); @@ -2036,6 +2058,7 @@ function bindEventHandlerToDialogAddPool($dialogAddPool) { //$("#add_pool_server_container", $dialogAddPool).hide(); //$('li[input_group="nfs"]', $dialogAddPool).hide(); $('li[input_group="iscsi"]', $dialogAddPool).hide(); + $('li[input_group="clvm"]', $dialogAddPool).hide(); $('li[input_group="vmfs"]', $dialogAddPool).hide(); $dialogAddPool.find("#add_pool_nfs_server").val(""); diff --git a/ui/scripts/cloud.core.zone.js b/ui/scripts/cloud.core.zone.js index 4f323f156a0..30a573c165a 100644 --- a/ui/scripts/cloud.core.zone.js +++ b/ui/scripts/cloud.core.zone.js @@ -991,6 +991,8 @@ function bindAddPrimaryStorageButtonOnZonePage($button, zoneId, zoneName) { isValid &= validateString("Server", $thisDialog.find("#add_pool_nfs_server"), $thisDialog.find("#add_pool_nfs_server_errormsg")); isValid &= validateString("Target IQN", $thisDialog.find("#add_pool_iqn"), $thisDialog.find("#add_pool_iqn_errormsg")); isValid &= validateString("LUN #", $thisDialog.find("#add_pool_lun"), $thisDialog.find("#add_pool_lun_errormsg")); + } else if(protocol == "clvm") { + isValid &= validateString("Volume Group", $thisDialog.find("#add_pool_clvm_vg"), $thisDialog.find("#add_pool_clvm_vg_errormsg")); } else if(protocol == "vmfs") { isValid &= validateString("vCenter Datacenter", $thisDialog.find("#add_pool_vmfs_dc"), $thisDialog.find("#add_pool_vmfs_dc_errormsg")); isValid &= validateString("vCenter Datastore", $thisDialog.find("#add_pool_vmfs_ds"), $thisDialog.find("#add_pool_vmfs_ds_errormsg")); @@ -1046,6 +1048,10 @@ function bindAddPrimaryStorageButtonOnZonePage($button, zoneId, zoneName) { path = "/" + path; url = SharedMountPointURL(server, path); } + else if (protocol == "clvm") { + var vg = trim($thisDialog.find("#add_pool_clvm_vg").val()); + url = clvmURL(vg); + } else if (protocol == "vmfs") { var path = trim($thisDialog.find("#add_pool_vmfs_dc").val()); if(path.substring(0,1)!="/")