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 62c71489229..3c959ef70b8 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 @@ -101,8 +101,6 @@ import com.cloud.agent.api.FenceCommand; import com.cloud.agent.api.GetStorageStatsAnswer; import com.cloud.agent.api.GetStorageStatsCommand; import com.cloud.agent.api.HostVmStateReportEntry; -import com.cloud.agent.api.MaintainAnswer; -import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.ManageSnapshotAnswer; import com.cloud.agent.api.ManageSnapshotCommand; import com.cloud.agent.api.ModifyStoragePoolAnswer; @@ -1305,9 +1303,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } try { - if (cmd instanceof MaintainCommand) { - return execute((MaintainCommand)cmd); - } else if (cmd instanceof CreateCommand) { + if (cmd instanceof CreateCommand) { return execute((CreateCommand)cmd); } else if (cmd instanceof DestroyCommand) { return execute((DestroyCommand)cmd); @@ -1769,7 +1765,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } // this is much like PrimaryStorageDownloadCommand, but keeping it separate - protected KVMPhysicalDisk templateToPrimaryDownload(final String templateUrl, final KVMStoragePool primaryPool, final String volUuid) { + public KVMPhysicalDisk templateToPrimaryDownload(final String templateUrl, final KVMStoragePool primaryPool, final String volUuid) { final int index = templateUrl.lastIndexOf("/"); final String mountpoint = templateUrl.substring(0, index); String templateName = null; @@ -2866,10 +2862,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return new Answer(cmd, result, ""); } - protected MaintainAnswer execute(final MaintainCommand cmd) { - return new MaintainAnswer(cmd); - } - protected PowerState convertToPowerState(final DomainState ps) { final PowerState state = s_powerStatesTable.get(ps); return state == null ? PowerState.PowerUnknown : state; diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCreateCommandWrapper.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCreateCommandWrapper.java new file mode 100644 index 00000000000..f169e720c52 --- /dev/null +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCreateCommandWrapper.java @@ -0,0 +1,83 @@ +// +// 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.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.storage.CreateAnswer; +import com.cloud.agent.api.storage.CreateCommand; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.agent.api.to.VolumeTO; +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.vm.DiskProfile; + +public final class LibvirtCreateCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(LibvirtCreateCommandWrapper.class); + + @Override + public Answer execute(final CreateCommand command, final LibvirtComputingResource libvirtComputingResource) { + final StorageFilerTO pool = command.getPool(); + final DiskProfile dskch = command.getDiskCharacteristics(); + KVMPhysicalDisk baseVol = null; + KVMStoragePool primaryPool = null; + KVMPhysicalDisk vol = null; + long disksize; + try { + final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr(); + primaryPool = storagePoolMgr.getStoragePool(pool.getType(), pool.getUuid()); + disksize = dskch.getSize(); + + if (command.getTemplateUrl() != null) { + if (primaryPool.getType() == StoragePoolType.CLVM) { + vol = libvirtComputingResource.templateToPrimaryDownload(command.getTemplateUrl(), primaryPool, dskch.getPath()); + } else { + baseVol = primaryPool.getPhysicalDisk(command.getTemplateUrl()); + vol = storagePoolMgr.createDiskFromTemplate(baseVol, + dskch.getPath(), dskch.getProvisioningType(), primaryPool, 0); + } + if (vol == null) { + return new Answer(command, false, " Can't create storage volume on storage pool"); + } + } else { + vol = primaryPool.createPhysicalDisk(dskch.getPath(), dskch.getProvisioningType(), dskch.getSize()); + } + final VolumeTO volume = + new VolumeTO(command.getVolumeId(), dskch.getType(), pool.getType(), pool.getUuid(), pool.getPath(), vol.getName(), vol.getName(), disksize, null); + + volume.setBytesReadRate(dskch.getBytesReadRate()); + volume.setBytesWriteRate(dskch.getBytesWriteRate()); + volume.setIopsReadRate(dskch.getIopsReadRate()); + volume.setIopsWriteRate(dskch.getIopsWriteRate()); + volume.setCacheMode(dskch.getCacheMode()); + return new CreateAnswer(command, volume); + } catch (final CloudRuntimeException e) { + s_logger.debug("Failed to create volume: " + e.toString()); + return new CreateAnswer(command, e); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMaintainCommandWrapper.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMaintainCommandWrapper.java new file mode 100644 index 00000000000..c1aba38ffe4 --- /dev/null +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMaintainCommandWrapper.java @@ -0,0 +1,34 @@ +// +// 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 com.cloud.agent.api.Answer; +import com.cloud.agent.api.MaintainAnswer; +import com.cloud.agent.api.MaintainCommand; +import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; +import com.cloud.resource.CommandWrapper; + +public final class LibvirtMaintainCommandWrapper extends CommandWrapper { + + @Override + public Answer execute(final MaintainCommand command, final LibvirtComputingResource libvirtComputingResource) { + return new MaintainAnswer(command); + } +} \ No newline at end of file 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 c5001c47386..bced7f88d8a 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 @@ -30,6 +30,7 @@ import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.GetVncPortCommand; +import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.MigrateCommand; import com.cloud.agent.api.ModifySshKeysCommand; import com.cloud.agent.api.PingTestCommand; @@ -40,6 +41,7 @@ import com.cloud.agent.api.RebootRouterCommand; import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; +import com.cloud.agent.api.storage.CreateCommand; import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; import com.cloud.resource.CommandWrapper; import com.cloud.resource.RequestWrapper; @@ -80,6 +82,8 @@ public class LibvirtRequestWrapper extends RequestWrapper { linbvirtCommands.put(CheckConsoleProxyLoadCommand.class, new LibvirtCheckConsoleProxyLoadCommandWrapper()); linbvirtCommands.put(GetVncPortCommand.class, new LibvirtGetVncPortCommandWrapper()); linbvirtCommands.put(ModifySshKeysCommand.class, new LibvirtModifySshKeysCommandWrapper()); + linbvirtCommands.put(MaintainCommand.class, new LibvirtMaintainCommandWrapper()); + linbvirtCommands.put(CreateCommand.class, new LibvirtCreateCommandWrapper()); resources.put(LibvirtComputingResource.class, linbvirtCommands); } 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 a2b3b7fc4ee..22fa80863e4 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 @@ -72,6 +72,7 @@ import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.GetVncPortCommand; +import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.MigrateCommand; import com.cloud.agent.api.ModifySshKeysCommand; import com.cloud.agent.api.PingTestCommand; @@ -83,8 +84,10 @@ import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.VmStatsEntry; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; +import com.cloud.agent.api.storage.CreateCommand; import com.cloud.agent.api.to.DiskTO; 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.VirtualRoutingResource; import com.cloud.exception.InternalErrorException; @@ -100,6 +103,7 @@ import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Volume; import com.cloud.template.VirtualMachineTemplate.BootloaderType; import com.cloud.utils.Pair; +import com.cloud.vm.DiskProfile; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.PowerState; @@ -1217,4 +1221,102 @@ public class LibvirtComputingResourceTest { verify(libvirtComputingResource, times(1)).getTimeout(); } + + @Test + public void testMaintainCommand() { + final MaintainCommand command = new MaintainCommand(); + + final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(command, libvirtComputingResource); + assertTrue(answer.getResult()); + } + + @Test + public void testCreateCommandNoTemplate() { + final DiskProfile diskCharacteristics = Mockito.mock(DiskProfile.class); + final StorageFilerTO pool = Mockito.mock(StorageFilerTO.class); + final boolean executeInSequence = false; + + final CreateCommand command = new CreateCommand(diskCharacteristics, pool, executeInSequence ); + + final KVMStoragePoolManager poolManager = Mockito.mock(KVMStoragePoolManager.class); + final KVMStoragePool primary = Mockito.mock(KVMStoragePool.class); + final KVMPhysicalDisk vol = Mockito.mock(KVMPhysicalDisk.class); + + when(libvirtComputingResource.getStoragePoolMgr()).thenReturn(poolManager); + when(poolManager.getStoragePool(pool.getType(), pool.getUuid())).thenReturn(primary); + + when(primary.createPhysicalDisk(diskCharacteristics.getPath(), diskCharacteristics.getProvisioningType(), diskCharacteristics.getSize())).thenReturn(vol); + + final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(command, libvirtComputingResource); + assertTrue(answer.getResult()); + + verify(libvirtComputingResource, times(1)).getStoragePoolMgr(); + verify(poolManager, times(1)).getStoragePool(pool.getType(), pool.getUuid()); + } + + @Test + public void testCreateCommand() { + final DiskProfile diskCharacteristics = Mockito.mock(DiskProfile.class); + final StorageFilerTO pool = Mockito.mock(StorageFilerTO.class); + final String templateUrl = "http://template"; + final boolean executeInSequence = false; + + final CreateCommand command = new CreateCommand(diskCharacteristics, templateUrl, pool, executeInSequence ); + + final KVMStoragePoolManager poolManager = Mockito.mock(KVMStoragePoolManager.class); + final KVMStoragePool primary = Mockito.mock(KVMStoragePool.class); + final KVMPhysicalDisk vol = Mockito.mock(KVMPhysicalDisk.class); + + when(libvirtComputingResource.getStoragePoolMgr()).thenReturn(poolManager); + when(poolManager.getStoragePool(pool.getType(), pool.getUuid())).thenReturn(primary); + + when(primary.getType()).thenReturn(StoragePoolType.CLVM); + when(libvirtComputingResource.templateToPrimaryDownload(command.getTemplateUrl(), primary, diskCharacteristics.getPath())).thenReturn(vol); + + final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(command, libvirtComputingResource); + assertTrue(answer.getResult()); + + verify(libvirtComputingResource, times(1)).getStoragePoolMgr(); + verify(poolManager, times(1)).getStoragePool(pool.getType(), pool.getUuid()); + } + + @Test + public void testCreateCommandCLVM() { + final DiskProfile diskCharacteristics = Mockito.mock(DiskProfile.class); + final StorageFilerTO pool = Mockito.mock(StorageFilerTO.class); + final String templateUrl = "http://template"; + final boolean executeInSequence = false; + + final CreateCommand command = new CreateCommand(diskCharacteristics, templateUrl, pool, executeInSequence ); + + final KVMStoragePoolManager poolManager = Mockito.mock(KVMStoragePoolManager.class); + final KVMStoragePool primary = Mockito.mock(KVMStoragePool.class); + final KVMPhysicalDisk vol = Mockito.mock(KVMPhysicalDisk.class); + final KVMPhysicalDisk baseVol = Mockito.mock(KVMPhysicalDisk.class); + + when(libvirtComputingResource.getStoragePoolMgr()).thenReturn(poolManager); + when(poolManager.getStoragePool(pool.getType(), pool.getUuid())).thenReturn(primary); + + when(primary.getPhysicalDisk(command.getTemplateUrl())).thenReturn(baseVol); + when(poolManager.createDiskFromTemplate(baseVol, + diskCharacteristics.getPath(), diskCharacteristics.getProvisioningType(), primary, 0)).thenReturn(vol); + + final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(command, libvirtComputingResource); + assertTrue(answer.getResult()); + + verify(libvirtComputingResource, times(1)).getStoragePoolMgr(); + verify(poolManager, times(1)).getStoragePool(pool.getType(), pool.getUuid()); + } } \ No newline at end of file