From 3c8b217262e08053fd59329f7466b65b150a18c2 Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Fri, 1 May 2015 19:17:30 +0200 Subject: [PATCH] Refactoring the LibvirtComputingResource - Adding LibvirtCheckOnHostCommandWrapper and LibvirtOvsCreateTunnelCommandWrapper - 4 unit tests added - KVM hypervisor plugin with 16.2% coverage --- .../resource/LibvirtComputingResource.java | 89 +------------- .../LibvirtCheckOnHostCommandWrapper.java | 64 ++++++++++ .../LibvirtOvsCreateTunnelCommandWrapper.java | 68 +++++++++++ .../wrapper/LibvirtRequestWrapper.java | 4 + .../LibvirtComputingResourceTest.java | 112 ++++++++++++++++++ 5 files changed, 252 insertions(+), 85 deletions(-) create mode 100644 plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckOnHostCommandWrapper.java create mode 100644 plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtOvsCreateTunnelCommandWrapper.java 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 9c1a6b42570..6d13ce61c72 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 @@ -85,7 +85,6 @@ import com.ceph.rbd.RbdImage; import com.cloud.agent.api.Answer; import com.cloud.agent.api.BackupSnapshotAnswer; import com.cloud.agent.api.BackupSnapshotCommand; -import com.cloud.agent.api.CheckOnHostCommand; import com.cloud.agent.api.Command; import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand; import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand; @@ -98,8 +97,6 @@ import com.cloud.agent.api.ManageSnapshotAnswer; import com.cloud.agent.api.ManageSnapshotCommand; import com.cloud.agent.api.NetworkUsageAnswer; import com.cloud.agent.api.NetworkUsageCommand; -import com.cloud.agent.api.OvsCreateTunnelAnswer; -import com.cloud.agent.api.OvsCreateTunnelCommand; import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.PingRoutingCommand; import com.cloud.agent.api.PingRoutingWithNwGroupsCommand; @@ -430,6 +427,10 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return _ovsTunnelPath; } + public KVMHAMonitor getMonitor() { + return _monitor; + } + private static final class KeyValueInterpreter extends OutputInterpreter { private final Map map = new HashMap(); @@ -1309,10 +1310,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return storageHandler.handleStorageCommands((StorageSubSystemCommand)cmd); } else if (cmd instanceof PvlanSetupCommand) { return execute((PvlanSetupCommand)cmd); - } else if (cmd instanceof CheckOnHostCommand) { - return execute((CheckOnHostCommand)cmd); - } else if (cmd instanceof OvsCreateTunnelCommand) { - return execute((OvsCreateTunnelCommand)cmd); } else { s_logger.warn("Unsupported command "); return Answer.createUnsupportedCommandAnswer(cmd); @@ -1398,39 +1395,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return true; } - private OvsCreateTunnelAnswer execute(final OvsCreateTunnelCommand cmd) { - final String bridge = cmd.getNetworkName(); - try { - if (!findOrCreateTunnelNetwork(bridge)) { - s_logger.debug("Error during bridge setup"); - return new OvsCreateTunnelAnswer(cmd, false, - "Cannot create network", bridge); - } - - configureTunnelNetwork(cmd.getNetworkId(), cmd.getFrom(), - cmd.getNetworkName()); - final Script command = new Script(_ovsTunnelPath, _timeout, s_logger); - command.add("create_tunnel"); - command.add("--bridge", bridge); - command.add("--remote_ip", cmd.getRemoteIp()); - command.add("--key", cmd.getKey().toString()); - command.add("--src_host", cmd.getFrom().toString()); - command.add("--dst_host", cmd.getTo().toString()); - - final String result = command.execute(); - if (result != null) { - return new OvsCreateTunnelAnswer(cmd, true, result, null, - bridge); - } else { - return new OvsCreateTunnelAnswer(cmd, false, result, bridge); - } - } catch (final Exception e) { - s_logger.debug("Error during tunnel setup"); - s_logger.warn("Caught execption when creating ovs tunnel", e); - return new OvsCreateTunnelAnswer(cmd, false, e.getMessage(), bridge); - } - } - private CopyVolumeAnswer execute(final CopyVolumeCommand cmd) { /** This method is only used for copying files from Primary Storage TO Secondary Storage @@ -1508,26 +1472,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } - protected Answer execute(final CheckOnHostCommand cmd) { - final ExecutorService executors = Executors.newSingleThreadExecutor(); - final List pools = _monitor.getStoragePools(); - final KVMHAChecker ha = new KVMHAChecker(pools, cmd.getHost().getPrivateNetwork().getIp()); - final Future future = executors.submit(ha); - try { - final Boolean result = future.get(); - if (result) { - return new Answer(cmd, false, "Heart is still beating..."); - } else { - return new Answer(cmd); - } - } catch (final InterruptedException e) { - return new Answer(cmd, false, "can't get status of host:"); - } catch (final ExecutionException e) { - return new Answer(cmd, false, "can't get status of host:"); - } - - } - protected Storage.StorageResourceType getStorageResourceType() { return Storage.StorageResourceType.STORAGE_POOL; } @@ -3795,28 +3739,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return parser.getEmulator(); } - private String getGuestType(final Connect conn, final String vmName) { - final LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); - Domain dm = null; - try { - dm = conn.domainLookupByName(vmName); - final String xmlDesc = dm.getXMLDesc(0); - parser.parseDomainXML(xmlDesc); - return parser.getDescription(); - } catch (final LibvirtException e) { - s_logger.trace("Ignoring libvirt error.", e); - return null; - } finally { - try { - if (dm != null) { - dm.free(); - } - } catch (final LibvirtException l) { - s_logger.trace("Ignoring libvirt error.", l); - } - } - } - boolean isGuestPVEnabled(final String guestOSName) { if (guestOSName == null) { return false; @@ -4304,13 +4226,11 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv @Override public void setName(final String name) { // TODO Auto-generated method stub - } @Override public void setConfigParams(final Map params) { // TODO Auto-generated method stub - } @Override @@ -4328,7 +4248,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv @Override public void setRunLevel(final int level) { // TODO Auto-generated method stub - } public HypervisorType getHypervisorType(){ diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckOnHostCommandWrapper.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckOnHostCommandWrapper.java new file mode 100644 index 00000000000..5e5602351a3 --- /dev/null +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckOnHostCommandWrapper.java @@ -0,0 +1,64 @@ +// +// 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 java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CheckOnHostCommand; +import com.cloud.agent.api.to.HostTO; +import com.cloud.agent.api.to.NetworkTO; +import com.cloud.hypervisor.kvm.resource.KVMHABase.NfsStoragePool; +import com.cloud.hypervisor.kvm.resource.KVMHAChecker; +import com.cloud.hypervisor.kvm.resource.KVMHAMonitor; +import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; +import com.cloud.resource.CommandWrapper; + +public final class LibvirtCheckOnHostCommandWrapper extends CommandWrapper { + + @Override + public Answer execute(final CheckOnHostCommand command, final LibvirtComputingResource libvirtComputingResource) { + final ExecutorService executors = Executors.newSingleThreadExecutor(); + final KVMHAMonitor monitor = libvirtComputingResource.getMonitor(); + + final List pools = monitor.getStoragePools(); + HostTO host = command.getHost(); + NetworkTO privateNetwork = host.getPrivateNetwork(); + final KVMHAChecker ha = new KVMHAChecker(pools, privateNetwork.getIp()); + + final Future future = executors.submit(ha); + try { + final Boolean result = future.get(); + if (result) { + return new Answer(command, false, "Heart is still beating..."); + } else { + return new Answer(command); + } + } catch (final InterruptedException e) { + return new Answer(command, false, "can't get status of host:"); + } catch (final ExecutionException e) { + return new Answer(command, false, "can't get status of host:"); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtOvsCreateTunnelCommandWrapper.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtOvsCreateTunnelCommandWrapper.java new file mode 100644 index 00000000000..3a620577d12 --- /dev/null +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtOvsCreateTunnelCommandWrapper.java @@ -0,0 +1,68 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// + +package com.cloud.hypervisor.kvm.resource.wrapper; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.OvsCreateTunnelAnswer; +import com.cloud.agent.api.OvsCreateTunnelCommand; +import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; +import com.cloud.resource.CommandWrapper; +import com.cloud.utils.script.Script; + +public final class LibvirtOvsCreateTunnelCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(LibvirtOvsCreateTunnelCommandWrapper.class); + + @Override + public Answer execute(final OvsCreateTunnelCommand command, final LibvirtComputingResource libvirtComputingResource) { + final String bridge = command.getNetworkName(); + try { + if (!libvirtComputingResource.findOrCreateTunnelNetwork(bridge)) { + s_logger.debug("Error during bridge setup"); + return new OvsCreateTunnelAnswer(command, false, + "Cannot create network", bridge); + } + + libvirtComputingResource.configureTunnelNetwork(command.getNetworkId(), command.getFrom(), + command.getNetworkName()); + + final Script scriptCommand = new Script(libvirtComputingResource.getOvsTunnelPath(), libvirtComputingResource.getTimeout(), s_logger); + scriptCommand.add("create_tunnel"); + scriptCommand.add("--bridge", bridge); + scriptCommand.add("--remote_ip", command.getRemoteIp()); + scriptCommand.add("--key", command.getKey().toString()); + scriptCommand.add("--src_host", command.getFrom().toString()); + scriptCommand.add("--dst_host", command.getTo().toString()); + + final String result = scriptCommand.execute(); + if (result != null) { + return new OvsCreateTunnelAnswer(command, true, result, null, + bridge); + } else { + return new OvsCreateTunnelAnswer(command, false, result, bridge); + } + } catch (final Exception e) { + s_logger.warn("Caught execption when creating ovs tunnel", e); + return new OvsCreateTunnelAnswer(command, false, e.getMessage(), bridge); + } + } +} \ 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 ca7a7d2638c..af2f544e094 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 @@ -25,6 +25,7 @@ import com.cloud.agent.api.AttachIsoCommand; import com.cloud.agent.api.AttachVolumeCommand; import com.cloud.agent.api.CheckHealthCommand; import com.cloud.agent.api.CheckNetworkCommand; +import com.cloud.agent.api.CheckOnHostCommand; import com.cloud.agent.api.CheckVirtualMachineCommand; import com.cloud.agent.api.CleanupNetworkRulesCmd; import com.cloud.agent.api.Command; @@ -41,6 +42,7 @@ import com.cloud.agent.api.ModifySshKeysCommand; import com.cloud.agent.api.ModifyStoragePoolCommand; import com.cloud.agent.api.NetworkRulesSystemVmCommand; import com.cloud.agent.api.NetworkRulesVmSecondaryIpCommand; +import com.cloud.agent.api.OvsCreateTunnelCommand; import com.cloud.agent.api.OvsDestroyBridgeCommand; import com.cloud.agent.api.OvsDestroyTunnelCommand; import com.cloud.agent.api.OvsFetchInterfaceCommand; @@ -120,6 +122,8 @@ public class LibvirtRequestWrapper extends RequestWrapper { linbvirtCommands.put(CheckSshCommand.class, new LibvirtCheckSshCommandWrapper()); linbvirtCommands.put(CheckNetworkCommand.class, new LibvirtCheckNetworkCommandWrapper()); linbvirtCommands.put(OvsDestroyTunnelCommand.class, new LibvirtOvsDestroyTunnelCommandWrapper()); + linbvirtCommands.put(CheckOnHostCommand.class, new LibvirtCheckOnHostCommandWrapper()); + linbvirtCommands.put(OvsCreateTunnelCommand.class, new LibvirtOvsCreateTunnelCommandWrapper()); 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 1551f98e4d5..f01ad7a76dc 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 @@ -68,6 +68,7 @@ import com.cloud.agent.api.AttachIsoCommand; import com.cloud.agent.api.AttachVolumeCommand; import com.cloud.agent.api.CheckHealthCommand; import com.cloud.agent.api.CheckNetworkCommand; +import com.cloud.agent.api.CheckOnHostCommand; import com.cloud.agent.api.CheckVirtualMachineCommand; import com.cloud.agent.api.CleanupNetworkRulesCmd; import com.cloud.agent.api.CreateStoragePoolCommand; @@ -83,6 +84,7 @@ import com.cloud.agent.api.ModifySshKeysCommand; import com.cloud.agent.api.ModifyStoragePoolCommand; import com.cloud.agent.api.NetworkRulesSystemVmCommand; import com.cloud.agent.api.NetworkRulesVmSecondaryIpCommand; +import com.cloud.agent.api.OvsCreateTunnelCommand; import com.cloud.agent.api.OvsDestroyBridgeCommand; import com.cloud.agent.api.OvsDestroyTunnelCommand; import com.cloud.agent.api.OvsFetchInterfaceCommand; @@ -2542,4 +2544,114 @@ public class LibvirtComputingResourceTest { verify(libvirtComputingResource, times(1)).findOrCreateTunnelNetwork(command.getBridgeName()); } + + @Test + public void testCheckOnHostCommand() { + final com.cloud.host.Host host = Mockito.mock(com.cloud.host.Host.class);; + + final CheckOnHostCommand command = new CheckOnHostCommand(host); + + final KVMHAMonitor monitor = Mockito.mock(KVMHAMonitor.class); + + when(libvirtComputingResource.getMonitor()).thenReturn(monitor); + + final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(command, libvirtComputingResource); + assertTrue(answer.getResult()); + + verify(libvirtComputingResource, times(1)).getMonitor(); + } + + @Test + public void testOvsCreateTunnelCommand() { + final String remoteIp = "172.16.16.16"; + final Integer key = 1; + final Long from = 1l; + final Long to = 2l; + final long networkId = 1l; + final String fromIp = "172.15.15.15"; + final String networkName = "eth"; + final String networkUuid = "8edb1156-a851-4914-afc6-468ee52ac861"; + + final OvsCreateTunnelCommand command = new OvsCreateTunnelCommand(remoteIp, key, from, to, networkId, fromIp, networkName, networkUuid); + + final String bridge = command.getNetworkName(); + + when(libvirtComputingResource.findOrCreateTunnelNetwork(bridge)).thenReturn(true); + when(libvirtComputingResource.configureTunnelNetwork(command.getNetworkId(), command.getFrom(), + command.getNetworkName())).thenReturn(true); + + final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(command, libvirtComputingResource); + assertTrue(answer.getResult()); + + verify(libvirtComputingResource, times(1)).findOrCreateTunnelNetwork(bridge); + verify(libvirtComputingResource, times(1)).configureTunnelNetwork(command.getNetworkId(), command.getFrom(), + command.getNetworkName()); + } + + @Test + public void testOvsCreateTunnelCommandFailure1() { + final String remoteIp = "172.16.16.16"; + final Integer key = 1; + final Long from = 1l; + final Long to = 2l; + final long networkId = 1l; + final String fromIp = "172.15.15.15"; + final String networkName = "eth"; + final String networkUuid = "8edb1156-a851-4914-afc6-468ee52ac861"; + + final OvsCreateTunnelCommand command = new OvsCreateTunnelCommand(remoteIp, key, from, to, networkId, fromIp, networkName, networkUuid); + + final String bridge = command.getNetworkName(); + + when(libvirtComputingResource.findOrCreateTunnelNetwork(bridge)).thenReturn(false); + when(libvirtComputingResource.configureTunnelNetwork(command.getNetworkId(), command.getFrom(), + command.getNetworkName())).thenReturn(true); + + final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(command, libvirtComputingResource); + assertFalse(answer.getResult()); + + verify(libvirtComputingResource, times(1)).findOrCreateTunnelNetwork(bridge); + verify(libvirtComputingResource, times(0)).configureTunnelNetwork(command.getNetworkId(), command.getFrom(), + command.getNetworkName()); + } + + @SuppressWarnings("unchecked") + @Test + public void testOvsCreateTunnelCommandFailure2() { + final String remoteIp = "172.16.16.16"; + final Integer key = 1; + final Long from = 1l; + final Long to = 2l; + final long networkId = 1l; + final String fromIp = "172.15.15.15"; + final String networkName = "eth"; + final String networkUuid = "8edb1156-a851-4914-afc6-468ee52ac861"; + + final OvsCreateTunnelCommand command = new OvsCreateTunnelCommand(remoteIp, key, from, to, networkId, fromIp, networkName, networkUuid); + + final String bridge = command.getNetworkName(); + + when(libvirtComputingResource.findOrCreateTunnelNetwork(bridge)).thenReturn(true); + when(libvirtComputingResource.configureTunnelNetwork(command.getNetworkId(), command.getFrom(), + command.getNetworkName())).thenThrow(Exception.class); + + final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(command, libvirtComputingResource); + assertFalse(answer.getResult()); + + verify(libvirtComputingResource, times(1)).findOrCreateTunnelNetwork(bridge); + verify(libvirtComputingResource, times(1)).configureTunnelNetwork(command.getNetworkId(), command.getFrom(), + command.getNetworkName()); + } } \ No newline at end of file