Return-Path: X-Original-To: apmail-incubator-cloudstack-commits-archive@minotaur.apache.org Delivered-To: apmail-incubator-cloudstack-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id E48F196BD for ; Thu, 26 Jul 2012 20:25:59 +0000 (UTC) Received: (qmail 43285 invoked by uid 500); 26 Jul 2012 20:25:59 -0000 Delivered-To: apmail-incubator-cloudstack-commits-archive@incubator.apache.org Received: (qmail 43253 invoked by uid 500); 26 Jul 2012 20:25:59 -0000 Mailing-List: contact cloudstack-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: cloudstack-dev@incubator.apache.org Delivered-To: mailing list cloudstack-commits@incubator.apache.org Received: (qmail 43244 invoked by uid 99); 26 Jul 2012 20:25:59 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 26 Jul 2012 20:25:59 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 428971908C; Thu, 26 Jul 2012 20:25:59 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: widodh@apache.org To: cloudstack-commits@incubator.apache.org X-Mailer: ASF-Git Admin Mailer Subject: git commit: Add RBD support for primary storage Message-Id: <20120726202559.428971908C@tyr.zones.apache.org> Date: Thu, 26 Jul 2012 20:25:59 +0000 (UTC) Updated Branches: refs/heads/master 764678f55 -> 406fd95d8 Add RBD support for primary storage This patch adds RBD (RADOS Block Device) support for primary storage in combination with KVM. To get this patch working you need: - libvirt-java 0.4.8 - libvirt with RBD storage pool support (>0.9.13) - Qemu with RBD support (>0.14) The primary storage does not support all the functions of CloudStack yet, for example snapshotting is disabled due to the fact that backupping up a RBD snapshot is not possible in the way CloudStack wants to do it. Creating templates from RBD volumes goes well, creating a VM from a template however is still a hit-and-miss. NFS primary storage is also still required, you are not able to run your System VM's from RBD, they will need to run on NFS. Other then these points you can run instances with RBD backed disks. Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/406fd95d Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/406fd95d Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/406fd95d Branch: refs/heads/master Commit: 406fd95d87bfcdbb282d65589ab1fb6e9fd0018a Parents: 764678f Author: Wido den Hollander Authored: Fri Jun 29 17:32:19 2012 +0200 Committer: Wido den Hollander Committed: Thu Jul 26 22:22:26 2012 +0200 ---------------------------------------------------------------------- .../computing/LibvirtComputingResource.java | 80 ++++- .../agent/resource/computing/LibvirtSecretDef.java | 106 ++++++ .../resource/computing/LibvirtStoragePoolDef.java | 80 +++++- .../computing/LibvirtStoragePoolXMLParser.java | 35 ++- .../agent/resource/computing/LibvirtVMDef.java | 66 ++++- .../com/cloud/agent/storage/KVMPhysicalDisk.java | 16 + .../com/cloud/agent/storage/KVMStoragePool.java | 10 + .../cloud/agent/storage/KVMStoragePoolManager.java | 21 +- .../cloud/agent/storage/LibvirtStorageAdaptor.java | 254 +++++++++++++-- .../cloud/agent/storage/LibvirtStoragePool.java | 50 +++ .../com/cloud/agent/storage/StorageAdaptor.java | 4 +- api/src/com/cloud/agent/api/to/StorageFilerTO.java | 6 + api/src/com/cloud/storage/Storage.java | 1 + api/src/com/cloud/storage/StoragePool.java | 5 + core/src/com/cloud/storage/StoragePoolVO.java | 22 ++ .../src/com/cloud/storage/StorageManagerImpl.java | 12 +- .../allocator/FirstFitStoragePoolAllocator.java | 13 + .../storage/snapshot/SnapshotManagerImpl.java | 8 + setup/db/create-schema.sql | 1 + ui/index.jsp | 1 + ui/scripts/sharedFunctions.js | 25 ++ ui/scripts/system.js | 52 +++ 22 files changed, 796 insertions(+), 72 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/406fd95d/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java ---------------------------------------------------------------------- diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java index 112ab61..347ff87 100755 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java @@ -30,12 +30,15 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; +import java.text.DateFormat; import java.text.MessageFormat; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -154,6 +157,7 @@ import com.cloud.agent.resource.computing.KVMHABase.NfsStoragePool; import com.cloud.agent.resource.computing.LibvirtVMDef.ConsoleDef; import com.cloud.agent.resource.computing.LibvirtVMDef.DevicesDef; import com.cloud.agent.resource.computing.LibvirtVMDef.DiskDef; +import com.cloud.agent.resource.computing.LibvirtVMDef.DiskDef.diskProtocol; import com.cloud.agent.resource.computing.LibvirtVMDef.FeaturesDef; import com.cloud.agent.resource.computing.LibvirtVMDef.GraphicDef; import com.cloud.agent.resource.computing.LibvirtVMDef.GuestDef; @@ -1298,6 +1302,13 @@ public class LibvirtComputingResource extends ServerResourceBase implements KVMStoragePool primaryPool = _storagePoolMgr.getStoragePool(cmd .getPool().getUuid()); + + if (primaryPool.getType() == StoragePoolType.RBD) { + s_logger.debug("Snapshots are not supported on RBD volumes"); + return new ManageSnapshotAnswer(cmd, false, + "Snapshots are not supported on RBD volumes"); + } + KVMPhysicalDisk disk = primaryPool.getPhysicalDisk(cmd .getVolumePath()); if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING @@ -1644,16 +1655,43 @@ public class LibvirtComputingResource extends ServerResourceBase implements + templateInstallFolder; _storage.mkdirs(tmpltPath); - Script command = new Script(_createTmplPath, _cmdsTimeout, s_logger); - command.add("-f", disk.getPath()); - command.add("-t", tmpltPath); - command.add("-n", cmd.getUniqueName() + ".qcow2"); + if (primary.getType() != StoragePoolType.RBD) { + Script command = new Script(_createTmplPath, _cmdsTimeout, s_logger); + command.add("-f", disk.getPath()); + command.add("-t", tmpltPath); + command.add("-n", cmd.getUniqueName() + ".qcow2"); - String result = command.execute(); + String result = command.execute(); - if (result != null) { - s_logger.debug("failed to create template: " + result); - return new CreatePrivateTemplateAnswer(cmd, false, result); + if (result != null) { + s_logger.debug("failed to create template: " + result); + return new CreatePrivateTemplateAnswer(cmd, false, result); + } + } else { + s_logger.debug("Converting RBD disk " + disk.getPath() + " into template " + cmd.getUniqueName()); + Script.runSimpleBashScript("qemu-img convert" + + " -f raw -O qcow2 " + + KVMPhysicalDisk.RBDStringBuilder(primary.getSourceHost(), + primary.getSourcePort(), + primary.getAuthUserName(), + primary.getAuthSecret(), + disk.getPath()) + + " " + tmpltPath + "/" + cmd.getUniqueName() + ".qcow2"); + File templateProp = new File(tmpltPath + "/template.properties"); + if (!templateProp.exists()) { + templateProp.createNewFile(); + } + + String templateContent = "filename=" + cmd.getUniqueName() + ".qcow2" + System.getProperty("line.separator"); + + DateFormat dateFormat = new SimpleDateFormat("MM_dd_yyyy"); + Date date = new Date(); + templateContent += "snapshot.name=" + dateFormat.format(date) + System.getProperty("line.separator"); + + FileOutputStream templFo = new FileOutputStream(templateProp); + templFo.write(templateContent.getBytes()); + templFo.flush(); + templFo.close(); } Map params = new HashMap(); @@ -1756,8 +1794,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements protected Answer execute(ModifyStoragePoolCommand cmd) { KVMStoragePool storagepool = _storagePoolMgr.createStoragePool(cmd - .getPool().getUuid(), cmd.getPool().getHost(), cmd.getPool() - .getPath(), cmd.getPool().getType()); + .getPool().getUuid(), cmd.getPool().getHost(), cmd.getPool().getPort(), + cmd.getPool().getPath(), cmd.getPool().getUserInfo(), cmd.getPool().getType()); if (storagepool == null) { return new Answer(cmd, false, " Failed to create storage pool"); } @@ -2624,10 +2662,19 @@ public class LibvirtComputingResource extends ServerResourceBase implements } else { int devId = (int) volume.getDeviceId(); - if (volume.getType() == Volume.Type.DATADISK) { - disk.defFileBasedDisk(physicalDisk.getPath(), devId, - DiskDef.diskBus.VIRTIO, - DiskDef.diskFmtType.QCOW2); + if (pool.getType() == StoragePoolType.RBD) { + /* + For RBD pools we use the secret mechanism in libvirt. + We store the secret under the UUID of the pool, that's why + we pass the pool's UUID as the authSecret + */ + disk.defNetworkBasedDisk(physicalDisk.getPath().replace("rbd:", ""), pool.getSourceHost(), pool.getSourcePort(), + pool.getAuthUserName(), pool.getUuid(), + devId, diskBusType, diskProtocol.RBD); + } else if (volume.getType() == Volume.Type.DATADISK) { + disk.defFileBasedDisk(physicalDisk.getPath(), devId, + DiskDef.diskBus.VIRTIO, + DiskDef.diskFmtType.QCOW2); } else { disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusType, DiskDef.diskFmtType.QCOW2); @@ -2982,8 +3029,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements try { KVMStoragePool localStoragePool = _storagePoolMgr - .createStoragePool(_localStorageUUID, "localhost", - _localStoragePath, StoragePoolType.Filesystem); + .createStoragePool(_localStorageUUID, "localhost", -1, + _localStoragePath, "", StoragePoolType.Filesystem); com.cloud.agent.api.StoragePoolInfo pi = new com.cloud.agent.api.StoragePoolInfo( localStoragePool.getUuid(), cmd.getPrivateIpAddress(), _localStoragePath, _localStoragePath, @@ -4083,5 +4130,4 @@ public class LibvirtComputingResource extends ServerResourceBase implements return new Answer(cmd, success, ""); } - } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/406fd95d/agent/src/com/cloud/agent/resource/computing/LibvirtSecretDef.java ---------------------------------------------------------------------- diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtSecretDef.java b/agent/src/com/cloud/agent/resource/computing/LibvirtSecretDef.java new file mode 100644 index 0000000..f7e10c3 --- /dev/null +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtSecretDef.java @@ -0,0 +1,106 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.agent.resource.computing; + +public class LibvirtSecretDef { + + public enum usage { + VOLUME("volume"), CEPH("ceph"); + String _usage; + + usage(String usage) { + _usage = usage; + } + + @Override + public String toString() { + return _usage; + } + } + + private usage _usage; + private boolean _ephemeral; + private boolean _private; + private String _uuid; + private String _description; + private String _cephName; + private String _volumeVolume; + + public LibvirtSecretDef (usage usage, String uuid) { + _usage = usage; + _uuid = uuid; + } + + public LibvirtSecretDef (usage usage, String uuid, String description) { + _usage = usage; + _uuid = uuid; + _description = description; + } + + public boolean getEphemeral() { + return _ephemeral; + } + + public boolean getPrivate() { + return _private; + } + + public String getUuid() { + return _uuid; + } + + public String getDescription() { + return _description; + } + + public String getVolumeVolume() { + return _volumeVolume; + } + + public String getCephName() { + return _cephName; + } + + public void setVolumeVolume(String volume) { + _volumeVolume = volume; + } + + public void setCephName(String name) { + _cephName = name; + } + + @Override + public String toString() { + StringBuilder secretBuilder = new StringBuilder(); + secretBuilder.append("\n"); + secretBuilder.append("" + _uuid + "\n"); + if (_description != null) { + secretBuilder.append("" + _description + "\n"); + } + secretBuilder.append("\n"); + if (_usage == _usage.VOLUME) { + secretBuilder.append("" + _volumeVolume + "\n"); + } + if (_usage == _usage.CEPH) { + secretBuilder.append("" + _cephName + "\n"); + } + secretBuilder.append("\n"); + secretBuilder.append("\n"); + return secretBuilder.toString(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/406fd95d/agent/src/com/cloud/agent/resource/computing/LibvirtStoragePoolDef.java ---------------------------------------------------------------------- diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtStoragePoolDef.java b/agent/src/com/cloud/agent/resource/computing/LibvirtStoragePoolDef.java index 582cd2e..9c28528 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtStoragePoolDef.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtStoragePoolDef.java @@ -18,7 +18,7 @@ package com.cloud.agent.resource.computing; public class LibvirtStoragePoolDef { public enum poolType { - ISCSI("iscsi"), NETFS("netfs"), LOGICAL("logical"), DIR("dir"); + ISCSI("iscsi"), NETFS("netfs"), LOGICAL("logical"), DIR("dir"), RBD("rbd"); String _poolType; poolType(String poolType) { @@ -31,12 +31,41 @@ public class LibvirtStoragePoolDef { } } + public enum authType { + CHAP("chap"), CEPH("ceph"); + String _authType; + + authType(String authType) { + _authType = authType; + } + + @Override + public String toString() { + return _authType; + } + } + private poolType _poolType; private String _poolName; private String _uuid; private String _sourceHost; + private int _sourcePort; private String _sourceDir; private String _targetPath; + private String _authUsername; + private authType _authType; + private String _secretUuid; + + public LibvirtStoragePoolDef(poolType type, String poolName, String uuid, + String host, int port, String dir, String targetPath) { + _poolType = type; + _poolName = poolName; + _uuid = uuid; + _sourceHost = host; + _sourcePort = port; + _sourceDir = dir; + _targetPath = targetPath; + } public LibvirtStoragePoolDef(poolType type, String poolName, String uuid, String host, String dir, String targetPath) { @@ -48,6 +77,20 @@ public class LibvirtStoragePoolDef { _targetPath = targetPath; } + public LibvirtStoragePoolDef(poolType type, String poolName, String uuid, + String sourceHost, int sourcePort, String dir, String authUsername, + authType authType, String secretUuid) { + _poolType = type; + _poolName = poolName; + _uuid = uuid; + _sourceHost = sourceHost; + _sourcePort = sourcePort; + _sourceDir = dir; + _authUsername = authUsername; + _authType = authType; + _secretUuid = secretUuid; + } + public String getPoolName() { return _poolName; } @@ -60,6 +103,10 @@ public class LibvirtStoragePoolDef { return _sourceHost; } + public int getSourcePort() { + return _sourcePort; + } + public String getSourceDir() { return _sourceDir; } @@ -68,6 +115,18 @@ public class LibvirtStoragePoolDef { return _targetPath; } + public String getAuthUserName() { + return _authUsername; + } + + public String getSecretUUID() { + return _secretUuid; + } + + public authType getAuthType() { + return _authType; + } + @Override public String toString() { StringBuilder storagePoolBuilder = new StringBuilder(); @@ -81,9 +140,22 @@ public class LibvirtStoragePoolDef { storagePoolBuilder.append("\n"); storagePoolBuilder.append("\n"); } - storagePoolBuilder.append("\n"); - storagePoolBuilder.append("" + _targetPath + "\n"); - storagePoolBuilder.append("\n"); + if (_poolType == poolType.RBD) { + storagePoolBuilder.append("\n"); + storagePoolBuilder.append("\n"); + storagePoolBuilder.append("" + _sourceDir + "\n"); + if (_authUsername != null) { + storagePoolBuilder.append("\n"); + storagePoolBuilder.append("\n"); + storagePoolBuilder.append("\n"); + } + storagePoolBuilder.append("\n"); + } + if (_poolType != poolType.RBD) { + storagePoolBuilder.append("\n"); + storagePoolBuilder.append("" + _targetPath + "\n"); + storagePoolBuilder.append("\n"); + } storagePoolBuilder.append("\n"); return storagePoolBuilder.toString(); } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/406fd95d/agent/src/com/cloud/agent/resource/computing/LibvirtStoragePoolXMLParser.java ---------------------------------------------------------------------- diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtStoragePoolXMLParser.java b/agent/src/com/cloud/agent/resource/computing/LibvirtStoragePoolXMLParser.java index 5c45d76..cff4c2b 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtStoragePoolXMLParser.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtStoragePoolXMLParser.java @@ -51,15 +51,34 @@ public class LibvirtStoragePoolXMLParser { 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); + if (type.equalsIgnoreCase("rbd")) { + int port = Integer.parseInt(getAttrValue("host", "port", source)); + String pool = getTagValue("name", source); + + Element auth = (Element) source.getElementsByTagName( + "auth").item(0); + + if (auth != null) { + String authUsername = auth.getAttribute("username"); + String authType = auth.getAttribute("type"); + return new LibvirtStoragePoolDef(LibvirtStoragePoolDef.poolType.valueOf(type.toUpperCase()), + poolName, uuid, host, port, pool, authUsername, LibvirtStoragePoolDef.authType.valueOf(authType.toUpperCase()), uuid); + } else { + return new LibvirtStoragePoolDef(LibvirtStoragePoolDef.poolType.valueOf(type.toUpperCase()), + poolName, uuid, host, port, pool, ""); + } + } else { + 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) { http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/406fd95d/agent/src/com/cloud/agent/resource/computing/LibvirtVMDef.java ---------------------------------------------------------------------- diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtVMDef.java b/agent/src/com/cloud/agent/resource/computing/LibvirtVMDef.java index 8fd7815..3b07bcd 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtVMDef.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtVMDef.java @@ -338,7 +338,7 @@ public class LibvirtVMDef { } enum diskType { - FILE("file"), BLOCK("block"), DIRECTROY("dir"); + FILE("file"), BLOCK("block"), DIRECTROY("dir"), NETWORK("network"); String _diskType; diskType(String type) { @@ -351,6 +351,20 @@ public class LibvirtVMDef { } } + enum diskProtocol { + RBD("rbd"), SHEEPDOG("sheepdog"); + String _diskProtocol; + + diskProtocol(String protocol) { + _diskProtocol = protocol; + } + + @Override + public String toString() { + return _diskProtocol; + } + } + enum diskBus { IDE("ide"), SCSI("scsi"), VIRTIO("virtio"), XEN("xen"), USB("usb"), UML( "uml"), FDC("fdc"); @@ -382,7 +396,12 @@ public class LibvirtVMDef { private deviceType _deviceType; /* floppy, disk, cdrom */ private diskType _diskType; + private diskProtocol _diskProtocol; private String _sourcePath; + private String _sourceHost; + private int _sourcePort; + private String _authUserName; + private String _authSecretUUID; private String _diskLabel; private diskBus _bus; private diskFmtType _diskFmtType; /* qcow2, raw etc. */ @@ -461,6 +480,38 @@ public class LibvirtVMDef { _bus = bus; } + public void defNetworkBasedDisk(String diskName, String sourceHost, int sourcePort, + String authUserName, String authSecretUUID, + int devId, diskBus bus, diskProtocol protocol) { + _diskType = diskType.NETWORK; + _deviceType = deviceType.DISK; + _diskFmtType = diskFmtType.RAW; + _sourcePath = diskName; + _sourceHost = sourceHost; + _sourcePort = sourcePort; + _authUserName = authUserName; + _authSecretUUID = authSecretUUID; + _diskLabel = getDevLabel(devId, bus); + _bus = bus; + _diskProtocol = protocol; + } + + public void defNetworkBasedDisk(String diskName, String sourceHost, int sourcePort, + String authUserName, String authSecretUUID, + String diskLabel, diskBus bus, diskProtocol protocol) { + _diskType = diskType.NETWORK; + _deviceType = deviceType.DISK; + _diskFmtType = diskFmtType.RAW; + _sourcePath = diskName; + _sourceHost = sourceHost; + _sourcePort = sourcePort; + _authUserName = authUserName; + _authSecretUUID = authSecretUUID; + _diskLabel = diskLabel; + _bus = bus; + _diskProtocol = protocol; + } + public void setReadonly() { _readonly = true; } @@ -527,6 +578,18 @@ public class LibvirtVMDef { diskBuilder.append(" dev='" + _sourcePath + "'"); } diskBuilder.append("/>\n"); + } else if (_diskType == diskType.NETWORK) { + diskBuilder.append("\n"); + diskBuilder.append("\n"); + diskBuilder.append("\n"); + if (_authUserName != null) { + diskBuilder.append("\n"); + diskBuilder.append("\n"); + diskBuilder.append("\n"); + } } diskBuilder.append("', 'label.SharedMountPoint': '', 'label.clvm': '', +'label.rbd': '', 'label.volgroup': '', 'label.VMFS.datastore': '', 'label.network.device': '', http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/406fd95d/ui/scripts/sharedFunctions.js ---------------------------------------------------------------------- diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js index 12d3498..c4cf58c 100644 --- a/ui/scripts/sharedFunctions.js +++ b/ui/scripts/sharedFunctions.js @@ -475,6 +475,31 @@ function SharedMountPointURL(server, path) { return url; } +function rbdURL(monitor, pool, id, secret) { + var url; + + /* + Replace the + and / symbols by - and _ to have URL-safe base64 going to the API + It's hacky, but otherwise we'll confuse java.net.URI which splits the incoming URI + */ + secret = str.replace("+", "-"); + secret = str.replace("/", "_"); + + if (id != null && secret != null) { + monitor = id + ":" + secret + "@" + monitor; + } + + if(pool.substring(0,1) != "/") + pool = "/" + pool; + + if(monitor.indexOf("://")==-1) + url = "rbd://" + monitor + pool; + else + url = monitor + pool; + + return url; +} + function clvmURL(vgname) { var url; if(vgname.indexOf("://")==-1) http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/406fd95d/ui/scripts/system.js ---------------------------------------------------------------------- diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 712c122..59d2d87 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -7494,6 +7494,7 @@ var items = []; items.push({id: "nfs", description: "nfs"}); items.push({id: "SharedMountPoint", description: "SharedMountPoint"}); + items.push({id: "rbd", description: "RBD"}); args.response.success({data: items}); } else if(selectedClusterObj.hypervisortype == "XenServer") { @@ -7677,6 +7678,27 @@ $form.find('.form-item[rel=vCenterDataCenter]').hide(); $form.find('.form-item[rel=vCenterDataStore]').hide(); } + else if(protocol == "rbd") { + $form.find('.form-item[rel=rbdmonitor]').css('display', 'inline-block'); + $form.find('.form-item[rel=rbdmonitor]').find(".name").find("label").text("RADOS Monitor:"); + + $form.find('.form-item[rel=rbdpool]').css('display', 'inline-block'); + $form.find('.form-item[rel=rbdpool]').find(".name").find("label").text("RADOS Pool:"); + + $form.find('.form-item[rel=rbdid]').css('display', 'inline-block'); + $form.find('.form-item[rel=rbdid]').find(".name").find("label").text("RADOS User:"); + + $form.find('.form-item[rel=rbdsecret]').css('display', 'inline-block'); + $form.find('.form-item[rel=rbdsecret]').find(".name").find("label").text("RADOS Secret:"); + + $form.find('.form-item[rel=server]').hide(); + $form.find('.form-item[rel=iqn]').hide(); + $form.find('.form-item[rel=lun]').hide(); + $form.find('.form-item[rel=volumegroup]').hide(); + $form.find('.form-item[rel=path]').hide(); + $form.find('.form-item[rel=vCenterDataCenter]').hide(); + $form.find('.form-item[rel=vCenterDataStore]').hide(); + } else { //$dialogAddPool.find("#add_pool_server_container").show(); $form.find('.form-item[rel=server]').css('display', 'inline-block'); @@ -7744,6 +7766,28 @@ validation: { required: true }, isHidden: true }, + + // RBD + rbdmonitor: { + label: 'label.rbd.monitor', + validation: { required: true }, + isHidden: true + }, + rbdpool: { + label: 'label.rbd.pool', + validation: { required: true }, + isHidden: true + }, + rbdid: { + label: 'label.rbd.id', + validation: { required: false }, + isHidden: true + }, + rbdsecret: { + label: 'label.rbd.secret', + validation: { required: false }, + isHidden: true + }, //always appear (begin) storageTags: { @@ -7803,6 +7847,14 @@ vg = "/" + vg; url = clvmURL(vg); } + else if (args.data.protocol == "rbd") { + var rbdmonitor = args.data.rbdmonitor; + var rbdpool = args.data.rbdpool; + var rbdid = args.data.rbdid; + var rbdsecret = args.data.rbdsecret; + + url = rbdURL(rbdmonitor, rbdpool, rbdid, rbdsecret); + } else if (args.data.protocol == "vmfs") { //var path = trim($thisDialog.find("#add_pool_vmfs_dc").val()); var path = args.data.vCenterDataCenter;