/** * Copyright (c) 2016 Inria * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * - Christophe Gourdin <christophe.gourdin@inria.fr> * */ package org.occiware.clouddesigner.occi.infrastructure.connector.vmware.utils; import java.rmi.RemoteException; import java.util.HashMap; import java.util.Map; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.addons.Volume; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.addons.exceptions.AttachDiskException; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.addons.exceptions.CreateDiskException; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.addons.exceptions.DeleteDiskException; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.addons.exceptions.DetachDiskException; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.addons.exceptions.DiskNotFoundException; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.addons.exceptions.LoadVolumeException; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.addons.exceptions.RenameDiskException; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.addons.exceptions.ResizeDiskException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.vmware.vim25.VirtualDevice; import com.vmware.vim25.VirtualDeviceBackingInfo; import com.vmware.vim25.VirtualDeviceFileBackingInfo; import com.vmware.vim25.VirtualDisk; import com.vmware.vim25.mo.ServiceInstance; import com.vmware.vim25.mo.VirtualDiskManager; import com.vmware.vim25.mo.VirtualMachine; public class VolumeHelper { private static Logger LOGGER = LoggerFactory.getLogger(VolumeHelper.class); public static Volume volume = null; /** * Load or refresh volume information from vcenter. * * @param dsName * @param volumeName * @param dcName * @param vmName * (may be null if volume is not attached.) * @throws LoadVolumeException */ public static void loadVolumeInformation(String dsName, String volumeName, String dcName, String vmName) throws LoadVolumeException { // Load a volume. volume = new Volume(volumeName, dsName, dcName, vmName); volume.loadVolume(); } /** * Is the volume exist on vcenter ? * * @param dsName * @param volumeName * @param dcName * @param vmName * (may be null if volume is not attached). * @return true if volume exist, else false. * @throws LoadVolumeException */ public static boolean isExistVolumeForName(String dsName, String volumeName, String dcName, String vmName) { // Search the volume on datastore. if (!checkVolume(volumeName)) { // Load the volume. try { loadVolumeInformation(dsName, volumeName, dcName, vmName); } catch (LoadVolumeException ex) { } } return volume.isExist(); } /** * Create an empty disk if no attachment on vm or a virtual disk attached to * a vm. * * @param dcName * (Datacenter name) * @param dsName * (Datastore name) * @param volumeName * @param volumeSize * @throws LoadVolumeException * @throws CreateDiskException */ public static void createVolume(final String dcName, final String dsName, final String volumeName, final Float volumeSize) throws LoadVolumeException, CreateDiskException { // build a new disk. if (!checkVolume(volumeName)) { loadVolumeInformation(dsName, volumeName, dcName, null); } if (volume.isExist()) { LOGGER.warn("The disk " + volumeName + " already exist, cant create it."); return; } if (volume.getVmName() != null) { volume.createAttachedVolume(); } else { volume.createEmptyVolume(); } } // Delegate methods. /** * Set the disk size on volume object. * * @param size */ public static void setSize(final String volumeName, final Float size) { if (checkVolume(volumeName)) { volume.setSize(size); } } public static Float getSize(String volumeName) throws DiskNotFoundException { if (checkVolume(volumeName)) { return volume.getSize(); } else { LOGGER.warn("No disk information loaded, cant give a size."); throw new DiskNotFoundException("No disk information loaded, cant give a size."); } } /** * * @return the volume state, null if no volume defined. * @throws DiskNotFoundException */ public static String getDiskState(final String volumeName) throws DiskNotFoundException { if (checkVolume(volumeName)) { return volume.getVolumeState(); } else { LOGGER.warn("No disk information loaded, cant give a state."); throw new DiskNotFoundException("No disk information loaded, cant give a state."); } } /** * * @return * @throws DiskNotFoundException */ public static boolean isAttached(final String volumeName) throws DiskNotFoundException { boolean result; if (checkVolume(volumeName)) { result = volume.isAttached(); } else { LOGGER.warn("No disk information loaded, cant give an attachment state."); throw new DiskNotFoundException("No disk information loaded, cant give an attachment state."); } return result; } /** * Resize the specified disk. * * @param dc * @param ds * @param volumeName * @param vmName * @throws ResizeDiskException */ public static void resizeDisk(final String volumeName, Float newSize) throws DiskNotFoundException, ResizeDiskException { if (checkVolume(volumeName)) { volume.resize(newSize); } else { LOGGER.warn("No disk information loaded, cant resize the disk."); throw new DiskNotFoundException("No disk information loaded, cant resize the disk."); } } /** * Get the uuid of the disk. * * @param volumeName * @return * @throws RemoteException */ public static String getDiskUUID(String volumeName) throws RemoteException { String uuid = "unknown"; if (checkVolume(volumeName)) { uuid = volume.getUUID(); } return uuid; } /** * Rename a disk from oldVolumeName to newVolumeName and the vmdk file * accordingly. * * @param oldVolumeName * @param newVolumeName * @return true if operation succeed * @throws DiskNotFoundException * @throws RenameDiskException */ public static void renameDisk(final String oldVolumeName, final String newVolumeName) throws DiskNotFoundException, RenameDiskException { if (checkVolume(oldVolumeName)) { volume.renameDisk(newVolumeName); } else { LOGGER.warn("No disk information loaded, cant rename the disk: " + oldVolumeName); throw new DiskNotFoundException("No disk information loaded, cant rename the disk : " + oldVolumeName); } } /** * Destroy definitively a disk from vcenter. If the disk is attached, the * disk is detached before. * * @param volumeName * @param dcName * @param dsName * @param vmName * @throws DetachDiskException * @throws DeleteDiskException * @throws LoadVolumeException */ public static void destroyDisk(final String volumeName, final String dcName, final String dsName, final String vmName) throws DetachDiskException, DeleteDiskException, LoadVolumeException { if (checkVolume(volumeName)) { // The volume is loaded // Destroy the vmdk. if (volume.isAttached()) { // Detach the disk before the deletion. detachDisk(volumeName); } volume.destroyVolume(); } else { if (isExistVolumeForName(dsName, volumeName, dcName, vmName)) { // disk is reloaded successfully, destroy the vmdk. volume.destroyVolume(); } } } /** * Detach the disk from vm instance. * * @param volumeName * @throws DetachDiskException */ public static void detachDisk(final String volumeName) throws DetachDiskException { if (checkVolume(volumeName)) { if (volume.isAttached()) { volume.detachVolume(); } } } /** * Attach the disk from vm instance. * * @param volumeName * @param vmName * @throws AttachDiskException * @throws DetachDiskException */ public static void attachDisk(final String volumeName, final String vmName) throws AttachDiskException, DetachDiskException { if (checkVolume(volumeName)) { if (volume.isAttached()) { detachDisk(volumeName); if (volume.isAttached()) { LOGGER.warn("Cant detach the disk, please check your configuration and logs."); } } volume.attachVolume(); } } /** * Check if volume object is the good one with volumeName info. * * @param volumeName * @return true if ok, false otherwise. */ private static boolean checkVolume(final String volumeName) { boolean result = false; if (volume != null && volume.getVolumeName().equals(volumeName)) { result = true; } return result; } /** * Get all vmware virtual disk object for a VM. * * @param vm * @return a map of String (diskName), VirtualDisk. */ public static Map<String, VirtualDisk> getVirtualDiskForVM(VirtualMachine vm) { Map<String, VirtualDisk> mapDisks = new HashMap<String, VirtualDisk>(); if (vm == null) { return mapDisks; } VirtualDevice[] devices = vm.getConfig().getHardware().getDevice(); String diskName; // Search on devices. for (VirtualDevice device : devices) { diskName = null; if (device == null) { continue; } else if (device instanceof VirtualDisk) { VirtualDisk disk = (VirtualDisk) device; VirtualDeviceBackingInfo vdbi = device.getBacking(); if (vdbi instanceof VirtualDeviceFileBackingInfo) { diskName = ((VirtualDeviceFileBackingInfo) vdbi).getFileName(); // Add to map. mapDisks.put(diskName, disk); } } } return mapDisks; } }