com.eucalyptus.storage.DASManager.java Source code

Java tutorial

Introduction

Here is the source code for com.eucalyptus.storage.DASManager.java

Source

/*******************************************************************************
 *Copyright (c) 2009  Eucalyptus Systems, Inc.
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, only version 3 of the License.
 * 
 * 
 *  This file is distributed in the hope that it will be useful, but WITHOUT
 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 *  for more details.
 * 
 *  You should have received a copy of the GNU General Public License along
 *  with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 *  Please contact Eucalyptus Systems, Inc., 130 Castilian
 *  Dr., Goleta, CA 93101 USA or visit <http://www.eucalyptus.com/licenses/>
 *  if you need additional information or have any questions.
 * 
 *  This file may incorporate work covered under the following copyright and
 *  permission notice:
 * 
 *    Software License Agreement (BSD License)
 * 
 *    Copyright (c) 2008, Regents of the University of California
 *    All rights reserved.
 * 
 *    Redistribution and use of this software in source and binary forms, with
 *    or without modification, are permitted provided that the following
 *    conditions are met:
 * 
 *      Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 * 
 *      Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 * 
 *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 *    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 *    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 *    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 *    OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 *    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 *    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF
 *    THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE
 *    LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS
 *    SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
 *    IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA
 *    BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN
 *    THE REGENTS' DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT
 *    OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR
 *    WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH
 *    ANY SUCH LICENSES OR RIGHTS.
 *******************************************************************************/
/*
 *
 * Author: Neil Soman neil@eucalyptus.com
 */

package com.eucalyptus.storage;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.crypto.Cipher;
import javax.persistence.EntityNotFoundException;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.bouncycastle.util.encoders.Base64;

import com.eucalyptus.auth.util.Hashes;
import com.eucalyptus.auth.util.X509CertHelper;
import com.eucalyptus.component.Partitions;
import com.eucalyptus.component.ServiceConfiguration;
import com.eucalyptus.component.ServiceConfigurations;
import com.eucalyptus.component.id.ClusterController;
import com.eucalyptus.configurable.ConfigurableClass;
import com.eucalyptus.configurable.ConfigurableProperty;
import com.eucalyptus.configurable.PropertyDirectory;
import com.eucalyptus.entities.EntityWrapper;
import com.eucalyptus.storage.StorageManagers.StorageManagerProperty;
import com.eucalyptus.system.BaseDirectory;
import com.eucalyptus.util.EucalyptusCloudException;
import com.eucalyptus.util.StorageProperties;
import com.eucalyptus.util.WalrusProperties;

import edu.ucsb.eucalyptus.cloud.entities.AOEVolumeInfo;
import edu.ucsb.eucalyptus.cloud.entities.DASInfo;
import edu.ucsb.eucalyptus.cloud.entities.DirectStorageInfo;
import edu.ucsb.eucalyptus.cloud.entities.ISCSIVolumeInfo;
import edu.ucsb.eucalyptus.cloud.entities.LVMVolumeInfo;
import edu.ucsb.eucalyptus.cloud.entities.StorageInfo;
import edu.ucsb.eucalyptus.msgs.ComponentProperty;
import edu.ucsb.eucalyptus.util.SystemUtil;
import edu.ucsb.eucalyptus.util.SystemUtil.CommandOutput;

@StorageManagerProperty("das")
public class DASManager implements LogicalStorageManager {

    public static final String lvmRootDirectory = "/dev";
    public static final String PATH_SEPARATOR = "/";
    public static boolean initialized = false;
    public static final int MAX_LOOP_DEVICES = 256;
    public static final String EUCA_ROOT_WRAPPER = BaseDirectory.LIBEXEC.toString() + "/euca_rootwrap";
    public static final String EUCA_VAR_RUN_PATH = System.getProperty("euca.run.dir");
    private static Logger LOG = Logger.getLogger(DASManager.class);
    public static StorageExportManager exportManager;
    private static String volumeGroup;

    public void checkPreconditions() throws EucalyptusCloudException {
        //check if binaries exist, commands can be executed, etc.
        if (!new File(EUCA_ROOT_WRAPPER).exists()) {
            throw new EucalyptusCloudException(
                    "root wrapper (euca_rootwrap) does not exist in " + EUCA_ROOT_WRAPPER);
        }
        File varDir = new File(EUCA_VAR_RUN_PATH);
        if (!varDir.exists()) {
            varDir.mkdirs();
        }
        try {
            String returnValue = getLvmVersion();
            if (returnValue.length() == 0) {
                throw new EucalyptusCloudException("Is lvm installed?");
            } else {
                LOG.info(returnValue);
            }
            if (System.getProperty("euca.disable.iscsi") != null) {
                exportManager = new AOEManager();
            } else {
                exportManager = new ISCSIManager();
            }
            exportManager.checkPreconditions();
        } catch (EucalyptusCloudException ex) {
            String error = "Unable to run command: " + ex.getMessage();
            LOG.error(error);
            throw new EucalyptusCloudException(error);
        }
    }

