You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ed...@apache.org on 2012/07/30 23:56:04 UTC

[8/8] Move KVM related code into plugins/hypervisor/kvm, a new jar file is created: cloud-kvm.jar

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7a0a9231/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java
new file mode 100644
index 0000000..491f772
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java
@@ -0,0 +1,109 @@
+// 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.hypervisor.kvm.storage;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import com.cloud.hypervisor.kvm.resource.KVMHABase;
+import com.cloud.hypervisor.kvm.resource.KVMHABase.PoolType;
+import com.cloud.hypervisor.kvm.resource.KVMHAMonitor;
+import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk.PhysicalDiskFormat;
+import com.cloud.storage.Storage.StoragePoolType;
+import com.cloud.storage.StorageLayer;
+
+public class KVMStoragePoolManager {
+    private StorageAdaptor _storageAdaptor;
+    private KVMHAMonitor _haMonitor;
+    private final Map<String, Object> _storagePools = new ConcurrentHashMap<String, Object>();
+
+    private void addStoragePool(String uuid) {
+        synchronized (_storagePools) {
+            if (!_storagePools.containsKey(uuid)) {
+                _storagePools.put(uuid, new Object());
+            }
+        }
+    }
+
+    public KVMStoragePoolManager(StorageLayer storagelayer, KVMHAMonitor monitor) {
+        this._storageAdaptor = new LibvirtStorageAdaptor(storagelayer);
+        this._haMonitor = monitor;
+    }
+
+    public KVMStoragePool getStoragePool(String uuid) {
+        return this._storageAdaptor.getStoragePool(uuid);
+    }
+
+    public KVMStoragePool getStoragePoolByURI(String uri) {
+        return this._storageAdaptor.getStoragePoolByUri(uri);
+    }
+
+    public KVMStoragePool createStoragePool(String name, String host, int port, String path,
+                                            String userInfo, StoragePoolType type) {
+        KVMStoragePool pool = this._storageAdaptor.createStoragePool(name,
+                                host, port, path, userInfo, type);
+        if (type == StoragePoolType.NetworkFilesystem) {
+            KVMHABase.NfsStoragePool nfspool = new KVMHABase.NfsStoragePool(
+                    pool.getUuid(), host, path, pool.getLocalPath(),
+                    PoolType.PrimaryStorage);
+            _haMonitor.addStoragePool(nfspool);
+        }
+        addStoragePool(pool.getUuid());
+        return pool;
+    }
+
+    public boolean deleteStoragePool(String uuid) {
+        _haMonitor.removeStoragePool(uuid);
+        this._storageAdaptor.deleteStoragePool(uuid);
+        _storagePools.remove(uuid);
+        return true;
+    }
+
+    public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template, String name,
+                                                    KVMStoragePool destPool) {
+        if (destPool.getType() == StoragePoolType.RBD) {
+            return this._storageAdaptor.createDiskFromTemplate(template, name,
+                    KVMPhysicalDisk.PhysicalDiskFormat.RAW, template.getSize(), destPool);
+        } else {
+            return this._storageAdaptor.createDiskFromTemplate(template, name,
+                    KVMPhysicalDisk.PhysicalDiskFormat.QCOW2,
+            template.getSize(), destPool);
+        }
+    }
+
+    public KVMPhysicalDisk createTemplateFromDisk(KVMPhysicalDisk disk,
+            String name, PhysicalDiskFormat format, long size,
+            KVMStoragePool destPool) {
+        return this._storageAdaptor.createTemplateFromDisk(disk, name, format,
+                size, destPool);
+    }
+
+    public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name,
+            KVMStoragePool destPool) {
+        return this._storageAdaptor.copyPhysicalDisk(disk, name, destPool);
+    }
+
+    public KVMPhysicalDisk createDiskFromSnapshot(KVMPhysicalDisk snapshot,
+            String snapshotName, String name, KVMStoragePool destPool) {
+        return this._storageAdaptor.createDiskFromSnapshot(snapshot,
+                snapshotName, name, destPool);
+    }
+
+    public KVMPhysicalDisk getPhysicalDiskFromUrl(String url) {
+        return this._storageAdaptor.getPhysicalDiskFromURI(url);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7a0a9231/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMVirtualDisk.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMVirtualDisk.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMVirtualDisk.java
new file mode 100644
index 0000000..d773cf4
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMVirtualDisk.java
@@ -0,0 +1,21 @@
+// 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.hypervisor.kvm.storage;
+
+public class KVMVirtualDisk {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7a0a9231/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java
new file mode 100644
index 0000000..90003f9
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java
@@ -0,0 +1,901 @@
+// 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.hypervisor.kvm.storage;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import org.apache.log4j.Logger;
+import org.apache.commons.codec.binary.Base64;
+import org.libvirt.Connect;
+import org.libvirt.LibvirtException;
+import org.libvirt.Secret;
+import org.libvirt.StoragePool;
+import org.libvirt.StoragePoolInfo;
+import org.libvirt.StorageVol;
+import org.libvirt.StoragePoolInfo.StoragePoolState;
+
+import com.cloud.agent.api.ManageSnapshotCommand;
+import com.cloud.hypervisor.kvm.resource.LibvirtConnection;
+import com.cloud.hypervisor.kvm.resource.LibvirtSecretDef;
+import com.cloud.hypervisor.kvm.resource.LibvirtSecretDef.usage;
+import com.cloud.hypervisor.kvm.resource.LibvirtStoragePoolDef;
+import com.cloud.hypervisor.kvm.resource.LibvirtStoragePoolXMLParser;
+import com.cloud.hypervisor.kvm.resource.LibvirtStorageVolumeDef;
+import com.cloud.hypervisor.kvm.resource.LibvirtStoragePoolDef.poolType;
+import com.cloud.hypervisor.kvm.resource.LibvirtStoragePoolDef.authType;
+import com.cloud.hypervisor.kvm.resource.LibvirtStorageVolumeDef.volFormat;
+import com.cloud.hypervisor.kvm.resource.LibvirtStorageVolumeXMLParser;
+import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk.PhysicalDiskFormat;
+import com.cloud.exception.InternalErrorException;
+import com.cloud.storage.Storage.StoragePoolType;
+import com.cloud.storage.StorageLayer;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.script.OutputInterpreter;
+import com.cloud.utils.script.Script;
+
+public class LibvirtStorageAdaptor implements StorageAdaptor {
+    private static final Logger s_logger = Logger
+            .getLogger(LibvirtStorageAdaptor.class);
+    private StorageLayer _storageLayer;
+    private String _mountPoint = "/mnt";
+    private String _manageSnapshotPath;
+
+    public LibvirtStorageAdaptor(StorageLayer storage) {
+        _storageLayer = storage;
+        _manageSnapshotPath = Script.findScript("scripts/storage/qcow2/",
+                "managesnapshot.sh");
+    }
+
+    @Override
+    public boolean createFolder(String uuid, String path) {
+        String mountPoint = _mountPoint + File.separator + uuid;
+        File f = new File(mountPoint + path);
+        if (!f.exists()) {
+            f.mkdirs();
+        }
+        return true;
+    }
+
+    public StorageVol getVolume(StoragePool pool, String volName) {
+        StorageVol vol = null;
+
+        try {
+            vol = pool.storageVolLookupByName(volName);
+        } catch (LibvirtException e) {
+
+        }
+        if (vol == null) {
+            storagePoolRefresh(pool);
+            try {
+                vol = pool.storageVolLookupByName(volName);
+            } catch (LibvirtException e) {
+                throw new CloudRuntimeException(e.toString());
+            }
+        }
+        return vol;
+    }
+
+    public StorageVol createVolume(Connect conn, StoragePool pool, String uuid,
+            long size, volFormat format) throws LibvirtException {
+        LibvirtStorageVolumeDef volDef = new LibvirtStorageVolumeDef(UUID
+                .randomUUID().toString(), size, format, null, null);
+        s_logger.debug(volDef.toString());
+        return pool.storageVolCreateXML(volDef.toString(), 0);
+    }
+
+    public StoragePool getStoragePoolbyURI(Connect conn, URI uri)
+            throws LibvirtException {
+        String sourcePath;
+        String uuid;
+        String sourceHost = "";
+        String protocal;
+        if (uri.getScheme().equalsIgnoreCase("local")) {
+            sourcePath = _mountPoint + File.separator
+                    + uri.toString().replace("local:///", "");
+            sourcePath = sourcePath.replace("//", "/");
+            uuid = UUID.nameUUIDFromBytes(new String(sourcePath).getBytes())
+                    .toString();
+            protocal = "DIR";
+        } else {
+            sourcePath = uri.getPath();
+            sourcePath = sourcePath.replace("//", "/");
+            sourceHost = uri.getHost();
+            uuid = UUID.nameUUIDFromBytes(
+                    new String(sourceHost + sourcePath).getBytes()).toString();
+            protocal = "NFS";
+        }
+
+        String targetPath = _mountPoint + File.separator + uuid;
+        StoragePool sp = null;
+        try {
+            sp = conn.storagePoolLookupByUUIDString(uuid);
+        } catch (LibvirtException e) {
+        }
+
+        if (sp == null) {
+            try {
+                LibvirtStoragePoolDef spd = null;
+                if (protocal.equalsIgnoreCase("NFS")) {
+                    _storageLayer.mkdir(targetPath);
+                    spd = new LibvirtStoragePoolDef(poolType.NETFS, uuid, uuid,
+                            sourceHost, sourcePath, targetPath);
+                    s_logger.debug(spd.toString());
+                    // addStoragePool(uuid);
+
+                } else if (protocal.equalsIgnoreCase("DIR")) {
+                    _storageLayer.mkdir(targetPath);
+                    spd = new LibvirtStoragePoolDef(poolType.DIR, uuid, uuid,
+                            null, null, sourcePath);
+                }
+
+                synchronized (getStoragePool(uuid)) {
+                    sp = conn.storagePoolDefineXML(spd.toString(), 0);
+                    if (sp == null) {
+                        s_logger.debug("Failed to define storage pool");
+                        return null;
+                    }
+                    sp.create(0);
+                }
+
+                return sp;
+            } catch (LibvirtException e) {
+                try {
+                    if (sp != null) {
+                        sp.undefine();
+                        sp.free();
+                    }
+                } catch (LibvirtException l) {
+
+                }
+                throw e;
+            }
+        } else {
+            StoragePoolInfo spi = sp.getInfo();
+            if (spi.state != StoragePoolState.VIR_STORAGE_POOL_RUNNING) {
+                sp.create(0);
+            }
+            return sp;
+        }
+    }
+
+    public void storagePoolRefresh(StoragePool pool) {
+        try {
+            synchronized (getStoragePool(pool.getUUIDString())) {
+                pool.refresh(0);
+            }
+        } catch (LibvirtException e) {
+
+        }
+    }
+
+    private StoragePool createNfsStoragePool(Connect conn, String uuid,
+            String host, String path) {
+        String targetPath = _mountPoint + File.separator + uuid;
+        LibvirtStoragePoolDef spd = new LibvirtStoragePoolDef(poolType.NETFS,
+                uuid, uuid, host, path, targetPath);
+        _storageLayer.mkdir(targetPath);
+        StoragePool sp = null;
+        try {
+            s_logger.debug(spd.toString());
+            sp = conn.storagePoolDefineXML(spd.toString(), 0);
+            sp.create(0);
+            return sp;
+        } catch (LibvirtException e) {
+            s_logger.debug(e.toString());
+            if (sp != null) {
+                try {
+                    sp.undefine();
+                    sp.free();
+                } catch (LibvirtException l) {
+                    s_logger.debug("Failed to define nfs storage pool with: "
+                            + l.toString());
+                }
+            }
+            return null;
+        }
+    }
+
+    private StoragePool CreateSharedStoragePool(Connect conn, String uuid,
+            String host, String path) {
+        String mountPoint = path;
+        if (!_storageLayer.exists(mountPoint)) {
+            return null;
+        }
+        LibvirtStoragePoolDef spd = new LibvirtStoragePoolDef(poolType.DIR,
+                uuid, uuid, host, path, path);
+        StoragePool sp = null;
+        try {
+            s_logger.debug(spd.toString());
+            sp = conn.storagePoolDefineXML(spd.toString(), 0);
+            sp.create(0);
+
+            return sp;
+        } catch (LibvirtException e) {
+            s_logger.debug(e.toString());
+            if (sp != null) {
+                try {
+                    sp.undefine();
+                    sp.free();
+                } catch (LibvirtException l) {
+                    s_logger.debug("Failed to define shared mount point storage pool with: "
+                            + l.toString());
+                }
+            }
+            return null;
+        }
+    }
+
+    private StoragePool createCLVMStoragePool(Connect conn, String uuid,
+            String host, String path) {
+
+        String volgroupPath = "/dev/" + path;
+        String volgroupName = path;
+        volgroupName = volgroupName.replaceFirst("/", "");
+
+        LibvirtStoragePoolDef spd = new LibvirtStoragePoolDef(poolType.LOGICAL,
+                volgroupName, 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;
+        }
+
+    }
+
+    private StoragePool createRBDStoragePool(Connect conn, String uuid,
+        String host, int port, String userInfo, String path) {
+
+        LibvirtStoragePoolDef spd;
+        StoragePool sp = null;
+
+        String[] userInfoTemp = userInfo.split(":");
+        if (userInfoTemp.length == 2) {
+            s_logger.debug("libvirt secret information found. id: " + userInfoTemp[0] + " secret: " + userInfoTemp[1]);
+            LibvirtSecretDef sd = new LibvirtSecretDef(usage.CEPH, uuid);
+
+            Secret s = null;
+
+            sd.setCephName(userInfoTemp[0]);
+
+            try {
+                s_logger.debug(sd.toString());
+                s = conn.secretDefineXML(sd.toString());
+                s.setValue(Base64.decodeBase64(userInfoTemp[1]));
+            } catch (LibvirtException e) {
+                s_logger.debug(e.toString());
+                if (s != null) {
+                    try {
+                        s.undefine();
+                        s.free();
+                    } catch (LibvirtException l) {
+                        s_logger.debug("Failed to define secret with: " + l.toString());
+                        }
+                    }
+            }
+            spd = new LibvirtStoragePoolDef(poolType.RBD, uuid, uuid, host, port, path, userInfoTemp[0], authType.CEPH, uuid);
+        } else {
+            spd = new LibvirtStoragePoolDef(poolType.RBD, uuid, uuid, host, port, path, "");
+        }
+
+        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 RBD storage pool with: " + l.toString());
+                }
+            }
+            return null;
+        }
+    }
+
+    public StorageVol copyVolume(StoragePool destPool,
+            LibvirtStorageVolumeDef destVol, StorageVol srcVol, int timeout)
+            throws LibvirtException {
+        StorageVol vol = destPool.storageVolCreateXML(destVol.toString(), 0);
+        String srcPath = srcVol.getKey();
+        String destPath = vol.getKey();
+        Script.runSimpleBashScript("cp " + srcPath + " " + destPath, timeout);
+        return vol;
+    }
+
+    public boolean copyVolume(String srcPath, String destPath,
+            String volumeName, int timeout) throws InternalErrorException {
+        _storageLayer.mkdirs(destPath);
+        if (!_storageLayer.exists(srcPath)) {
+            throw new InternalErrorException("volume:" + srcPath
+                    + " is not exits");
+        }
+        String result = Script.runSimpleBashScript("cp " + srcPath + " "
+                + destPath + File.separator + volumeName, timeout);
+        if (result != null) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    public LibvirtStoragePoolDef getStoragePoolDef(Connect conn,
+            StoragePool pool) throws LibvirtException {
+        String poolDefXML = pool.getXMLDesc(0);
+        LibvirtStoragePoolXMLParser parser = new LibvirtStoragePoolXMLParser();
+        return parser.parseStoragePoolXML(poolDefXML);
+    }
+
+    public LibvirtStorageVolumeDef getStorageVolumeDef(Connect conn,
+            StorageVol vol) throws LibvirtException {
+        String volDefXML = vol.getXMLDesc(0);
+        LibvirtStorageVolumeXMLParser parser = new LibvirtStorageVolumeXMLParser();
+        return parser.parseStorageVolumeXML(volDefXML);
+    }
+
+    public StorageVol getVolumeFromURI(Connect conn, String volPath)
+            throws LibvirtException, URISyntaxException {
+        int index = volPath.lastIndexOf("/");
+        URI volDir = null;
+        StoragePool sp = null;
+        StorageVol vol = null;
+        try {
+            volDir = new URI(volPath.substring(0, index));
+            String volName = volPath.substring(index + 1);
+            sp = getStoragePoolbyURI(conn, volDir);
+            vol = sp.storageVolLookupByName(volName);
+            return vol;
+        } catch (LibvirtException e) {
+            s_logger.debug("Faild to get vol path: " + e.toString());
+            throw e;
+        } finally {
+            try {
+                if (sp != null) {
+                    sp.free();
+                }
+            } catch (LibvirtException e) {
+
+            }
+        }
+    }
+
+    public StoragePool createFileBasedStoragePool(Connect conn,
+            String localStoragePath, String uuid) {
+        if (!(_storageLayer.exists(localStoragePath) && _storageLayer
+                .isDirectory(localStoragePath))) {
+            return null;
+        }
+
+        File path = new File(localStoragePath);
+        if (!(path.canWrite() && path.canRead() && path.canExecute())) {
+            return null;
+        }
+
+        StoragePool pool = null;
+
+        try {
+            pool = conn.storagePoolLookupByUUIDString(uuid);
+        } catch (LibvirtException e) {
+
+        }
+
+        if (pool == null) {
+            LibvirtStoragePoolDef spd = new LibvirtStoragePoolDef(poolType.DIR,
+                    uuid, uuid, null, null, localStoragePath);
+            try {
+                pool = conn.storagePoolDefineXML(spd.toString(), 0);
+                pool.create(0);
+            } catch (LibvirtException e) {
+                if (pool != null) {
+                    try {
+                        pool.destroy();
+                        pool.undefine();
+                    } catch (LibvirtException e1) {
+                    }
+                    pool = null;
+                }
+                throw new CloudRuntimeException(e.toString());
+            }
+        }
+
+        try {
+            StoragePoolInfo spi = pool.getInfo();
+            if (spi.state != StoragePoolState.VIR_STORAGE_POOL_RUNNING) {
+                pool.create(0);
+            }
+
+        } catch (LibvirtException e) {
+            throw new CloudRuntimeException(e.toString());
+        }
+
+        return pool;
+    }
+
+    private void getStats(LibvirtStoragePool pool) {
+        Script statsScript = new Script("/bin/bash", s_logger);
+        statsScript.add("-c");
+        statsScript.add("stats=$(df --total " + pool.getLocalPath()
+                + " |grep total|awk '{print $2,$3}');echo $stats");
+        final OutputInterpreter.OneLineParser statsParser = new OutputInterpreter.OneLineParser();
+        String result = statsScript.execute(statsParser);
+        if (result == null) {
+            String stats = statsParser.getLine();
+            if (stats != null && !stats.isEmpty()) {
+                String sizes[] = stats.trim().split(" ");
+                if (sizes.length == 2) {
+                    pool.setCapacity(Long.parseLong(sizes[0]) * 1024);
+                    pool.setUsed(Long.parseLong(sizes[1]) * 1024);
+                }
+            }
+        }
+    }
+
+    @Override
+    public KVMStoragePool getStoragePool(String uuid) {
+        StoragePool storage = null;
+        try {
+            Connect conn = LibvirtConnection.getConnection();
+            storage = conn.storagePoolLookupByUUIDString(uuid);
+
+            if (storage.getInfo().state != StoragePoolState.VIR_STORAGE_POOL_RUNNING) {
+                storage.create(0);
+            }
+            LibvirtStoragePoolDef spd = getStoragePoolDef(conn, storage);
+            StoragePoolType type = null;
+            if (spd.getPoolType() == LibvirtStoragePoolDef.poolType.NETFS
+                    || spd.getPoolType() == LibvirtStoragePoolDef.poolType.DIR) {
+                type = StoragePoolType.Filesystem;
+            } else if (spd.getPoolType() == LibvirtStoragePoolDef.poolType.RBD) {
+                type = StoragePoolType.RBD;
+            }
+
+            LibvirtStoragePool pool = new LibvirtStoragePool(uuid, storage.getName(),
+                                                            type, this, storage);
+
+            if (pool.getType() != StoragePoolType.RBD) {
+                pool.setLocalPath(spd.getTargetPath());
+            } else {
+                pool.setLocalPath("");
+                pool.setSourceHost(spd.getSourceHost());
+                pool.setSourcePort(spd.getSourcePort());
+                pool.setSourceDir(spd.getSourceDir());
+                String authUsername = spd.getAuthUserName();
+                if (authUsername != null) {
+                    Secret secret = conn.secretLookupByUUIDString(spd.getSecretUUID());
+                    String secretValue = new String(Base64.encodeBase64(secret.getByteValue()));
+                    pool.setAuthUsername(authUsername);
+                    pool.setAuthSecret(secretValue);
+                }
+            }
+
+            if (pool.getType() == StoragePoolType.RBD) {
+                pool.setCapacity(storage.getInfo().capacity);
+                pool.setUsed(storage.getInfo().allocation);
+            } else {
+                getStats(pool);
+            }
+
+            return pool;
+        } catch (LibvirtException e) {
+            throw new CloudRuntimeException(e.toString());
+        }
+    }
+
+    @Override
+    public KVMPhysicalDisk getPhysicalDisk(String volumeUuid,
+            KVMStoragePool pool) {
+        LibvirtStoragePool libvirtPool = (LibvirtStoragePool) pool;
+
+        try {
+            StorageVol vol = this.getVolume(libvirtPool.getPool(), volumeUuid);
+            KVMPhysicalDisk disk;
+            LibvirtStorageVolumeDef voldef = getStorageVolumeDef(libvirtPool
+                    .getPool().getConnect(), vol);
+            disk = new KVMPhysicalDisk(vol.getPath(), vol.getName(), pool);
+            disk.setSize(vol.getInfo().allocation);
+            disk.setVirtualSize(vol.getInfo().capacity);
+            if (voldef.getFormat() == null) {
+                disk.setFormat(pool.getDefaultFormat());
+            } else if (pool.getType() == StoragePoolType.RBD) {
+                disk.setFormat(KVMPhysicalDisk.PhysicalDiskFormat.RAW);
+            } else if (voldef.getFormat() == LibvirtStorageVolumeDef.volFormat.QCOW2) {
+                disk.setFormat(KVMPhysicalDisk.PhysicalDiskFormat.QCOW2);
+            } else if (voldef.getFormat() == LibvirtStorageVolumeDef.volFormat.RAW) {
+                disk.setFormat(KVMPhysicalDisk.PhysicalDiskFormat.RAW);
+            }
+            return disk;
+        } catch (LibvirtException e) {
+            throw new CloudRuntimeException(e.toString());
+        }
+
+    }
+
+    @Override
+    public KVMStoragePool createStoragePool(String name, String host, int port,
+                                            String path, String userInfo, StoragePoolType type) {
+        StoragePool sp = null;
+        Connect conn = null;
+        try {
+            conn = LibvirtConnection.getConnection();
+        } catch (LibvirtException e) {
+            throw new CloudRuntimeException(e.toString());
+        }
+
+        try {
+            sp = conn.storagePoolLookupByUUIDString(name);
+            if (sp.getInfo().state != StoragePoolState.VIR_STORAGE_POOL_RUNNING) {
+                sp.undefine();
+                sp = null;
+            }
+        } catch (LibvirtException e) {
+
+        }
+
+        if (sp == null) {
+            if (type == StoragePoolType.NetworkFilesystem) {
+                sp = createNfsStoragePool(conn, name, host, path);
+            } else if (type == StoragePoolType.SharedMountPoint
+                    || type == StoragePoolType.Filesystem) {
+                sp = CreateSharedStoragePool(conn, name, host, path);
+            } else if (type == StoragePoolType.RBD) {
+                sp = createRBDStoragePool(conn, name, host, port, userInfo, path);
+            }
+        }
+
+        try {
+            StoragePoolInfo spi = sp.getInfo();
+            if (spi.state != StoragePoolState.VIR_STORAGE_POOL_RUNNING) {
+                sp.create(0);
+            }
+
+            LibvirtStoragePoolDef spd = getStoragePoolDef(conn, sp);
+            LibvirtStoragePool pool = new LibvirtStoragePool(name,
+                    sp.getName(), type, this, sp);
+
+            if (pool.getType() != StoragePoolType.RBD) {
+                pool.setLocalPath(spd.getTargetPath());
+            } else {
+                pool.setLocalPath("");
+            }
+
+            if (pool.getType() == StoragePoolType.RBD) {
+                pool.setCapacity(sp.getInfo().capacity);
+                pool.setUsed(sp.getInfo().allocation);
+            } else {
+                getStats(pool);
+            }
+            return pool;
+        } catch (LibvirtException e) {
+            throw new CloudRuntimeException(e.toString());
+        }
+    }
+
+    @Override
+    public boolean deleteStoragePool(String uuid) {
+        Connect conn = null;
+        try {
+            conn = LibvirtConnection.getConnection();
+        } catch (LibvirtException e) {
+            throw new CloudRuntimeException(e.toString());
+        }
+
+        StoragePool sp = null;
+        Secret s = null;
+
+        try {
+            sp = conn.storagePoolLookupByUUIDString(uuid);
+        } catch (LibvirtException e) {
+            return true;
+        }
+
+        /*
+         * Some storage pools, like RBD also have 'secret' information stored in libvirt
+         * Destroy them if they exist
+        */
+        try {
+            s = conn.secretLookupByUUIDString(uuid);
+        } catch (LibvirtException e) {
+        }
+
+        try {
+            sp.destroy();
+            sp.undefine();
+            sp.free();
+            if (s != null) {
+                s.undefine();
+                s.free();
+            }
+            return true;
+        } catch (LibvirtException e) {
+            throw new CloudRuntimeException(e.toString());
+        }
+    }
+
+    @Override
+    public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool,
+            PhysicalDiskFormat format, long size) {
+        LibvirtStoragePool libvirtPool = (LibvirtStoragePool) pool;
+        StoragePool virtPool = libvirtPool.getPool();
+        LibvirtStorageVolumeDef.volFormat libvirtformat = null;
+
+        if (pool.getType() == StoragePoolType.RBD) {
+            format = PhysicalDiskFormat.RAW;
+        }
+
+        if (format == PhysicalDiskFormat.QCOW2) {
+            libvirtformat = LibvirtStorageVolumeDef.volFormat.QCOW2;
+        } else if (format == PhysicalDiskFormat.RAW) {
+            libvirtformat = LibvirtStorageVolumeDef.volFormat.RAW;
+        }
+
+        LibvirtStorageVolumeDef volDef = new LibvirtStorageVolumeDef(name,
+                size, libvirtformat, null, null);
+        s_logger.debug(volDef.toString());
+        try {
+            StorageVol vol = virtPool.storageVolCreateXML(volDef.toString(), 0);
+            KVMPhysicalDisk disk = new KVMPhysicalDisk(vol.getPath(),
+                    vol.getName(), pool);
+            disk.setFormat(format);
+            disk.setSize(vol.getInfo().allocation);
+            disk.setVirtualSize(vol.getInfo().capacity);
+            return disk;
+        } catch (LibvirtException e) {
+            throw new CloudRuntimeException(e.toString());
+        }
+    }
+
+    @Override
+    public boolean deletePhysicalDisk(String uuid, KVMStoragePool pool) {
+        LibvirtStoragePool libvirtPool = (LibvirtStoragePool) pool;
+        try {
+            StorageVol vol = this.getVolume(libvirtPool.getPool(), uuid);
+            vol.delete(0);
+            vol.free();
+            return true;
+        } catch (LibvirtException e) {
+            throw new CloudRuntimeException(e.toString());
+        }
+    }
+
+    @Override
+    public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template,
+            String name, PhysicalDiskFormat format, long size, KVMStoragePool destPool) {
+
+        String newUuid = UUID.randomUUID().toString();
+        KVMStoragePool srcPool = template.getPool();
+        KVMPhysicalDisk disk = null;
+
+        /*
+            With RBD you can't run qemu-img convert with an existing RBD image as destination
+            qemu-img will exit with the error that the destination already exists.
+            So for RBD we don't create the image, but let qemu-img do that for us.
+
+            We then create a KVMPhysicalDisk object that we can return
+        */
+
+        if (destPool.getType() != StoragePoolType.RBD) {
+            disk = destPool.createPhysicalDisk(newUuid, format, template.getVirtualSize());
+
+            Script.runSimpleBashScript("qemu-img create -f "
+                    + template.getFormat() + " -b  " + template.getPath() + " "
+                    + disk.getPath());
+        } else {
+            disk = new KVMPhysicalDisk(destPool.getSourceDir() + "/" + newUuid, newUuid, destPool);
+            disk.setFormat(format);
+            disk.setSize(template.getVirtualSize());
+            disk.setVirtualSize(disk.getSize());
+
+            if (srcPool.getType() != StoragePoolType.RBD) {
+                Script.runSimpleBashScript("qemu-img convert"
+                        + " -f " + template.getFormat()
+                        + " -O " + format
+                        + " " + template.getPath()
+                        + " " + KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(),
+                                                destPool.getSourcePort(),
+                                                destPool.getAuthUserName(),
+                                                destPool.getAuthSecret(),
+                                                disk.getPath()));
+            } else {
+                template.setFormat(PhysicalDiskFormat.RAW);
+                Script.runSimpleBashScript("qemu-img convert"
+                        + " -f " + template.getFormat()
+                        + " -O " + format
+                        + " " + KVMPhysicalDisk.RBDStringBuilder(srcPool.getSourceHost(),
+                                                srcPool.getSourcePort(),
+                                                srcPool.getAuthUserName(),
+                                                srcPool.getAuthSecret(),
+                                                template.getPath())
+                        + " " + KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(),
+                                                destPool.getSourcePort(),
+                                                destPool.getAuthUserName(),
+                                                destPool.getAuthSecret(),
+                                                disk.getPath()));
+            }
+        }
+        return disk;
+    }
+
+    @Override
+    public KVMPhysicalDisk createTemplateFromDisk(KVMPhysicalDisk disk,
+            String name, PhysicalDiskFormat format, long size,
+            KVMStoragePool destPool) {
+        return null;
+    }
+
+    @Override
+    public List<KVMPhysicalDisk> listPhysicalDisks(String storagePoolUuid,
+            KVMStoragePool pool) {
+        LibvirtStoragePool libvirtPool = (LibvirtStoragePool) pool;
+        StoragePool virtPool = libvirtPool.getPool();
+        List<KVMPhysicalDisk> disks = new ArrayList<KVMPhysicalDisk>();
+        try {
+            String[] vols = virtPool.listVolumes();
+            for (String volName : vols) {
+                KVMPhysicalDisk disk = this.getPhysicalDisk(volName, pool);
+                disks.add(disk);
+            }
+            return disks;
+        } catch (LibvirtException e) {
+            throw new CloudRuntimeException(e.toString());
+        }
+    }
+
+    @Override
+    public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name,
+            KVMStoragePool destPool) {
+
+        /*
+            With RBD you can't run qemu-img convert with an existing RBD image as destination
+            qemu-img will exit with the error that the destination already exists.
+            So for RBD we don't create the image, but let qemu-img do that for us.
+
+            We then create a KVMPhysicalDisk object that we can return
+        */
+
+        KVMPhysicalDisk newDisk;
+        if (destPool.getType() != StoragePoolType.RBD) {
+            newDisk = destPool.createPhysicalDisk(name, disk.getVirtualSize());
+        } else {
+            newDisk = new KVMPhysicalDisk(destPool.getSourceDir() + "/" + name, name, destPool);
+            newDisk.setFormat(PhysicalDiskFormat.RAW);
+            newDisk.setSize(disk.getVirtualSize());
+            newDisk.setVirtualSize(disk.getSize());
+        }
+
+        KVMStoragePool srcPool = disk.getPool();
+        String destPath = newDisk.getPath();
+        String sourcePath = disk.getPath();
+        PhysicalDiskFormat sourceFormat = disk.getFormat();
+        PhysicalDiskFormat destFormat = newDisk.getFormat();
+
+        if ((srcPool.getType() != StoragePoolType.RBD) && (destPool.getType() != StoragePoolType.RBD)) {
+            Script.runSimpleBashScript("qemu-img convert -f " + sourceFormat
+                + " -O " + destFormat
+                + " " + sourcePath
+                + " " + destPath);
+        } else if ((srcPool.getType() != StoragePoolType.RBD) && (destPool.getType() == StoragePoolType.RBD))  {
+            Script.runSimpleBashScript("qemu-img convert -f " + sourceFormat
+                    + " -O " + destFormat
+                    + " " + sourcePath
+                    + " " + KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(),
+                                                destPool.getSourcePort(),
+                                                destPool.getAuthUserName(),
+                                                destPool.getAuthSecret(),
+                                                destPath));
+        } else {
+            Script.runSimpleBashScript("qemu-img convert -f " + sourceFormat
+                    + " -O " + destFormat
+                    + " " + KVMPhysicalDisk.RBDStringBuilder(srcPool.getSourceHost(),
+                                                srcPool.getSourcePort(),
+                                                srcPool.getAuthUserName(),
+                                                srcPool.getAuthSecret(),
+                                                sourcePath)
+                    + " " + KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(),
+                                                destPool.getSourcePort(),
+                                                destPool.getAuthUserName(),
+                                                destPool.getAuthSecret(),
+                                                destPath));
+        }
+
+        return newDisk;
+    }
+
+    @Override
+    public KVMStoragePool getStoragePoolByUri(String uri) {
+        URI storageUri = null;
+
+        try {
+            storageUri = new URI(uri);
+        } catch (URISyntaxException e) {
+            throw new CloudRuntimeException(e.toString());
+        }
+
+        String sourcePath = null;
+        String uuid = null;
+        String sourceHost = "";
+        StoragePoolType protocal = null;
+        if (storageUri.getScheme().equalsIgnoreCase("nfs")) {
+            sourcePath = storageUri.getPath();
+            sourcePath = sourcePath.replace("//", "/");
+            sourceHost = storageUri.getHost();
+            uuid = UUID.randomUUID().toString();
+            protocal = StoragePoolType.NetworkFilesystem;
+        }
+
+            return createStoragePool(uuid, sourceHost, 0, sourcePath, "", protocal);
+    }
+
+    @Override
+    public KVMPhysicalDisk getPhysicalDiskFromURI(String uri) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public KVMPhysicalDisk createDiskFromSnapshot(KVMPhysicalDisk snapshot,
+            String snapshotName, String name, KVMStoragePool destPool) {
+        return null;
+    }
+
+    @Override
+    public boolean refresh(KVMStoragePool pool) {
+        LibvirtStoragePool libvirtPool = (LibvirtStoragePool) pool;
+        StoragePool virtPool = libvirtPool.getPool();
+        try {
+            virtPool.refresh(0);
+        } catch (LibvirtException e) {
+            return false;
+        }
+        return true;
+    }
+
+    @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;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7a0a9231/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStoragePool.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStoragePool.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStoragePool.java
new file mode 100644
index 0000000..bc428e1
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStoragePool.java
@@ -0,0 +1,208 @@
+// 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.hypervisor.kvm.storage;
+
+import java.util.List;
+
+import org.libvirt.StoragePool;
+
+import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk.PhysicalDiskFormat;
+import com.cloud.storage.Storage.StoragePoolType;
+
+public class LibvirtStoragePool implements KVMStoragePool {
+    protected String uuid;
+    protected String uri;
+    protected long capacity;
+    protected long used;
+    protected String name;
+    protected String localPath;
+    protected PhysicalDiskFormat defaultFormat;
+    protected StoragePoolType type;
+    protected StorageAdaptor _storageAdaptor;
+    protected StoragePool _pool;
+    protected String authUsername;
+    protected String authSecret;
+    protected String sourceHost;
+    protected int sourcePort;
+    protected String sourceDir;
+
+    public LibvirtStoragePool(String uuid, String name, StoragePoolType type,
+            StorageAdaptor adaptor, StoragePool pool) {
+        this.uuid = uuid;
+        this.name = name;
+        this.type = type;
+        this._storageAdaptor = adaptor;
+        this.capacity = 0;
+        this.used = 0;
+        this._pool = pool;
+
+    }
+
+    public void setCapacity(long capacity) {
+        this.capacity = capacity;
+    }
+
+    @Override
+    public long getCapacity() {
+        return this.capacity;
+    }
+
+    public void setUsed(long used) {
+        this.used = used;
+    }
+
+    @Override
+    public long getUsed() {
+        return this.used;
+    }
+
+    public StoragePoolType getStoragePoolType() {
+        return this.type;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public String getUuid() {
+        return this.uuid;
+    }
+
+    public String uri() {
+        return this.uri;
+    }
+
+    @Override
+    public PhysicalDiskFormat getDefaultFormat() {
+        return PhysicalDiskFormat.QCOW2;
+    }
+
+    @Override
+    public KVMPhysicalDisk createPhysicalDisk(String name,
+            PhysicalDiskFormat format, long size) {
+        return this._storageAdaptor
+                .createPhysicalDisk(name, this, format, size);
+    }
+
+    @Override
+    public KVMPhysicalDisk createPhysicalDisk(String name, long size) {
+        return this._storageAdaptor.createPhysicalDisk(name, this,
+                this.getDefaultFormat(), size);
+    }
+
+    @Override
+    public KVMPhysicalDisk getPhysicalDisk(String volumeUuid) {
+        return this._storageAdaptor.getPhysicalDisk(volumeUuid, this);
+    }
+
+    @Override
+    public boolean deletePhysicalDisk(String uuid) {
+        return this._storageAdaptor.deletePhysicalDisk(uuid, this);
+    }
+
+    @Override
+    public List<KVMPhysicalDisk> listPhysicalDisks() {
+        return this._storageAdaptor.listPhysicalDisks(this.uuid, this);
+    }
+
+    @Override
+    public boolean refresh() {
+        return this._storageAdaptor.refresh(this);
+    }
+
+    @Override
+    public boolean isExternalSnapshot() {
+        if (this.type == StoragePoolType.Filesystem) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public String getLocalPath() {
+        return this.localPath;
+    }
+
+    public void setLocalPath(String localPath) {
+        this.localPath = localPath;
+    }
+
+    @Override
+    public String getAuthUserName() {
+        return this.authUsername;
+    }
+
+    public void setAuthUsername(String authUsername) {
+        this.authUsername = authUsername;
+    }
+
+    @Override
+    public String getAuthSecret() {
+        return this.authSecret;
+    }
+
+    public void setAuthSecret(String authSecret) {
+        this.authSecret = authSecret;
+    }
+
+    @Override
+    public String getSourceHost() {
+        return this.sourceHost;
+    }
+
+    public void setSourceHost(String host) {
+        this.sourceHost = host;
+    }
+
+    @Override
+    public int getSourcePort() {
+        return this.sourcePort;
+    }
+
+    public void setSourcePort(int port) {
+        this.sourcePort = port;
+    }
+
+    @Override
+    public String getSourceDir() {
+        return this.sourceDir;
+    }
+
+    public void setSourceDir(String dir) {
+        this.sourceDir = dir;
+    }
+
+    @Override
+    public StoragePoolType getType() {
+        return this.type;
+    }
+
+    public StoragePool getPool() {
+        return this._pool;
+    }
+
+    @Override
+    public boolean delete() {
+        return this._storageAdaptor.deleteStoragePool(this);
+    }
+
+    @Override
+    public boolean createFolder(String path) {
+        return this._storageAdaptor.createFolder(this.uuid, path);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7a0a9231/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/StorageAdaptor.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/StorageAdaptor.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/StorageAdaptor.java
new file mode 100644
index 0000000..be6c5c0
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/StorageAdaptor.java
@@ -0,0 +1,68 @@
+// 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.hypervisor.kvm.storage;
+
+import java.util.List;
+
+import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk.PhysicalDiskFormat;
+import com.cloud.storage.Storage.StoragePoolType;
+
+public interface StorageAdaptor {
+
+    public KVMStoragePool getStoragePool(String uuid);
+
+    public KVMPhysicalDisk getPhysicalDisk(String volumeUuid,
+            KVMStoragePool pool);
+
+    public KVMStoragePool createStoragePool(String name, String host, int port,
+            String path, String userInfo, StoragePoolType type);
+
+    public boolean deleteStoragePool(String uuid);
+
+    public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool,
+            PhysicalDiskFormat format, long size);
+
+    public boolean deletePhysicalDisk(String uuid, KVMStoragePool pool);
+
+    public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template,
+            String name, PhysicalDiskFormat format, long size,
+            KVMStoragePool destPool);
+
+    public KVMPhysicalDisk createTemplateFromDisk(KVMPhysicalDisk disk,
+            String name, PhysicalDiskFormat format, long size,
+            KVMStoragePool destPool);
+
+    public List<KVMPhysicalDisk> listPhysicalDisks(String storagePoolUuid,
+            KVMStoragePool pool);
+
+    public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name,
+            KVMStoragePool destPools);
+
+    public KVMPhysicalDisk createDiskFromSnapshot(KVMPhysicalDisk snapshot,
+            String snapshotName, String name, KVMStoragePool destPool);
+
+    public KVMStoragePool getStoragePoolByUri(String uri);
+
+    public KVMPhysicalDisk getPhysicalDiskFromURI(String uri);
+
+    public boolean refresh(KVMStoragePool pool);
+
+    public boolean deleteStoragePool(KVMStoragePool pool);
+
+    public boolean createFolder(String uuid, String path);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7a0a9231/server/src/com/cloud/agent/manager/AgentManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/agent/manager/AgentManagerImpl.java b/server/src/com/cloud/agent/manager/AgentManagerImpl.java
index 844c8b9..9fb9027 100755
--- a/server/src/com/cloud/agent/manager/AgentManagerImpl.java
+++ b/server/src/com/cloud/agent/manager/AgentManagerImpl.java
@@ -88,7 +88,7 @@ import com.cloud.host.dao.HostDao;
 import com.cloud.host.dao.HostTagsDao;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.hypervisor.HypervisorGuruManager;
-import com.cloud.hypervisor.kvm.resource.KvmDummyResourceBase;
+import com.cloud.hypervisor.kvm.discover.KvmDummyResourceBase;
 import com.cloud.network.dao.IPAddressDao;
 import com.cloud.resource.Discoverer;
 import com.cloud.resource.ResourceManager;

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7a0a9231/server/src/com/cloud/baremetal/BareMetalResourceBase.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/baremetal/BareMetalResourceBase.java b/server/src/com/cloud/baremetal/BareMetalResourceBase.java
index 24f8002..8c14cce 100755
--- a/server/src/com/cloud/baremetal/BareMetalResourceBase.java
+++ b/server/src/com/cloud/baremetal/BareMetalResourceBase.java
@@ -56,7 +56,6 @@ import com.cloud.agent.api.to.VirtualMachineTO;
 import com.cloud.api.ApiConstants;
 import com.cloud.host.Host.Type;
 import com.cloud.hypervisor.Hypervisor;
-import com.cloud.hypervisor.kvm.resource.KvmDummyResourceBase;
 import com.cloud.resource.ServerResource;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.script.OutputInterpreter;

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7a0a9231/server/src/com/cloud/hypervisor/kvm/discoverer/KvmServerDiscoverer.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/hypervisor/kvm/discoverer/KvmServerDiscoverer.java b/server/src/com/cloud/hypervisor/kvm/discoverer/KvmServerDiscoverer.java
deleted file mode 100755
index fa47a20..0000000
--- a/server/src/com/cloud/hypervisor/kvm/discoverer/KvmServerDiscoverer.java
+++ /dev/null
@@ -1,400 +0,0 @@
-// 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.hypervisor.kvm.discoverer;
-
-import java.net.InetAddress;
-import java.net.URI;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import javax.ejb.Local;
-import javax.naming.ConfigurationException;
-
-import org.apache.log4j.Logger;
-
-import com.cloud.agent.AgentManager;
-import com.cloud.agent.Listener;
-import com.cloud.agent.api.AgentControlAnswer;
-import com.cloud.agent.api.AgentControlCommand;
-import com.cloud.agent.api.Answer;
-import com.cloud.agent.api.Command;
-import com.cloud.agent.api.ShutdownCommand;
-import com.cloud.agent.api.StartupCommand;
-import com.cloud.agent.api.StartupRoutingCommand;
-import com.cloud.configuration.Config;
-import com.cloud.configuration.dao.ConfigurationDao;
-import com.cloud.dc.ClusterVO;
-import com.cloud.dc.dao.ClusterDao;
-import com.cloud.exception.AgentUnavailableException;
-import com.cloud.exception.DiscoveredWithErrorException;
-import com.cloud.exception.DiscoveryException;
-import com.cloud.exception.OperationTimedoutException;
-import com.cloud.host.Host;
-import com.cloud.host.HostVO;
-import com.cloud.host.Status;
-import com.cloud.host.dao.HostDao;
-import com.cloud.hypervisor.Hypervisor;
-import com.cloud.hypervisor.Hypervisor.HypervisorType;
-import com.cloud.hypervisor.kvm.resource.KvmDummyResourceBase;
-import com.cloud.network.NetworkManager;
-import com.cloud.network.PhysicalNetworkSetupInfo;
-import com.cloud.network.PhysicalNetworkVO;
-import com.cloud.network.Networks.TrafficType;
-import com.cloud.resource.Discoverer;
-import com.cloud.resource.DiscovererBase;
-import com.cloud.resource.ResourceManager;
-import com.cloud.resource.ResourceStateAdapter;
-import com.cloud.resource.ServerResource;
-import com.cloud.resource.UnableDeleteHostException;
-import com.cloud.utils.component.ComponentLocator;
-import com.cloud.utils.component.Inject;
-import com.cloud.utils.script.Script;
-import com.cloud.utils.ssh.SSHCmdHelper;
-import com.trilead.ssh2.ChannelCondition;
-import com.trilead.ssh2.SCPClient;
-import com.trilead.ssh2.Session;
-
-@Local(value=Discoverer.class)
-public class KvmServerDiscoverer extends DiscovererBase implements Discoverer,
-		Listener, ResourceStateAdapter {
-	 private static final Logger s_logger = Logger.getLogger(KvmServerDiscoverer.class);
-	 private String _setupAgentPath;
-	 private ConfigurationDao _configDao;
-	 private String _hostIp;
-	 private int _waitTime = 5; /*wait for 5 minutes*/
-	 private String _kvmPrivateNic;
-	 private String _kvmPublicNic;
-	 private String _kvmGuestNic;
-	 @Inject HostDao _hostDao = null;
-	 @Inject ClusterDao _clusterDao;
-	 @Inject ResourceManager _resourceMgr;
-	 @Inject AgentManager _agentMgr;
-	 @Inject NetworkManager _networkMgr;
-	 
-	@Override
-	public boolean processAnswers(long agentId, long seq, Answer[] answers) {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	@Override
-	public boolean processCommands(long agentId, long seq, Command[] commands) {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	@Override
-	public AgentControlAnswer processControlCommand(long agentId,
-			AgentControlCommand cmd) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) {
-	}
-
-	@Override
-	public boolean processDisconnect(long agentId, Status state) {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	@Override
-	public boolean isRecurring() {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	@Override
-	public int getTimeout() {
-		// TODO Auto-generated method stub
-		return 0;
-	}
-
-	@Override
-	public boolean processTimeout(long agentId, long seq) {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	@Override
-	public Map<? extends ServerResource, Map<String, String>> find(long dcId,
-			Long podId, Long clusterId, URI uri, String username,
-			String password, List<String> hostTags) throws DiscoveryException {
-		
-        ClusterVO cluster = _clusterDao.findById(clusterId);
-        if(cluster == null || cluster.getHypervisorType() != HypervisorType.KVM) {
-        	if(s_logger.isInfoEnabled())
-        		s_logger.info("invalid cluster id or cluster is not for KVM hypervisors"); 
-    		return null;
-        }
-		
-		 Map<KvmDummyResourceBase, Map<String, String>> resources = new HashMap<KvmDummyResourceBase, Map<String, String>>();
-		 Map<String, String> details = new HashMap<String, String>();
-		if (!uri.getScheme().equals("http")) {
-            String msg = "urlString is not http so we're not taking care of the discovery for this: " + uri;
-            s_logger.debug(msg);
-            return null;
-		}
-		com.trilead.ssh2.Connection sshConnection = null;
-		String agentIp = null;
-		try {
-			
-			String hostname = uri.getHost();
-			InetAddress ia = InetAddress.getByName(hostname);
-			agentIp = ia.getHostAddress();
-			String guid = UUID.nameUUIDFromBytes(agentIp.getBytes()).toString();
-			String guidWithTail = guid + "-LibvirtComputingResource";/*tail added by agent.java*/
-			if (_resourceMgr.findHostByGuid(guidWithTail) != null) {
-				s_logger.debug("Skipping " + agentIp + " because " + guidWithTail + " is already in the database.");
-				return null;
-			}       
-			
-			sshConnection = new com.trilead.ssh2.Connection(agentIp, 22);
-
-			sshConnection.connect(null, 60000, 60000);
-			if (!sshConnection.authenticateWithPassword(username, password)) {
-				s_logger.debug("Failed to authenticate");
-				throw new DiscoveredWithErrorException("Authentication error");
-			}
-			
-			if (!SSHCmdHelper.sshExecuteCmd(sshConnection, "lsmod|grep kvm", 3)) {
-				s_logger.debug("It's not a KVM enabled machine");
-				return null;
-			}
-			
-			List <PhysicalNetworkSetupInfo> netInfos = _networkMgr.getPhysicalNetworkInfo(dcId, HypervisorType.KVM);
-			String kvmPrivateNic = _kvmPrivateNic;
-			String kvmPublicNic = _kvmPublicNic;
-			String kvmGuestNic = _kvmGuestNic;
-
-			for (PhysicalNetworkSetupInfo info : netInfos) {
-			    if (info.getPrivateNetworkName() != null) {
-			        kvmPrivateNic = info.getPrivateNetworkName();
-			    }
-			    if (info.getPublicNetworkName() != null) {
-			        kvmPublicNic = info.getPublicNetworkName();
-			    }
-			    if (info.getGuestNetworkName() != null) {
-			        kvmGuestNic = info.getGuestNetworkName();
-			    }
-			}
-
-                        String parameters = " -m " + _hostIp + " -z " + dcId + " -p " + podId + " -c " + clusterId + " -g " + guid + " -a";
-			
-			if (kvmPublicNic != null) {
-				parameters += " --pubNic=" + kvmPublicNic;
-			}
-			
-			if (kvmPrivateNic != null) {
-				parameters += " --prvNic=" + kvmPrivateNic;
-			}
-			
-			if (kvmGuestNic != null) {
-			    parameters += " --guestNic=" + kvmGuestNic;
-			}
-		
-			SSHCmdHelper.sshExecuteCmd(sshConnection, "cloud-setup-agent " + parameters, 3);
-			
-			KvmDummyResourceBase kvmResource = new KvmDummyResourceBase();
-			Map<String, Object> params = new HashMap<String, Object>();
-						
-			params.put("zone", Long.toString(dcId));
-			params.put("pod", Long.toString(podId));
-			params.put("cluster",  Long.toString(clusterId));
-			params.put("guid", guid); 
-			params.put("agentIp", agentIp);
-			kvmResource.configure("kvm agent", params);
-			resources.put(kvmResource, details);
-			
-			HostVO connectedHost = waitForHostConnect(dcId, podId, clusterId, guidWithTail);
-			if (connectedHost == null)
-				return null;
-			
-			details.put("guid", guidWithTail);
-			
-			 // place a place holder guid derived from cluster ID
-			if (cluster.getGuid() == null) {
-			    cluster.setGuid(UUID.nameUUIDFromBytes(String.valueOf(clusterId).getBytes()).toString());
-			    _clusterDao.update(clusterId, cluster);
-			}
-			
-			//save user name and password
-			_hostDao.loadDetails(connectedHost);
-			Map<String, String> hostDetails = connectedHost.getDetails();
-			hostDetails.put("password", password);
-			hostDetails.put("username", username);
-			_hostDao.saveDetails(connectedHost);
-			return resources;
-		} catch (DiscoveredWithErrorException e){ 
-			throw e;
-		}catch (Exception e) {
-			String msg = " can't setup agent, due to " + e.toString() + " - " + e.getMessage();
-			s_logger.warn(msg);
-		} finally {
-			if (sshConnection != null)
-				sshConnection.close();
-		}
-		
-		return null;
-	}
-
-	private HostVO waitForHostConnect(long dcId, long podId, long clusterId, String guid) {
-		for (int i = 0; i < _waitTime *2; i++) {
-			List<HostVO> hosts = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.Routing, clusterId, podId, dcId);
-			for (HostVO host : hosts) {
-				if (host.getGuid().equalsIgnoreCase(guid)) {
-					return host;
-				}
-			}
-			try {
-				Thread.sleep(30000);
-			} catch (InterruptedException e) {
-				s_logger.debug("Failed to sleep: " + e.toString());
-			}
-		}
-		s_logger.debug("Timeout, to wait for the host connecting to mgt svr, assuming it is failed");
-		List<HostVO> hosts = _resourceMgr.findHostByGuid(dcId, guid);
-		if (hosts.size() == 1) {
-			return hosts.get(0);
-		} else {
-			return null;
-		}
-	}
-	
-	@Override
-    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
-		ComponentLocator locator = ComponentLocator.getCurrentLocator();
-        _configDao = locator.getDao(ConfigurationDao.class);
-		_setupAgentPath = Script.findScript(getPatchPath(), "setup_agent.sh");
-		_kvmPrivateNic = _configDao.getValue(Config.KvmPrivateNetwork.key());
-		if (_kvmPrivateNic == null) {
-		    _kvmPrivateNic = "cloudbr0";
-		}
-		
-		_kvmPublicNic = _configDao.getValue(Config.KvmPublicNetwork.key());
-		if (_kvmPublicNic == null) {
-		    _kvmPublicNic = _kvmPrivateNic;
-		}
-		
-		_kvmGuestNic = _configDao.getValue(Config.KvmGuestNetwork.key());
-		if (_kvmGuestNic == null) {
-		    _kvmGuestNic = _kvmPrivateNic;
-		}
-		
-		if (_setupAgentPath == null) {
-			throw new ConfigurationException("Can't find setup_agent.sh");
-		}
-		_hostIp = _configDao.getValue("host");
-		if (_hostIp == null) {
-			throw new ConfigurationException("Can't get host IP");
-		}
-    	_resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
-		return true;
-	}
-	
-	protected String getPatchPath() {
-        return "scripts/vm/hypervisor/kvm/";
-    }
-
-	@Override
-	public void postDiscovery(List<HostVO> hosts, long msId)
-			throws DiscoveryException {
-		// TODO Auto-generated method stub
-	}
-	
-	public Hypervisor.HypervisorType getHypervisorType() {
-		return Hypervisor.HypervisorType.KVM;
-	}
-	
-    @Override
-	public boolean matchHypervisor(String hypervisor) {
-    	// for backwards compatibility, if not supplied, always let to try it
-    	if(hypervisor == null)
-    		return true;
-    	
-    	return Hypervisor.HypervisorType.KVM.toString().equalsIgnoreCase(hypervisor);
-    }
-
-	@Override
-    public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) {
-		StartupCommand firstCmd = cmd[0];
-		if (!(firstCmd instanceof StartupRoutingCommand)) {
-			return null;
-		}
-
-		StartupRoutingCommand ssCmd = ((StartupRoutingCommand) firstCmd);
-		if (ssCmd.getHypervisorType() != HypervisorType.KVM) {
-			return null;
-		}
-
-		/* KVM requires host are the same in cluster */
-		ClusterVO clusterVO = _clusterDao.findById(host.getClusterId());
-		List<HostVO> hostsInCluster = _resourceMgr.listAllHostsInCluster(clusterVO.getId());
-		if (!hostsInCluster.isEmpty()) {
-			HostVO oneHost = hostsInCluster.get(0);
-			_hostDao.loadDetails(oneHost);
-			String hostOsInCluster = oneHost.getDetail("Host.OS");
-			String hostOs = ssCmd.getHostDetails().get("Host.OS");
-			if (!hostOsInCluster.equalsIgnoreCase(hostOs)) {
-				throw new IllegalArgumentException("Can't add host: " + firstCmd.getPrivateIpAddress() + " with hostOS: " + hostOs + " into a cluster,"
-				        + "in which there are " + hostOsInCluster + " hosts added");
-			}
-		}
-		
-		_hostDao.loadDetails(host);
-		
-		return _resourceMgr.fillRoutingHostVO(host, ssCmd, HypervisorType.KVM, host.getDetails(), null);
-    }
-
-	@Override
-    public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details,
-            List<String> hostTags) {
-	    // TODO Auto-generated method stub
-	    return null;
-    }
-
-	@Override
-    public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
-        if (host.getType() != Host.Type.Routing || host.getHypervisorType() != HypervisorType.KVM) {
-            return null;
-        }
-        
-        _resourceMgr.deleteRoutingHost(host, isForced, isForceDeleteStorage);
-        try {
-            ShutdownCommand cmd = new ShutdownCommand(ShutdownCommand.DeleteHost, null);
-            _agentMgr.send(host.getId(), cmd);
-        } catch (AgentUnavailableException e) {
-            s_logger.warn("Sending ShutdownCommand failed: ", e);
-        } catch (OperationTimedoutException e) {
-            s_logger.warn("Sending ShutdownCommand failed: ", e);
-        }
-        
-        return new DeleteHostAnswer(true);
-    }
-	
-    @Override
-    public boolean stop() {
-    	_resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName());
-        return super.stop();
-    }
-    
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7a0a9231/server/src/com/cloud/resource/ResourceManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java
index 3473462..7f00da9 100755
--- a/server/src/com/cloud/resource/ResourceManagerImpl.java
+++ b/server/src/com/cloud/resource/ResourceManagerImpl.java
@@ -98,7 +98,7 @@ import com.cloud.host.dao.HostDetailsDao;
 import com.cloud.host.dao.HostTagsDao;
 import com.cloud.hypervisor.Hypervisor;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
-import com.cloud.hypervisor.kvm.resource.KvmDummyResourceBase;
+import com.cloud.hypervisor.kvm.discover.KvmDummyResourceBase;
 import com.cloud.network.IPAddressVO;
 import com.cloud.network.dao.IPAddressDao;
 import com.cloud.org.Cluster;