diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 31a9ed71234..e98e9459698 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -60,7 +60,6 @@ import org.libvirt.DomainInfo.DomainState; import org.libvirt.DomainInterfaceStats; import org.libvirt.LibvirtException; import org.libvirt.NodeInfo; -import org.libvirt.StorageVol; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; @@ -80,15 +79,12 @@ import com.cloud.agent.api.routing.IpAssocCommand; import com.cloud.agent.api.routing.IpAssocVpcCommand; import com.cloud.agent.api.routing.NetworkElementCommand; import com.cloud.agent.api.routing.SetSourceNatCommand; -import com.cloud.agent.api.storage.ResizeVolumeAnswer; -import com.cloud.agent.api.storage.ResizeVolumeCommand; import com.cloud.agent.api.to.DataStoreTO; import com.cloud.agent.api.to.DataTO; import com.cloud.agent.api.to.DiskTO; import com.cloud.agent.api.to.IpAddressTO; import com.cloud.agent.api.to.NfsTO; import com.cloud.agent.api.to.NicTO; -import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.resource.virtualnetwork.VirtualRouterDeployer; import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource; @@ -408,6 +404,10 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return _ovsPvlanVmPath; } + public String getResizeVolumePath() { + return _resizeVolumePath; + } + private static final class KeyValueInterpreter extends OutputInterpreter { private final Map map = new HashMap(); @@ -1259,8 +1259,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return execute((StartCommand)cmd); } else if (cmd instanceof NetworkElementCommand) { return _virtRouterResource.executeRequest((NetworkElementCommand)cmd); - } else if (cmd instanceof ResizeVolumeCommand) { - return execute((ResizeVolumeCommand)cmd); } else if (cmd instanceof StorageSubSystemCommand) { return storageHandler.handleStorageCommands((StorageSubSystemCommand)cmd); } else { @@ -1401,7 +1399,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } } - private String getResizeScriptType(final KVMStoragePool pool, final KVMPhysicalDisk vol) { + public String getResizeScriptType(final KVMStoragePool pool, final KVMPhysicalDisk vol) { final StoragePoolType poolType = pool.getType(); final PhysicalDiskFormat volFormat = vol.getFormat(); @@ -1417,92 +1415,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv throw new CloudRuntimeException("Cannot determine resize type from pool type " + pool.getType()); } - /* uses a local script now, eventually support for virStorageVolResize() will maybe work on - qcow2 and lvm and we can do this in libvirt calls */ - public Answer execute(final ResizeVolumeCommand cmd) { - final String volid = cmd.getPath(); - final long newSize = cmd.getNewSize(); - final long currentSize = cmd.getCurrentSize(); - final String vmInstanceName = cmd.getInstanceName(); - final boolean shrinkOk = cmd.getShrinkOk(); - final StorageFilerTO spool = cmd.getPool(); - final String notifyOnlyType = "NOTIFYONLY"; - - if ( currentSize == newSize) { - // nothing to do - s_logger.info("No need to resize volume: current size " + currentSize + " is same as new size " + newSize); - return new ResizeVolumeAnswer(cmd, true, "success", currentSize); - } - - try { - KVMStoragePool pool = _storagePoolMgr.getStoragePool(spool.getType(), spool.getUuid()); - final KVMPhysicalDisk vol = pool.getPhysicalDisk(volid); - final String path = vol.getPath(); - String type = getResizeScriptType(pool, vol); - - if (pool.getType() != StoragePoolType.RBD) { - if (type.equals("QCOW2") && shrinkOk) { - return new ResizeVolumeAnswer(cmd, false, "Unable to shrink volumes of type " + type); - } - } else { - s_logger.debug("Volume " + path + " is on a RBD storage pool. No need to query for additional information."); - } - - s_logger.debug("Resizing volume: " + path + "," + currentSize + "," + newSize + "," + type + "," + vmInstanceName + "," + shrinkOk); - - /* libvirt doesn't support resizing (C)LVM devices, and corrupts QCOW2 in some scenarios, so we have to do these via Bash script */ - if (pool.getType() != StoragePoolType.CLVM && vol.getFormat() != PhysicalDiskFormat.QCOW2) { - s_logger.debug("Volume " + path + " can be resized by libvirt. Asking libvirt to resize the volume."); - try { - final Connect conn = LibvirtConnection.getConnection(); - final StorageVol v = conn.storageVolLookupByPath(path); - int flags = 0; - - if (conn.getLibVirVersion() > 1001000 && vol.getFormat() == PhysicalDiskFormat.RAW && pool.getType() != StoragePoolType.RBD) { - flags = 1; - } - if (shrinkOk) { - flags = 4; - } - - v.resize(newSize, flags); - type = notifyOnlyType; - } catch (final LibvirtException e) { - return new ResizeVolumeAnswer(cmd, false, e.toString()); - } - } - s_logger.debug("Invoking resize script to handle type " + type); - final Script resizecmd = new Script(_resizeVolumePath, _cmdsTimeout, s_logger); - resizecmd.add("-s", String.valueOf(newSize)); - resizecmd.add("-c", String.valueOf(currentSize)); - resizecmd.add("-p", path); - resizecmd.add("-t", type); - resizecmd.add("-r", String.valueOf(shrinkOk)); - resizecmd.add("-v", vmInstanceName); - final String result = resizecmd.execute(); - - if (result != null) { - if(type.equals(notifyOnlyType)) { - return new ResizeVolumeAnswer(cmd, true, "Resize succeeded, but need reboot to notify guest"); - } else { - return new ResizeVolumeAnswer(cmd, false, result); - } - } - - /* fetch new size as seen from libvirt, don't want to assume anything */ - pool = _storagePoolMgr.getStoragePool(spool.getType(), spool.getUuid()); - pool.refresh(); - final long finalSize = pool.getPhysicalDisk(volid).getVirtualSize(); - s_logger.debug("after resize, size reports as " + finalSize + ", requested " + newSize); - return new ResizeVolumeAnswer(cmd, true, "success", finalSize); - } catch (final CloudRuntimeException e) { - final String error = "Failed to resize volume: " + e.getMessage(); - s_logger.debug(error); - return new ResizeVolumeAnswer(cmd, false, error); - } - - } - private String getBroadcastUriFromBridge(final String brName) { final String pif = matchPifFileInDirectory(brName); final Pattern pattern = Pattern.compile("(\\D+)(\\d+)(\\D*)(\\d*)"); diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtRequestWrapper.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtRequestWrapper.java index c103ef397b8..363981d47cc 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtRequestWrapper.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtRequestWrapper.java @@ -74,6 +74,7 @@ import com.cloud.agent.api.storage.CopyVolumeCommand; import com.cloud.agent.api.storage.CreateCommand; import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; +import com.cloud.agent.api.storage.ResizeVolumeCommand; import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; import com.cloud.resource.CommandWrapper; import com.cloud.resource.RequestWrapper; @@ -148,6 +149,7 @@ public class LibvirtRequestWrapper extends RequestWrapper { linbvirtCommands.put(CreatePrivateTemplateFromSnapshotCommand.class, new LibvirtCreatePrivateTemplateFromSnapshotCommandWrapper()); linbvirtCommands.put(CopyVolumeCommand.class, new LibvirtCopyVolumeCommandWrapper()); linbvirtCommands.put(PvlanSetupCommand.class, new LibvirtPvlanSetupCommandWrapper()); + linbvirtCommands.put(ResizeVolumeCommand.class, new LibvirtResizeVolumeCommandWrapper()); resources.put(LibvirtComputingResource.class, linbvirtCommands); } diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtResizeVolumeCommandWrapper.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtResizeVolumeCommandWrapper.java new file mode 100644 index 00000000000..bbcba4756e5 --- /dev/null +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtResizeVolumeCommandWrapper.java @@ -0,0 +1,136 @@ +// +// 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.resource.wrapper; + +import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; +import org.apache.log4j.Logger; +import org.libvirt.Connect; +import org.libvirt.LibvirtException; +import org.libvirt.StorageVol; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.storage.ResizeVolumeAnswer; +import com.cloud.agent.api.storage.ResizeVolumeCommand; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; +import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk; +import com.cloud.hypervisor.kvm.storage.KVMStoragePool; +import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager; +import com.cloud.resource.CommandWrapper; +import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; + +/* + * Uses a local script now, eventually support for virStorageVolResize() will maybe work on qcow2 and lvm and we can do this in libvirt calls + */ +public final class LibvirtResizeVolumeCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(LibvirtResizeVolumeCommandWrapper.class); + + @Override + public Answer execute(final ResizeVolumeCommand command, final LibvirtComputingResource libvirtComputingResource) { + final String volid = command.getPath(); + final long newSize = command.getNewSize(); + final long currentSize = command.getCurrentSize(); + final String vmInstanceName = command.getInstanceName(); + final boolean shrinkOk = command.getShrinkOk(); + final StorageFilerTO spool = command.getPool(); + final String notifyOnlyType = "NOTIFYONLY"; + + if ( currentSize == newSize) { + // nothing to do + s_logger.info("No need to resize volume: current size " + currentSize + " is same as new size " + newSize); + return new ResizeVolumeAnswer(command, true, "success", currentSize); + } + + try { + final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr(); + KVMStoragePool pool = storagePoolMgr.getStoragePool(spool.getType(), spool.getUuid()); + + final KVMPhysicalDisk vol = pool.getPhysicalDisk(volid); + final String path = vol.getPath(); + String type = libvirtComputingResource.getResizeScriptType(pool, vol); + + if (pool.getType() != StoragePoolType.RBD) { + if (type.equals("QCOW2") && shrinkOk) { + return new ResizeVolumeAnswer(command, false, "Unable to shrink volumes of type " + type); + } + } else { + s_logger.debug("Volume " + path + " is on a RBD storage pool. No need to query for additional information."); + } + + s_logger.debug("Resizing volume: " + path + "," + currentSize + "," + newSize + "," + type + "," + vmInstanceName + "," + shrinkOk); + + /* libvirt doesn't support resizing (C)LVM devices, and corrupts QCOW2 in some scenarios, so we have to do these via Bash script */ + if (pool.getType() != StoragePoolType.CLVM && vol.getFormat() != PhysicalDiskFormat.QCOW2) { + s_logger.debug("Volume " + path + " can be resized by libvirt. Asking libvirt to resize the volume."); + try { + final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper(); + + final Connect conn = libvirtUtilitiesHelper.getConnection(); + final StorageVol v = conn.storageVolLookupByPath(path); + int flags = 0; + + if (conn.getLibVirVersion() > 1001000 && vol.getFormat() == PhysicalDiskFormat.RAW && pool.getType() != StoragePoolType.RBD) { + flags = 1; + } + if (shrinkOk) { + flags = 4; + } + + v.resize(newSize, flags); + type = notifyOnlyType; + } catch (final LibvirtException e) { + return new ResizeVolumeAnswer(command, false, e.toString()); + } + } + s_logger.debug("Invoking resize script to handle type " + type); + + final Script resizecmd = new Script(libvirtComputingResource.getResizeVolumePath(), libvirtComputingResource.getCmdsTimeout(), s_logger); + resizecmd.add("-s", String.valueOf(newSize)); + resizecmd.add("-c", String.valueOf(currentSize)); + resizecmd.add("-p", path); + resizecmd.add("-t", type); + resizecmd.add("-r", String.valueOf(shrinkOk)); + resizecmd.add("-v", vmInstanceName); + final String result = resizecmd.execute(); + + if (result != null) { + if(type.equals(notifyOnlyType)) { + return new ResizeVolumeAnswer(command, true, "Resize succeeded, but need reboot to notify guest"); + } else { + return new ResizeVolumeAnswer(command, false, result); + } + } + + /* fetch new size as seen from libvirt, don't want to assume anything */ + pool = storagePoolMgr.getStoragePool(spool.getType(), spool.getUuid()); + pool.refresh(); + final long finalSize = pool.getPhysicalDisk(volid).getVirtualSize(); + s_logger.debug("after resize, size reports as " + finalSize + ", requested " + newSize); + return new ResizeVolumeAnswer(command, true, "success", finalSize); + } catch (final CloudRuntimeException e) { + final String error = "Failed to resize volume: " + e.getMessage(); + s_logger.debug(error); + return new ResizeVolumeAnswer(command, false, error); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java index ad75b532751..4e8d7bdc52c 100644 --- a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java +++ b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java @@ -46,6 +46,7 @@ import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; +import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; import org.apache.commons.lang.SystemUtils; import org.junit.Assert; import org.junit.Assume; @@ -59,6 +60,7 @@ import org.libvirt.DomainInfo.DomainState; import org.libvirt.DomainInterfaceStats; import org.libvirt.LibvirtException; import org.libvirt.NodeInfo; +import org.libvirt.StorageVol; import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.Mockito; @@ -126,6 +128,7 @@ import com.cloud.agent.api.storage.CopyVolumeCommand; import com.cloud.agent.api.storage.CreateCommand; import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; +import com.cloud.agent.api.storage.ResizeVolumeCommand; import com.cloud.agent.api.to.DataStoreTO; import com.cloud.agent.api.to.DiskTO; import com.cloud.agent.api.to.NicTO; @@ -4328,4 +4331,179 @@ public class LibvirtComputingResourceTest { final Answer answer = wrapper.execute(command, libvirtComputingResource); assertFalse(answer.getResult()); } + + @Test + public void testResizeVolumeCommand() { + final String path = "nfs:/192.168.2.2/storage/secondary"; + final StorageFilerTO pool = Mockito.mock(StorageFilerTO.class); + final Long currentSize = 100l; + final Long newSize = 200l; + final boolean shrinkOk = true; + final String vmInstance = "Test"; + + final ResizeVolumeCommand command = new ResizeVolumeCommand(path, pool, currentSize, newSize, shrinkOk, vmInstance); + + final KVMStoragePoolManager storagePoolMgr = Mockito.mock(KVMStoragePoolManager.class); + final KVMStoragePool storagePool = Mockito.mock(KVMStoragePool.class); + final KVMPhysicalDisk vol = Mockito.mock(KVMPhysicalDisk.class); + final LibvirtUtilitiesHelper libvirtUtilitiesHelper = Mockito.mock(LibvirtUtilitiesHelper.class); + final Connect conn = Mockito.mock(Connect.class); + final StorageVol v = Mockito.mock(StorageVol.class); + + when(libvirtComputingResource.getStoragePoolMgr()).thenReturn(storagePoolMgr); + when(storagePoolMgr.getStoragePool(pool.getType(), pool.getUuid())).thenReturn(storagePool); + when(storagePool.getPhysicalDisk(path)).thenReturn(vol); + when(vol.getPath()).thenReturn(path); + when(libvirtComputingResource.getResizeScriptType(storagePool, vol)).thenReturn("FILE"); + when(storagePool.getType()).thenReturn(StoragePoolType.RBD); + when(vol.getFormat()).thenReturn(PhysicalDiskFormat.FILE); + + when(libvirtComputingResource.getLibvirtUtilitiesHelper()).thenReturn(libvirtUtilitiesHelper); + try { + when(libvirtUtilitiesHelper.getConnection()).thenReturn(conn); + when(conn.storageVolLookupByPath(path)).thenReturn(v); + + when(conn.getLibVirVersion()).thenReturn(10010l); + + } catch (final LibvirtException e) { + fail(e.getMessage()); + } + + final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(command, libvirtComputingResource); + assertTrue(answer.getResult()); + + verify(libvirtComputingResource, times(1)).getStoragePoolMgr(); + + verify(libvirtComputingResource, times(1)).getLibvirtUtilitiesHelper(); + try { + verify(libvirtUtilitiesHelper, times(1)).getConnection(); + } catch (final LibvirtException e) { + fail(e.getMessage()); + } + } + + @Test + public void testResizeVolumeCommandSameSize() { + final String path = "nfs:/192.168.2.2/storage/secondary"; + final StorageFilerTO pool = Mockito.mock(StorageFilerTO.class); + final Long currentSize = 100l; + final Long newSize = 100l; + final boolean shrinkOk = false; + final String vmInstance = "Test"; + + final ResizeVolumeCommand command = new ResizeVolumeCommand(path, pool, currentSize, newSize, shrinkOk, vmInstance); + + final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(command, libvirtComputingResource); + assertTrue(answer.getResult()); + } + + @Test + public void testResizeVolumeCommandShrink() { + final String path = "nfs:/192.168.2.2/storage/secondary"; + final StorageFilerTO pool = Mockito.mock(StorageFilerTO.class); + final Long currentSize = 100l; + final Long newSize = 200l; + final boolean shrinkOk = true; + final String vmInstance = "Test"; + + final ResizeVolumeCommand command = new ResizeVolumeCommand(path, pool, currentSize, newSize, shrinkOk, vmInstance); + + final KVMStoragePoolManager storagePoolMgr = Mockito.mock(KVMStoragePoolManager.class); + final KVMStoragePool storagePool = Mockito.mock(KVMStoragePool.class); + final KVMPhysicalDisk vol = Mockito.mock(KVMPhysicalDisk.class); + + when(libvirtComputingResource.getStoragePoolMgr()).thenReturn(storagePoolMgr); + when(storagePoolMgr.getStoragePool(pool.getType(), pool.getUuid())).thenReturn(storagePool); + when(storagePool.getPhysicalDisk(path)).thenReturn(vol); + when(vol.getPath()).thenReturn(path); + when(libvirtComputingResource.getResizeScriptType(storagePool, vol)).thenReturn("QCOW2"); + + final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(command, libvirtComputingResource); + assertFalse(answer.getResult()); + } + + @SuppressWarnings("unchecked") + @Test + public void testResizeVolumeCommandException() { + final String path = "nfs:/192.168.2.2/storage/secondary"; + final StorageFilerTO pool = Mockito.mock(StorageFilerTO.class); + final Long currentSize = 100l; + final Long newSize = 200l; + final boolean shrinkOk = false; + final String vmInstance = "Test"; + + final ResizeVolumeCommand command = new ResizeVolumeCommand(path, pool, currentSize, newSize, shrinkOk, vmInstance); + + final KVMStoragePoolManager storagePoolMgr = Mockito.mock(KVMStoragePoolManager.class); + final KVMStoragePool storagePool = Mockito.mock(KVMStoragePool.class); + final KVMPhysicalDisk vol = Mockito.mock(KVMPhysicalDisk.class); + final LibvirtUtilitiesHelper libvirtUtilitiesHelper = Mockito.mock(LibvirtUtilitiesHelper.class); + + when(libvirtComputingResource.getStoragePoolMgr()).thenReturn(storagePoolMgr); + when(storagePoolMgr.getStoragePool(pool.getType(), pool.getUuid())).thenReturn(storagePool); + when(storagePool.getPhysicalDisk(path)).thenReturn(vol); + when(vol.getPath()).thenReturn(path); + when(libvirtComputingResource.getResizeScriptType(storagePool, vol)).thenReturn("FILE"); + when(storagePool.getType()).thenReturn(StoragePoolType.RBD); + when(vol.getFormat()).thenReturn(PhysicalDiskFormat.FILE); + + when(libvirtComputingResource.getLibvirtUtilitiesHelper()).thenReturn(libvirtUtilitiesHelper); + try { + when(libvirtUtilitiesHelper.getConnection()).thenThrow(LibvirtException.class); + } catch (final LibvirtException e) { + fail(e.getMessage()); + } + + final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(command, libvirtComputingResource); + assertFalse(answer.getResult()); + + verify(libvirtComputingResource, times(1)).getStoragePoolMgr(); + + verify(libvirtComputingResource, times(1)).getLibvirtUtilitiesHelper(); + try { + verify(libvirtUtilitiesHelper, times(1)).getConnection(); + } catch (final LibvirtException e) { + fail(e.getMessage()); + } + } + + @SuppressWarnings("unchecked") + @Test + public void testResizeVolumeCommandException2() { + final String path = "nfs:/192.168.2.2/storage/secondary"; + final StorageFilerTO pool = Mockito.mock(StorageFilerTO.class); + final Long currentSize = 100l; + final Long newSize = 200l; + final boolean shrinkOk = false; + final String vmInstance = "Test"; + + final ResizeVolumeCommand command = new ResizeVolumeCommand(path, pool, currentSize, newSize, shrinkOk, vmInstance); + + final KVMStoragePoolManager storagePoolMgr = Mockito.mock(KVMStoragePoolManager.class); + final KVMStoragePool storagePool = Mockito.mock(KVMStoragePool.class); + + when(libvirtComputingResource.getStoragePoolMgr()).thenReturn(storagePoolMgr); + when(storagePoolMgr.getStoragePool(pool.getType(), pool.getUuid())).thenReturn(storagePool); + when(storagePool.getPhysicalDisk(path)).thenThrow(CloudRuntimeException.class); + + final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(command, libvirtComputingResource); + assertFalse(answer.getResult()); + + verify(libvirtComputingResource, times(1)).getStoragePoolMgr(); + } } \ No newline at end of file