    private void updateVolumeGroup() throws EucalyptusCloudException {
        if (volumeGroup == null) {
            String dasDevice = DASInfo.getStorageInfo().getDASDevice();
            if (dasDevice != null) {
                try {
                    boolean volumeGroupFound = false;
                    String returnValue = null;
                    try {
                        returnValue = getVolumeGroup(dasDevice);
                        if (returnValue.length() > 0) {
                            volumeGroupFound = true;
                        }
                    } catch (EucalyptusCloudException e) {
                        LOG.warn(e);
                    }
                    if (volumeGroupFound) {
                        Pattern volumeGroupPattern = Pattern.compile("(?s:.*VG Name)(.*)\n.*");
                        Matcher m = volumeGroupPattern.matcher(returnValue);
                        if (m.find())
                            volumeGroup = m.group(1).trim();
                        else
                            throw new EucalyptusCloudException("Not a volume group: " + dasDevice);
                    } else {
                        boolean physicalVolumeGroupFound = false;
                        try {
                            returnValue = getPhysicalVolume(dasDevice);
                            if (returnValue.matches("(?s:.*)PV Name.*" + dasDevice + "(?s:.*)")) {
                                physicalVolumeGroupFound = true;
                            }
                        } catch (EucalyptusCloudException e) {
                            LOG.warn(e);
                        }
                        if (!physicalVolumeGroupFound) {
                            returnValue = createPhysicalVolume(dasDevice);
                            if (returnValue.length() == 0) {
                                throw new EucalyptusCloudException(
                                        "Unable to create physical volume on device: " + dasDevice);
                            }
                        }
                        //PV should be initialized at this point.
                        returnValue = getPhysicalVolumeVerbose(dasDevice);
                        if (returnValue.matches("(?s:.*)PV Name.*" + dasDevice + "(?s:.*)")) {
                            Pattern volumeGroupPattern = Pattern.compile("(?s:.*VG Name)(.*)\n.*");
                            Matcher m = volumeGroupPattern.matcher(returnValue);
                            if (m.find()) {
                                volumeGroup = m.group(1).trim();
                            }
                            if ((volumeGroup == null) || (volumeGroup.length() == 0)) {
                                volumeGroup = "vg-" + Hashes.getRandom(10);
                                returnValue = createVolumeGroup(dasDevice, volumeGroup);
                                if (returnValue.length() == 0) {
                                    throw new EucalyptusCloudException("Unable to create volume group: "
                                            + volumeGroup + " physical volume: " + dasDevice);
                                }
                            }
                        } else {
                            Pattern volumeGroupPattern = Pattern.compile("(?s:.*VG Name)(.*)\n.*");
                            Matcher m = volumeGroupPattern.matcher(returnValue);
                            if (m.find())
                                volumeGroup = m.group(1).trim();
                            else
                                throw new EucalyptusCloudException(
                                        "Unable to get volume group for physical volume: " + dasDevice);
                        }
                    }
                } catch (EucalyptusCloudException e) {
                    LOG.error(e);
                    throw new EucalyptusCloudException(e);
                }
            } else {
                throw new EucalyptusCloudException("DAS partition not yet configured. Please specify partition.");
            }
        }
    }

    private String getLvmVersion() throws EucalyptusCloudException {
        return SystemUtil.run(new String[] { EUCA_ROOT_WRAPPER, "lvm", "version" });
    }

    private String createPhysicalVolume(String loDevName) throws EucalyptusCloudException {
        return SystemUtil.run(new String[] { EUCA_ROOT_WRAPPER, "pvcreate", loDevName });
    }

    private String getPhysicalVolume(String partition) throws EucalyptusCloudException {
        return SystemUtil.run(new String[] { EUCA_ROOT_WRAPPER, "pvdisplay", partition });
    }

    private String getVolumeGroup(String volumeGroup) throws EucalyptusCloudException {
        return SystemUtil.run(new String[] { EUCA_ROOT_WRAPPER, "vgdisplay", volumeGroup });
    }

    private String createVolumeGroup(String pvName, String vgName) throws EucalyptusCloudException {
        return SystemUtil.run(new String[] { EUCA_ROOT_WRAPPER, "vgcreate", vgName, pvName });
    }

    private String getPhysicalVolumeVerbose(String pvName) throws EucalyptusCloudException {
        return SystemUtil.run(new String[] { EUCA_ROOT_WRAPPER, "pvdisplay", "-v", pvName });
    }

    private String createLogicalVolume(String vgName, String lvName, long size) throws EucalyptusCloudException {
        // return SystemUtil.run(new String[]{EUCA_ROOT_WRAPPER, "lvcreate", "-n", lvName, "-L", String.valueOf(size) + "G", vgName});
        return SystemUtil.run(new String[] { EUCA_ROOT_WRAPPER, "lvcreate", "-n", lvName, "-L",
                String.valueOf(size) + "M", vgName });
    }

    private String createSnapshotLogicalVolume(String lvName, String snapLvName, long size)
            throws EucalyptusCloudException {
        // return SystemUtil.run(new String[]{EUCA_ROOT_WRAPPER, "lvcreate", "-n", snapLvName, "-s", "-L", String.valueOf(size) + "G", lvName});
        return SystemUtil.run(new String[] { EUCA_ROOT_WRAPPER, "lvcreate", "-n", snapLvName, "-s", "-L",
                String.valueOf(size) + "M", lvName });
    }

    private String removeLogicalVolume(String lvName) throws EucalyptusCloudException {
        return SystemUtil.run(new String[] { EUCA_ROOT_WRAPPER, "lvremove", "-f", lvName });
    }

    private String enableLogicalVolume(String lvName) throws EucalyptusCloudException {
        return SystemUtil.run(new String[] { EUCA_ROOT_WRAPPER, "lvchange", "-ay", lvName });
    }

    private String duplicateLogicalVolume(String oldLvName, String newLvName) throws EucalyptusCloudException {
        return SystemUtil.run(new String[] { EUCA_ROOT_WRAPPER, "dd", "if=" + oldLvName, "of=" + newLvName,
                "bs=" + StorageProperties.blockSize });
    }

    private String createFile(String fileName, long size) throws EucalyptusCloudException {
        if (!DirectStorageInfo.getStorageInfo().getZeroFillVolumes())
            return SystemUtil.run(new String[] { EUCA_ROOT_WRAPPER, "dd", "if=/dev/zero", "of=" + fileName,
                    "count=1", "bs=" + StorageProperties.blockSize, "seek=" + (size - 1) });
        else
            return SystemUtil.run(new String[] { EUCA_ROOT_WRAPPER, "dd", "if=/dev/zero", "of=" + fileName,
                    "count=" + size, "bs=" + StorageProperties.blockSize });
    }

    private String createEmptyFile(String fileName, int size) throws EucalyptusCloudException {
        long fileSize = size * 1024;
        return createFile(fileName, fileSize);
    }

    public String createAbsoluteEmptyFile(String fileName, long size) throws EucalyptusCloudException {
        size = size / WalrusProperties.M;
        return createFile(fileName, size);
    }

    public void initialize() {
        if (!initialized) {
            System.loadLibrary("dascontrol");
            registerSignals();
            initialized = true;
        }
    }

    public void configure() {
        exportManager.configure();
        //dummy init
        LOG.info(StorageInfo.getStorageInfo().getName());
        LOG.info(DirectStorageInfo.getStorageInfo().getName());
        LOG.info(DASInfo.getStorageInfo().getName());
    }

    public void startupChecks() {
        reload();
    }

    public void cleanVolume(String volumeId) {
        try {
            updateVolumeGroup();
        } catch (EucalyptusCloudException e) {
            LOG.error(e);
            return;
        }
        VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
        LVMVolumeInfo lvmVolInfo = volumeManager.getVolumeInfo(volumeId);
        if (lvmVolInfo != null) {
            volumeManager.unexportVolume(lvmVolInfo);
            String lvName = lvmVolInfo.getLvName();
            String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + volumeGroup + PATH_SEPARATOR + lvName;
            try {
                String returnValue = removeLogicalVolume(absoluteLVName);
            } catch (EucalyptusCloudException ex) {
                volumeManager.abort();
                String error = "Unable to run command: " + ex.getMessage();
                LOG.error(error);
            }
            volumeManager.remove(lvmVolInfo);
            volumeManager.finish();
        }
    }

    public void cleanSnapshot(String snapshotId) {
        try {
            updateVolumeGroup();
        } catch (EucalyptusCloudException e) {
            LOG.error(e);
            return;
        }
        VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
        LVMVolumeInfo lvmVolInfo = volumeManager.getVolumeInfo(snapshotId);
        if (lvmVolInfo != null) {
            volumeManager.remove(lvmVolInfo);
        }
        volumeManager.finish();
    }

    public native void registerSignals();

    public void dupFile(String oldFileName, String newFileName) {
        FileOutputStream fileOutputStream = null;
        FileChannel out = null;
        FileInputStream fileInputStream = null;
        FileChannel in = null;
        try {
            fileOutputStream = new FileOutputStream(new File(newFileName));
            out = fileOutputStream.getChannel();
            fileInputStream = new FileInputStream(new File(oldFileName));
            in = fileInputStream.getChannel();
            in.transferTo(0, in.size(), out);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (fileOutputStream != null) {
                try {
                    out.close();
                    fileOutputStream.close();
                } catch (IOException e) {
                    LOG.error(e);
                }
            }
            if (fileInputStream != null) {
                try {
                    in.close();
                    fileInputStream.close();
                } catch (IOException e) {
                    LOG.error(e);
                }
            }
        }
    }

    //creates a logical volume (and a new physical volume and volume group)
    public void createLogicalVolume(String lvName, long size) throws EucalyptusCloudException {
        if (volumeGroup != null) {
            String returnValue = createLogicalVolume(volumeGroup, lvName, size);
            if (returnValue.length() == 0) {
                throw new EucalyptusCloudException(
                        "Unable to create logical volume " + lvName + " in volume group " + volumeGroup);
            }
        } else {
            throw new EucalyptusCloudException("Volume group is null! This should never happen");
        }
    }

    public void createVolume(String volumeId, int size) throws EucalyptusCloudException {
        updateVolumeGroup();
        File volumeDir = new File(DirectStorageInfo.getStorageInfo().getVolumesDir());
        volumeDir.mkdirs();
        VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();

        String lvName = "lv-" + Hashes.getRandom(4);
        LVMVolumeInfo lvmVolumeInfo = null;
        if (exportManager instanceof AOEManager) {
            lvmVolumeInfo = new AOEVolumeInfo();
        } else {
            lvmVolumeInfo = new ISCSIVolumeInfo();
        }
        volumeManager.finish();
        //create file and attach to loopback device
        try {
            //create logical volume
            createLogicalVolume(lvName, (size * StorageProperties.KB));
            //export logical volume
            try {
                volumeManager.exportVolume(lvmVolumeInfo, volumeGroup, lvName);
            } catch (EucalyptusCloudException ex) {
                LOG.error(ex);
                String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + volumeGroup + PATH_SEPARATOR + lvName;
                String returnValue = removeLogicalVolume(absoluteLVName);
                throw ex;
            }
            lvmVolumeInfo.setVolumeId(volumeId);
            lvmVolumeInfo.setLvName(lvName);
            lvmVolumeInfo.setStatus(StorageProperties.Status.available.toString());
            lvmVolumeInfo.setSize(size);
            volumeManager = new VolumeEntityWrapperManager();
            volumeManager.add(lvmVolumeInfo);
            volumeManager.finish();
        } catch (EucalyptusCloudException ex) {
            String error = "Unable to run command: " + ex.getMessage();
            volumeManager.abort();
            LOG.error(error);
            throw new EucalyptusCloudException(error);
        }
    }

    public int createVolume(String volumeId, String snapshotId, int size) throws EucalyptusCloudException {
        updateVolumeGroup();
        VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
        LVMVolumeInfo foundSnapshotInfo = volumeManager.getVolumeInfo(snapshotId);
        if (foundSnapshotInfo != null) {
            String status = foundSnapshotInfo.getStatus();
            if (status.equals(StorageProperties.Status.available.toString())) {
                String lvName = "lv-" + Hashes.getRandom(4);
                LVMVolumeInfo lvmVolumeInfo = volumeManager.getVolumeInfo();
                String snapId = foundSnapshotInfo.getVolumeId();
                String loFileName = foundSnapshotInfo.getLoFileName();
                volumeManager.finish();
                try {
                    File snapshotFile = new File(
                            DirectStorageInfo.getStorageInfo().getVolumesDir() + PATH_SEPARATOR + snapId);
                    assert (snapshotFile.exists());
                    long absoluteSize;
                    if (size <= 0 || size == foundSnapshotInfo.getSize()) {
                        // size = (int)(snapshotFile.length() / StorageProperties.GB);
                        absoluteSize = snapshotFile.length() / StorageProperties.MB;
                        size = (int) (absoluteSize / StorageProperties.KB);
                    } else {
                        absoluteSize = size * StorageProperties.KB;
                    }
                    //create physical volume, volume group and logical volume
                    createLogicalVolume(lvName, absoluteSize);
                    //duplicate snapshot volume
                    String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + volumeGroup + PATH_SEPARATOR
                            + lvName;
                    duplicateLogicalVolume(loFileName, absoluteLVName);
                    //export logical volume
                    try {
                        volumeManager.exportVolume(lvmVolumeInfo, volumeGroup, lvName);
                    } catch (EucalyptusCloudException ex) {
                        String returnValue = removeLogicalVolume(absoluteLVName);
                        throw ex;
                    }
                    lvmVolumeInfo.setVolumeId(volumeId);
                    lvmVolumeInfo.setLvName(lvName);
                    lvmVolumeInfo.setStatus(StorageProperties.Status.available.toString());
                    lvmVolumeInfo.setSize(size);
                    volumeManager = new VolumeEntityWrapperManager();
                    volumeManager.add(lvmVolumeInfo);
                    volumeManager.finish();
                } catch (EucalyptusCloudException ex) {
                    volumeManager.abort();
                    String error = "Unable to run command: " + ex.getMessage();
                    LOG.error(error);
                    throw new EucalyptusCloudException(error);
                }
            }
        } else {
            volumeManager.abort();
            throw new EucalyptusCloudException("Unable to find snapshot: " + snapshotId);
        }
        return size;
    }

    public void cloneVolume(String volumeId, String parentVolumeId) throws EucalyptusCloudException {
        updateVolumeGroup();
        VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
        LVMVolumeInfo foundVolumeInfo = volumeManager.getVolumeInfo(parentVolumeId);
        if (foundVolumeInfo != null) {
            String status = foundVolumeInfo.getStatus();
            String lvName = "lv-" + Hashes.getRandom(4);
            LVMVolumeInfo lvmVolumeInfo = volumeManager.getVolumeInfo();
            String parentLvName = foundVolumeInfo.getLvName();
            int size = foundVolumeInfo.getSize();
            volumeManager.finish();
            try {
                File parentVolumeFile = new File(
                        DirectStorageInfo.getStorageInfo().getVolumesDir() + PATH_SEPARATOR + parentVolumeId);
                assert (parentVolumeFile.exists());
                long absouluteSize = (parentVolumeFile.length() / StorageProperties.MB);
                //create physical volume, volume group and logical volume
                createLogicalVolume(lvName, absouluteSize);
                //duplicate snapshot volume
                String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + volumeGroup + PATH_SEPARATOR + lvName;
                String absoluteParentLVName = lvmRootDirectory + PATH_SEPARATOR + volumeGroup + PATH_SEPARATOR
                        + parentLvName;
                duplicateLogicalVolume(absoluteParentLVName, absoluteLVName);
                //export logical volume
                try {
                    volumeManager.exportVolume(lvmVolumeInfo, volumeGroup, lvName);
                } catch (EucalyptusCloudException ex) {
                    String returnValue = removeLogicalVolume(absoluteLVName);
                    throw ex;
                }
                lvmVolumeInfo.setVolumeId(volumeId);
                lvmVolumeInfo.setLvName(lvName);
                lvmVolumeInfo.setStatus(StorageProperties.Status.available.toString());
                lvmVolumeInfo.setSize(size);
                volumeManager = new VolumeEntityWrapperManager();
                volumeManager.add(lvmVolumeInfo);
                volumeManager.finish();
            } catch (EucalyptusCloudException ex) {
                volumeManager.abort();
                String error = "Unable to run command: " + ex.getMessage();
                LOG.error(error);
                throw new EucalyptusCloudException(error);
            }
        } else {
            volumeManager.abort();
            throw new EucalyptusCloudException("Unable to find volume: " + parentVolumeId);
        }
    }

    public void addSnapshot(String snapshotId) throws EucalyptusCloudException {
        String snapshotRawFileName = DirectStorageInfo.getStorageInfo().getVolumesDir() + "/" + snapshotId;
        File snapshotFile = new File(snapshotRawFileName);
        if (snapshotFile.exists()) {
            VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
            LVMVolumeInfo lvmVolumeInfo = volumeManager.getVolumeInfo();
            lvmVolumeInfo.setVolumeId(snapshotId);
            lvmVolumeInfo.setLoFileName(snapshotRawFileName);
            lvmVolumeInfo.setStatus(StorageProperties.Status.available.toString());
            lvmVolumeInfo.setSize((int) (snapshotFile.length() / StorageProperties.GB));
            volumeManager.add(lvmVolumeInfo);
            volumeManager.finish();
        } else {
            throw new EucalyptusCloudException("Snapshot backing file does not exist for: " + snapshotId);
        }
    }

    public void deleteVolume(String volumeId) throws EucalyptusCloudException {
        updateVolumeGroup();
        VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
        LVMVolumeInfo foundLVMVolumeInfo = volumeManager.getVolumeInfo(volumeId);
        if (foundLVMVolumeInfo != null) {
            //remove aoe export
            String lvName = foundLVMVolumeInfo.getLvName();
            String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + volumeGroup + PATH_SEPARATOR + lvName;
            volumeManager.unexportVolume(foundLVMVolumeInfo);
            try {
                String returnValue = "";
                for (int i = 0; i < 5; ++i) {
                    returnValue = removeLogicalVolume(absoluteLVName);
                    if (returnValue.length() != 0) {
                        if (returnValue.contains("successfully removed")) {
                            break;
                        }
                    }
                    //retry lv deletion (can take a while).
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        LOG.error(e);
                        break;
                    }
                }
                if (returnValue.length() == 0) {
                    throw new EucalyptusCloudException("Unable to remove logical volume " + absoluteLVName);
                }
                volumeManager.remove(foundLVMVolumeInfo);
                volumeManager.finish();
            } catch (EucalyptusCloudException ex) {
                volumeManager.abort();
                String error = "Unable to run command: " + ex.getMessage();
                LOG.error(error);
                throw new EucalyptusCloudException(error);
            }
        } else {
            volumeManager.abort();
            throw new EucalyptusCloudException("Unable to find volume: " + volumeId);
        }
    }

    public List<String> createSnapshot(String volumeId, String snapshotId, Boolean shouldTransferSnapshot)
            throws EucalyptusCloudException {
        updateVolumeGroup();
        VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
        LVMVolumeInfo foundLVMVolumeInfo = volumeManager.getVolumeInfo(volumeId);
        ArrayList<String> returnValues = new ArrayList<String>();
        if (foundLVMVolumeInfo != null) {
            LVMVolumeInfo snapshotInfo = volumeManager.getVolumeInfo();
            snapshotInfo.setVolumeId(snapshotId);
            File snapshotDir = new File(DirectStorageInfo.getStorageInfo().getVolumesDir());
            snapshotDir.mkdirs();

            String lvName = "lv-snap-" + Hashes.getRandom(4);
            String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + volumeGroup + PATH_SEPARATOR
                    + foundLVMVolumeInfo.getLvName();

            int size = foundLVMVolumeInfo.getSize();
            volumeManager.finish();
            volumeManager = null;
            try {
                long absoluteSize;
                CommandOutput result = SystemUtil.runWithRawOutput(
                        new String[] { EUCA_ROOT_WRAPPER, "blockdev", "--getsize64", absoluteLVName });
                if (null != result && result.returnValue == 0
                        && StringUtils.isNotBlank(StringUtils.trim(result.output))) {
                    try {
                        absoluteSize = (Long.parseLong(StringUtils.trim(result.output)) / StorageProperties.MB);
                    } catch (NumberFormatException e) {
                        LOG.debug("Failed to parse size of volume " + volumeId, e);
                        absoluteSize = size * StorageProperties.KB;
                    }
                } else {
                    absoluteSize = size * StorageProperties.KB;
                }

                //create physical volume, volume group and logical volume
                // String returnValue = createSnapshotLogicalVolume(absoluteLVName, lvName, size);
                String returnValue = createSnapshotLogicalVolume(absoluteLVName, lvName, absoluteSize);
                if (returnValue.length() == 0) {
                    throw new EucalyptusCloudException(
                            "Unable to create snapshot logical volume " + lvName + " for volume " + lvName);
                }
                String snapRawFileName = DirectStorageInfo.getStorageInfo().getVolumesDir() + "/" + snapshotId;
                String absoluteSnapLVName = lvmRootDirectory + PATH_SEPARATOR + volumeGroup + PATH_SEPARATOR
                        + lvName;

                duplicateLogicalVolume(absoluteSnapLVName, snapRawFileName);

                returnValue = removeLogicalVolume(absoluteSnapLVName);
                if (returnValue.length() == 0) {
                    throw new EucalyptusCloudException("Unable to remove logical volume " + absoluteSnapLVName);
                }
                snapshotInfo.setLoFileName(snapRawFileName);
                // snapshotInfo.setStatus(StorageProperties.Status.available.toString());
                snapshotInfo.setSize(size);
                volumeManager = new VolumeEntityWrapperManager();
                volumeManager.add(snapshotInfo);
                returnValues.add(snapRawFileName);
                returnValues.add(String.valueOf(size * WalrusProperties.G));
                // } catch(EucalyptusCloudException ex) {
            } catch (Exception ex) {
                if (volumeManager != null)
                    volumeManager.abort();
                String error = "Unable to run command: " + ex.getMessage();
                LOG.error(error);
                throw new EucalyptusCloudException(error);
            }

        }
        volumeManager.finish();
        return returnValues;
    }

    public List<String> prepareForTransfer(String snapshotId) throws EucalyptusCloudException {
        VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
        LVMVolumeInfo foundLVMVolumeInfo = volumeManager.getVolumeInfo(snapshotId);
        ArrayList<String> returnValues = new ArrayList<String>();

        if (foundLVMVolumeInfo != null) {
            returnValues.add(DirectStorageInfo.getStorageInfo().getVolumesDir() + PATH_SEPARATOR
                    + foundLVMVolumeInfo.getVolumeId());
            volumeManager.finish();
        } else {
            volumeManager.abort();
            throw new EucalyptusCloudException("Unable to find snapshot: " + snapshotId);
        }
        return returnValues;
    }

    public void deleteSnapshot(String snapshotId) throws EucalyptusCloudException {
        updateVolumeGroup();
        VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
        LVMVolumeInfo foundLVMVolumeInfo = volumeManager.getVolumeInfo(snapshotId);

        if (foundLVMVolumeInfo != null) {
            volumeManager.remove(foundLVMVolumeInfo);
            File snapFile = new File(DirectStorageInfo.getStorageInfo().getVolumesDir() + File.separator
                    + foundLVMVolumeInfo.getVolumeId());
            volumeManager.finish();
            if (snapFile.exists()) {
                if (!snapFile.delete()) {
                    throw new EucalyptusCloudException("Unable to delete: " + snapFile.getAbsolutePath());
                }
            }
        } else {
            volumeManager.abort();
            throw new EucalyptusCloudException("Unable to find snapshot: " + snapshotId);
        }
    }

    public String getVolumeProperty(String volumeId) throws EucalyptusCloudException {
        VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
        String returnValue = volumeManager.getVolumeProperty(volumeId);
        volumeManager.finish();
        return returnValue;
    }

    public void reload() {
        VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
        List<LVMVolumeInfo> volumeInfos = volumeManager.getAllVolumeInfos();
        //now enable them
        for (LVMVolumeInfo foundVolumeInfo : volumeInfos) {
            try {
                if (foundVolumeInfo.getVgName() != null) {
                    volumeManager.exportVolume(foundVolumeInfo);
                }
            } catch (EucalyptusCloudException ex) {
                LOG.error("Unable to reload volume: " + foundVolumeInfo.getVolumeId() + ex);
            }
        }
        volumeManager.finish();
    }

    public int getSnapshotSize(String snapshotId) throws EucalyptusCloudException {
        VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
        LVMVolumeInfo lvmVolumeInfo = volumeManager.getVolumeInfo(snapshotId);
        if (lvmVolumeInfo != null) {
            int snapSize = lvmVolumeInfo.getSize();
            volumeManager.finish();
            return snapSize;
        } else {
            volumeManager.abort();
            return 0;
        }
    }

    private String aoeStatus(int pid) {
        File file = new File("/proc/" + pid + "/cmdline");
        String returnString = "";
        if (file.exists()) {
            FileInputStream fileIn = null;
            try {
                fileIn = new FileInputStream(file);
                byte[] bytes = new byte[512];
                int bytesRead;
                while ((bytesRead = fileIn.read(bytes)) > 0) {
                    returnString += new String(bytes, 0, bytesRead);
                }
            } catch (Exception ex) {
                LOG.warn("could not find " + file.getAbsolutePath());
            } finally {
                if (fileIn != null)
                    try {
                        fileIn.close();
                    } catch (IOException e) {
                        LOG.error(e);
                    }
            }
        }
        return returnString;
    }

    private class VolumeEntityWrapperManager {
        private EntityWrapper entityWrapper;

        private VolumeEntityWrapperManager() {
            entityWrapper = StorageProperties.getEntityWrapper();
        }

        public List<String> getSnapshotValues(String snapshotId) {
            ArrayList<String> returnValues = new ArrayList<String>();
            LVMVolumeInfo lvmVolumeInfo = getVolumeInfo(snapshotId);
            if (lvmVolumeInfo instanceof AOEVolumeInfo) {
                returnValues.add(volumeGroup);
                returnValues.add(lvmVolumeInfo.getLvName());
            }
            return returnValues;
        }

        public void exportVolume(LVMVolumeInfo lvmVolumeInfo) throws EucalyptusCloudException {
            if (exportManager instanceof AOEManager) {
                AOEVolumeInfo aoeVolumeInfo = (AOEVolumeInfo) lvmVolumeInfo;

                int pid = aoeVolumeInfo.getVbladePid();
                if (pid > 0) {
                    //enable logical volumes
                    String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + volumeGroup + PATH_SEPARATOR
                            + aoeVolumeInfo.getLvName();
                    try {
                        enableLogicalVolume(absoluteLVName);
                    } catch (EucalyptusCloudException ex) {
                        String error = "Unable to run command: " + ex.getMessage();
                        LOG.error(error);
                        throw new EucalyptusCloudException(ex);
                    }
                    String returnValue = aoeStatus(pid);
                    if (returnValue.length() == 0) {
                        int majorNumber = aoeVolumeInfo.getMajorNumber();
                        int minorNumber = aoeVolumeInfo.getMinorNumber();
                        pid = exportManager.exportVolume(DirectStorageInfo.getStorageInfo().getStorageInterface(),
                                absoluteLVName, majorNumber, minorNumber);
                        aoeVolumeInfo.setVbladePid(pid);
                        File vbladePidFile = new File(
                                EUCA_VAR_RUN_PATH + "/vblade-" + majorNumber + minorNumber + ".pid");
                        FileOutputStream fileOutStream = null;
                        try {
                            fileOutStream = new FileOutputStream(vbladePidFile);
                            String pidString = String.valueOf(pid);
                            fileOutStream.write(pidString.getBytes());
                            fileOutStream.close();
                        } catch (Exception ex) {
                            if (fileOutStream != null)
                                try {
                                    fileOutStream.close();
                                } catch (IOException e) {
                                    LOG.error(e);
                                }
                            LOG.error("Could not write pid file vblade-" + majorNumber + minorNumber + ".pid");
                        }
                    }
                }
            } else if (exportManager instanceof ISCSIManager) {
                ISCSIVolumeInfo iscsiVolumeInfo = (ISCSIVolumeInfo) lvmVolumeInfo;
                String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + volumeGroup + PATH_SEPARATOR
                        + iscsiVolumeInfo.getLvName();
                try {
                    enableLogicalVolume(absoluteLVName);
                } catch (EucalyptusCloudException ex) {
                    String error = "Unable to run command: " + ex.getMessage();
                    LOG.error(error);
                    throw new EucalyptusCloudException(ex);
                }
                ((ISCSIManager) exportManager).exportTarget(iscsiVolumeInfo.getTid(),
                        iscsiVolumeInfo.getStoreName(), iscsiVolumeInfo.getLun(), absoluteLVName,
                        iscsiVolumeInfo.getStoreUser());
            }
        }

        public String getVolumeProperty(String volumeId) {
            LVMVolumeInfo lvmVolumeInfo = getVolumeInfo(volumeId);
            if (lvmVolumeInfo != null) {
                if (exportManager instanceof AOEManager) {
                    AOEVolumeInfo aoeVolumeInfo = (AOEVolumeInfo) lvmVolumeInfo;
                    return StorageProperties.ETHERD_PREFIX + aoeVolumeInfo.getMajorNumber() + "."
                            + aoeVolumeInfo.getMinorNumber();
                } else if (exportManager instanceof ISCSIManager) {
                    ISCSIVolumeInfo iscsiVolumeInfo = (ISCSIVolumeInfo) lvmVolumeInfo;
                    String storeName = iscsiVolumeInfo.getStoreName();
                    String encryptedPassword;
                    try {
                        encryptedPassword = ((ISCSIManager) exportManager).getEncryptedPassword();
                    } catch (EucalyptusCloudException e) {
                        LOG.error(e);
                        return null;
                    }
                    return ",,," + encryptedPassword + ",," + StorageProperties.STORAGE_HOST + "," + storeName;
                }
            }
            return null;
        }

        public void unexportVolume(LVMVolumeInfo volumeInfo) {
            if (volumeInfo instanceof AOEVolumeInfo) {
                AOEVolumeInfo aoeVolumeInfo = (AOEVolumeInfo) volumeInfo;
                int pid = aoeVolumeInfo.getVbladePid();
                if (pid > 0) {
                    String returnValue = aoeStatus(pid);
                    if (returnValue.length() > 0) {
                        exportManager.unexportVolume(pid);
                        int majorNumber = aoeVolumeInfo.getMajorNumber();
                        int minorNumber = aoeVolumeInfo.getMinorNumber();
                        File vbladePidFile = new File(
                                EUCA_VAR_RUN_PATH + "/vblade-" + majorNumber + minorNumber + ".pid");
                        if (vbladePidFile.exists()) {
                            vbladePidFile.delete();
                        }
                    }
                }
            } else if (volumeInfo instanceof ISCSIVolumeInfo) {
                ISCSIVolumeInfo iscsiVolumeInfo = (ISCSIVolumeInfo) volumeInfo;
                ((ISCSIManager) exportManager).unexportTarget(iscsiVolumeInfo.getTid(), iscsiVolumeInfo.getLun());
            }
        }

        private void finish() {
            entityWrapper.commit();
        }

        private void abort() {
            entityWrapper.rollback();
        }

        private LVMVolumeInfo getVolumeInfo(String volumeId) {
            if (exportManager instanceof AOEManager) {
                AOEVolumeInfo AOEVolumeInfo = new AOEVolumeInfo(volumeId);
                List<AOEVolumeInfo> AOEVolumeInfos = entityWrapper.query(AOEVolumeInfo);
                if (AOEVolumeInfos.size() > 0) {
                    return AOEVolumeInfos.get(0);
                }
            } else if (exportManager instanceof ISCSIManager) {
                ISCSIVolumeInfo ISCSIVolumeInfo = new ISCSIVolumeInfo(volumeId);
                List<ISCSIVolumeInfo> ISCSIVolumeInfos = entityWrapper.query(ISCSIVolumeInfo);
                if (ISCSIVolumeInfos.size() > 0) {
                    return ISCSIVolumeInfos.get(0);
                }
            }
            return null;
        }

        private LVMVolumeInfo getVolumeInfo() {
            if (exportManager instanceof AOEManager) {
                AOEVolumeInfo aoeVolumeInfo = new AOEVolumeInfo();
                aoeVolumeInfo.setVbladePid(-1);
                aoeVolumeInfo.setMajorNumber(-1);
                aoeVolumeInfo.setMinorNumber(-1);
                return aoeVolumeInfo;
            } else if (exportManager instanceof ISCSIManager) {
                return new ISCSIVolumeInfo();
            }
            return null;
        }

        private List<LVMVolumeInfo> getAllVolumeInfos() {
            if (exportManager instanceof AOEManager) {
                AOEVolumeInfo AOEVolumeInfo = new AOEVolumeInfo();
                return entityWrapper.query(AOEVolumeInfo);
            } else if (exportManager instanceof ISCSIManager) {
                ISCSIVolumeInfo ISCSIVolumeInfo = new ISCSIVolumeInfo();
                return entityWrapper.query(ISCSIVolumeInfo);
            }
            return new ArrayList<LVMVolumeInfo>();
        }

        private void add(LVMVolumeInfo volumeInfo) {
            entityWrapper.add(volumeInfo);
        }

        private void remove(LVMVolumeInfo volumeInfo) {
            entityWrapper.delete(volumeInfo);
        }

        private String encryptTargetPassword(String password) throws EucalyptusCloudException {
            try {
                List<ServiceConfiguration> partitionConfigs = ServiceConfigurations
                        .listPartition(ClusterController.class, StorageProperties.NAME);
                ServiceConfiguration clusterConfig = partitionConfigs.get(0);
                PublicKey ncPublicKey = Partitions.lookup(clusterConfig).getNodeCertificate().getPublicKey();
                Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
                cipher.init(Cipher.ENCRYPT_MODE, ncPublicKey);
                return new String(Base64.encode(cipher.doFinal(password.getBytes())));
            } catch (Exception e) {
                LOG.error("Unable to encrypt storage target password");
                throw new EucalyptusCloudException(e.getMessage(), e);
            }
        }

        private int exportVolume(LVMVolumeInfo lvmVolumeInfo, String vgName, String lvName)
                throws EucalyptusCloudException {
            if (exportManager instanceof AOEManager) {
                AOEVolumeInfo aoeVolumeInfo = (AOEVolumeInfo) lvmVolumeInfo;
                exportManager.allocateTarget(aoeVolumeInfo);
                int majorNumber = aoeVolumeInfo.getMajorNumber();
                int minorNumber = aoeVolumeInfo.getMinorNumber();
                String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + vgName + PATH_SEPARATOR + lvName;
                int pid = exportManager.exportVolume(DirectStorageInfo.getStorageInfo().getStorageInterface(),
                        absoluteLVName, majorNumber, minorNumber);
                boolean success = false;
                String returnValue = "";
                int timeout = 300;
                if (pid > 0) {
                    for (int i = 0; i < 5; ++i) {
                        returnValue = aoeStatus(pid);
                        if (returnValue.length() == 0) {
                            success = false;
                            try {
                                Thread.sleep(timeout);
                            } catch (InterruptedException ie) {
                                LOG.error(ie);
                            }
                            timeout += 300;
                        } else {
                            success = true;
                            break;
                        }
                    }
                }
                if (!success) {
                    throw new EucalyptusCloudException("Could not export AoE device " + absoluteLVName + " iface: "
                            + DirectStorageInfo.getStorageInfo().getStorageInterface() + " pid: " + pid
                            + " returnValue: " + returnValue);
                }

                File vbladePidFile = new File(EUCA_VAR_RUN_PATH + "/vblade-" + majorNumber + minorNumber + ".pid");
                FileOutputStream fileOutStream = null;
                try {
                    fileOutStream = new FileOutputStream(vbladePidFile);
                    String pidString = String.valueOf(pid);
                    fileOutStream.write(pidString.getBytes());
                } catch (Exception ex) {
                    LOG.error("Could not write pid file vblade-" + majorNumber + minorNumber + ".pid");
                } finally {
                    if (fileOutStream != null)
                        try {
                            fileOutStream.close();
                        } catch (IOException e) {
                            LOG.error(e);
                        }
                }
                if (pid < 0)
                    throw new EucalyptusCloudException("invalid vblade pid: " + pid);
                aoeVolumeInfo.setVbladePid(pid);
                return pid;
            } else if (exportManager instanceof ISCSIManager) {
                ISCSIVolumeInfo iscsiVolumeInfo = (ISCSIVolumeInfo) lvmVolumeInfo;
                exportManager.allocateTarget(iscsiVolumeInfo);
                String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + vgName + PATH_SEPARATOR + lvName;
                ((ISCSIManager) exportManager).exportTarget(iscsiVolumeInfo.getTid(),
                        iscsiVolumeInfo.getStoreName(), iscsiVolumeInfo.getLun(), absoluteLVName,
                        iscsiVolumeInfo.getStoreUser());
            }
            return 0;
        }
    }

    @Override
    public void loadSnapshots(List<String> snapshotSet, List<String> snapshotFileNames)
            throws EucalyptusCloudException {
        // TODO Auto-generated method stub

    }

    @Override
    public String prepareSnapshot(String snapshotId, int sizeExpected, long actualSizeInMB)
            throws EucalyptusCloudException {
        String deviceName = null;
        VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
        LVMVolumeInfo foundSnapshotInfo = volumeManager.getVolumeInfo(snapshotId);
        if (null == foundSnapshotInfo) {
            LVMVolumeInfo snapshotInfo = volumeManager.getVolumeInfo();
            snapshotInfo.setVolumeId(snapshotId);
            snapshotInfo.setSize(sizeExpected);
            snapshotInfo.setLoFileName(
                    DirectStorageInfo.getStorageInfo().getVolumesDir() + File.separator + snapshotId);
            deviceName = snapshotInfo.getLoFileName();
            volumeManager.add(snapshotInfo);
        }

        volumeManager.finish();
        return deviceName;
        // return DirectStorageInfo.getStorageInfo().getVolumesDir() + File.separator + snapshotId;
    }

    @Override
    public ArrayList<ComponentProperty> getStorageProps() {
        ArrayList<ComponentProperty> componentProperties = null;
        ConfigurableClass configurableClass = StorageInfo.class.getAnnotation(ConfigurableClass.class);
        if (configurableClass != null) {
            String root = configurableClass.root();
            String alias = configurableClass.alias();
            componentProperties = (ArrayList<ComponentProperty>) PropertyDirectory
                    .getComponentPropertySet(StorageProperties.NAME + "." + root, alias);
        }
        configurableClass = DirectStorageInfo.class.getAnnotation(ConfigurableClass.class);
        if (configurableClass != null) {
            String root = configurableClass.root();
            String alias = configurableClass.alias();
            if (componentProperties == null)
                componentProperties = (ArrayList<ComponentProperty>) PropertyDirectory
                        .getComponentPropertySet(StorageProperties.NAME + "." + root, alias);
            else
                componentProperties.addAll(
                        PropertyDirectory.getComponentPropertySet(StorageProperties.NAME + "." + root, alias));
        }
        configurableClass = DASInfo.class.getAnnotation(ConfigurableClass.class);
        if (configurableClass != null) {
            String root = configurableClass.root();
            String alias = configurableClass.alias();
            if (componentProperties == null)
                componentProperties = (ArrayList<ComponentProperty>) PropertyDirectory
                        .getComponentPropertySet(StorageProperties.NAME + "." + root, alias);
            else
                componentProperties.addAll(
                        PropertyDirectory.getComponentPropertySet(StorageProperties.NAME + "." + root, alias));
        }
        return componentProperties;
    }

    @Override
    public void setStorageProps(ArrayList<ComponentProperty> storageProps) {
        for (ComponentProperty prop : storageProps) {
            try {
                ConfigurableProperty entry = PropertyDirectory.getPropertyEntry(prop.getQualifiedName());
                //type parser will correctly covert the value
                entry.setValue(prop.getValue());
            } catch (IllegalAccessException e) {
                LOG.error(e, e);
            }
        }
    }

    @Override
    public String getStorageRootDirectory() {
        return DirectStorageInfo.getStorageInfo().getVolumesDir();
    }

    @Override
    public void finishVolume(String snapshotId) throws EucalyptusCloudException {
        VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
        LVMVolumeInfo foundSnapshotInfo = volumeManager.getVolumeInfo(snapshotId);
        if (null != foundSnapshotInfo) {
            foundSnapshotInfo.setStatus(StorageProperties.Status.available.toString());
        }
        volumeManager.finish();
    }

    @Override
    public String getSnapshotPath(String snapshotId) throws EucalyptusCloudException {
        VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
        LVMVolumeInfo volInfo = volumeManager.getVolumeInfo(snapshotId);
        if (volInfo != null) {
            String snapPath = volInfo.getLoFileName();
            volumeManager.finish();
            return snapPath;
        } else {
            volumeManager.abort();
            throw new EntityNotFoundException("Unable to find snapshot with id: " + snapshotId);
        }
    }

    @Override
    public String getVolumePath(String volumeId) throws EucalyptusCloudException {
        VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
        LVMVolumeInfo volInfo = volumeManager.getVolumeInfo(volumeId);
        if (volInfo != null) {
            String volumePath = lvmRootDirectory + File.separator + volInfo.getVgName() + File.separator
                    + volInfo.getLvName();
            volumeManager.finish();
            return volumePath;
        } else {
            volumeManager.abort();
            throw new EntityNotFoundException("Unable to find volume with id: " + volumeId);
        }
    }

    @Override
    public void importSnapshot(String snapshotId, String snapPath, String volumeId, int size)
            throws EucalyptusCloudException {
        VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
        LVMVolumeInfo snapInfo = volumeManager.getVolumeInfo(snapshotId);
        if (snapInfo != null) {
            volumeManager.finish();
            throw new EucalyptusCloudException("Snapshot " + snapshotId + " already exists. Import failed.");
        }
        volumeManager.finish();
        String snapFileName = getStorageRootDirectory() + File.separator + snapshotId;
        SystemUtil.run(new String[] { StorageProperties.EUCA_ROOT_WRAPPER, "dd", "if=" + snapPath,
                "of=" + snapFileName, "bs=" + StorageProperties.blockSize });
        volumeManager = new VolumeEntityWrapperManager();
        LVMVolumeInfo snapshotInfo = volumeManager.getVolumeInfo();
        snapshotInfo.setVolumeId(snapshotId);
        snapshotInfo.setLoFileName(snapFileName);
        snapshotInfo.setSize(size);
        snapshotInfo.setSnapshotOf(volumeId);
        volumeManager.add(snapshotInfo);
        volumeManager.finish();
    }

    @Override
    public void importVolume(String volumeId, String volumePath, int size) throws EucalyptusCloudException {
        VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
        LVMVolumeInfo volInfo = volumeManager.getVolumeInfo(volumeId);
        if (volInfo != null) {
            volumeManager.finish();
            throw new EucalyptusCloudException("Volume " + volumeId + " already exists. Import failed.");
        }
        volumeManager.finish();
        createVolume(volumeId, size);
        volumeManager = new VolumeEntityWrapperManager();
        LVMVolumeInfo volumeInfo = volumeManager.getVolumeInfo(volumeId);
        if (volumeInfo != null) {
            SystemUtil.run(new String[] {
                    StorageProperties.EUCA_ROOT_WRAPPER, "dd", "if=" + volumePath, "of=" + lvmRootDirectory
                            + File.separator + volumeInfo.getVgName() + File.separator + volumeInfo.getLvName(),
                    "bs=" + StorageProperties.blockSize });
        } else {
            volumeManager.abort();
            throw new EucalyptusCloudException("Unable to find volume with id: " + volumeId);
        }
    }

    @Override
    public String attachVolume(String volumeId, List<String> nodeIqns) throws EucalyptusCloudException {
        return getVolumeProperty(volumeId);
    }

    @Override
    public void detachVolume(String volumeId, String nodeIqn) throws EucalyptusCloudException {
    }

    @Override
    public void checkReady() throws EucalyptusCloudException {
        // TODO Auto-generated method stub

    }

    @Override
    public void stop() throws EucalyptusCloudException {
        // TODO Auto-generated method stub

    }

    @Override
    public void disable() throws EucalyptusCloudException {
        // TODO Auto-generated method stub

    }

    @Override
    public void enable() throws EucalyptusCloudException {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean getFromBackend(String snapshotId, int size) throws EucalyptusCloudException {
        return false;
    }

    @Override
    public void checkVolume(String volumeId) throws EucalyptusCloudException {
    }

    @Override
    public List<CheckerTask> getCheckers() {
        List<CheckerTask> checkers = new ArrayList<CheckerTask>();
        return checkers;
    }
}