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 8b74b1c3b58..31a9ed71234 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 @@ -68,7 +68,6 @@ import com.cloud.agent.api.HostVmStateReportEntry; import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.PingRoutingCommand; import com.cloud.agent.api.PingRoutingWithNwGroupsCommand; -import com.cloud.agent.api.PvlanSetupCommand; import com.cloud.agent.api.SetupGuestNetworkCommand; import com.cloud.agent.api.StartAnswer; import com.cloud.agent.api.StartCommand; @@ -397,6 +396,18 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return _manageSnapshotPath; } + public String getGuestBridgeName() { + return _guestBridgeName; + } + + public String getOvsPvlanDhcpHostPath() { + return _ovsPvlanDhcpHostPath; + } + + public String getOvsPvlanVmPath() { + return _ovsPvlanVmPath; + } + private static final class KeyValueInterpreter extends OutputInterpreter { private final Map map = new HashMap(); @@ -1252,8 +1263,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return execute((ResizeVolumeCommand)cmd); } else if (cmd instanceof StorageSubSystemCommand) { return storageHandler.handleStorageCommands((StorageSubSystemCommand)cmd); - } else if (cmd instanceof PvlanSetupCommand) { - return execute((PvlanSetupCommand)cmd); } else { s_logger.warn("Unsupported command "); return Answer.createUnsupportedCommandAnswer(cmd); @@ -1519,61 +1528,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } } - private Answer execute(final PvlanSetupCommand cmd) { - final String primaryPvlan = cmd.getPrimary(); - final String isolatedPvlan = cmd.getIsolated(); - final String op = cmd.getOp(); - final String dhcpName = cmd.getDhcpName(); - final String dhcpMac = cmd.getDhcpMac(); - final String dhcpIp = cmd.getDhcpIp(); - final String vmMac = cmd.getVmMac(); - boolean add = true; - - String opr = "-A"; - if (op.equals("delete")) { - opr = "-D"; - add = false; - } - - String result = null; - Connect conn; - try { - if (cmd.getType() == PvlanSetupCommand.Type.DHCP) { - final Script script = new Script(_ovsPvlanDhcpHostPath, _timeout, s_logger); - if (add) { - conn = LibvirtConnection.getConnectionByVmName(dhcpName); - final List ifaces = getInterfaces(conn, dhcpName); - final InterfaceDef guestNic = ifaces.get(0); - script.add(opr, "-b", _guestBridgeName, "-p", primaryPvlan, "-i", isolatedPvlan, "-n", dhcpName, "-d", dhcpIp, "-m", dhcpMac, "-I", - guestNic.getDevName()); - } else { - script.add(opr, "-b", _guestBridgeName, "-p", primaryPvlan, "-i", isolatedPvlan, "-n", dhcpName, "-d", dhcpIp, "-m", dhcpMac); - } - result = script.execute(); - if (result != null) { - s_logger.warn("Failed to program pvlan for dhcp server with mac " + dhcpMac); - return new Answer(cmd, false, result); - } else { - s_logger.info("Programmed pvlan for dhcp server with mac " + dhcpMac); - } - } else if (cmd.getType() == PvlanSetupCommand.Type.VM) { - final Script script = new Script(_ovsPvlanVmPath, _timeout, s_logger); - script.add(opr, "-b", _guestBridgeName, "-p", primaryPvlan, "-i", isolatedPvlan, "-v", vmMac); - result = script.execute(); - if (result != null) { - s_logger.warn("Failed to program pvlan for vm with mac " + vmMac); - return new Answer(cmd, false, result); - } else { - s_logger.info("Programmed pvlan for vm with mac " + vmMac); - } - } - } catch (final LibvirtException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return new Answer(cmd, true, result); - } - private void VifHotPlug(final Connect conn, final String vmName, final String broadcastUri, final String macAddr) throws InternalErrorException, LibvirtException { final NicTO nicTO = new NicTO(); nicTO.setMac(macAddr); diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPvlanSetupCommandWrapper.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPvlanSetupCommandWrapper.java new file mode 100644 index 00000000000..7233723ae1a --- /dev/null +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPvlanSetupCommandWrapper.java @@ -0,0 +1,105 @@ +// +// 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 org.apache.log4j.Logger; +import org.libvirt.Connect; +import org.libvirt.LibvirtException; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.PvlanSetupCommand; +import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef; +import com.cloud.resource.CommandWrapper; +import com.cloud.utils.script.Script; + +public final class LibvirtPvlanSetupCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(LibvirtPvlanSetupCommandWrapper.class); + + @Override + public Answer execute(final PvlanSetupCommand command, final LibvirtComputingResource libvirtComputingResource) { + final String primaryPvlan = command.getPrimary(); + final String isolatedPvlan = command.getIsolated(); + final String op = command.getOp(); + final String dhcpName = command.getDhcpName(); + final String dhcpMac = command.getDhcpMac(); + final String dhcpIp = command.getDhcpIp(); + final String vmMac = command.getVmMac(); + boolean add = true; + + String opr = "-A"; + if (op.equals("delete")) { + opr = "-D"; + add = false; + } + + String result = null; + try { + final String guestBridgeName = libvirtComputingResource.getGuestBridgeName(); + final int timeout = libvirtComputingResource.getTimeout(); + + if (command.getType() == PvlanSetupCommand.Type.DHCP) { + final String ovsPvlanDhcpHostPath = libvirtComputingResource.getOvsPvlanDhcpHostPath(); + final Script script = new Script(ovsPvlanDhcpHostPath, timeout, s_logger); + + if (add) { + final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper(); + final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(dhcpName); + + final List ifaces = libvirtComputingResource.getInterfaces(conn, dhcpName); + final InterfaceDef guestNic = ifaces.get(0); + script.add(opr, "-b", guestBridgeName, "-p", primaryPvlan, "-i", isolatedPvlan, "-n", dhcpName, "-d", dhcpIp, "-m", dhcpMac, "-I", + guestNic.getDevName()); + } else { + script.add(opr, "-b", guestBridgeName, "-p", primaryPvlan, "-i", isolatedPvlan, "-n", dhcpName, "-d", dhcpIp, "-m", dhcpMac); + } + + result = script.execute(); + + if (result != null) { + s_logger.warn("Failed to program pvlan for dhcp server with mac " + dhcpMac); + return new Answer(command, false, result); + } else { + s_logger.info("Programmed pvlan for dhcp server with mac " + dhcpMac); + } + } else if (command.getType() == PvlanSetupCommand.Type.VM) { + final String ovsPvlanVmPath = libvirtComputingResource.getOvsPvlanVmPath(); + + final Script script = new Script(ovsPvlanVmPath, timeout, s_logger); + script.add(opr, "-b", guestBridgeName, "-p", primaryPvlan, "-i", isolatedPvlan, "-v", vmMac); + result = script.execute(); + + if (result != null) { + s_logger.warn("Failed to program pvlan for vm with mac " + vmMac); + return new Answer(command, false, result); + } else { + s_logger.info("Programmed pvlan for vm with mac " + vmMac); + } + } + } catch (final LibvirtException e) { + s_logger.error("Error whislt executing OVS Setup command! ==> " + e.getMessage()); + return new Answer(command, false, e.getMessage()); + } + return new Answer(command, true, result); + } +} \ 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 1ee14a1dfe9..c103ef397b8 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 @@ -59,6 +59,7 @@ import com.cloud.agent.api.OvsVpcRoutingPolicyConfigCommand; import com.cloud.agent.api.PingTestCommand; import com.cloud.agent.api.PlugNicCommand; import com.cloud.agent.api.PrepareForMigrationCommand; +import com.cloud.agent.api.PvlanSetupCommand; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.RebootRouterCommand; @@ -146,6 +147,7 @@ public class LibvirtRequestWrapper extends RequestWrapper { linbvirtCommands.put(BackupSnapshotCommand.class, new LibvirtBackupSnapshotCommandWrapper()); linbvirtCommands.put(CreatePrivateTemplateFromSnapshotCommand.class, new LibvirtCreatePrivateTemplateFromSnapshotCommandWrapper()); linbvirtCommands.put(CopyVolumeCommand.class, new LibvirtCopyVolumeCommandWrapper()); + linbvirtCommands.put(PvlanSetupCommand.class, new LibvirtPvlanSetupCommandWrapper()); 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 86ff007917c..ad75b532751 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 @@ -31,6 +31,7 @@ import static org.mockito.Mockito.when; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; +import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; @@ -54,6 +55,7 @@ import org.libvirt.Connect; import org.libvirt.Domain; import org.libvirt.DomainBlockStats; import org.libvirt.DomainInfo; +import org.libvirt.DomainInfo.DomainState; import org.libvirt.DomainInterfaceStats; import org.libvirt.LibvirtException; import org.libvirt.NodeInfo; @@ -107,6 +109,7 @@ import com.cloud.agent.api.OvsVpcRoutingPolicyConfigCommand.Acl; import com.cloud.agent.api.PingTestCommand; import com.cloud.agent.api.PlugNicCommand; import com.cloud.agent.api.PrepareForMigrationCommand; +import com.cloud.agent.api.PvlanSetupCommand; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.RebootRouterCommand; @@ -504,10 +507,13 @@ public class LibvirtComputingResourceTest { } @Test - public void testStopCommandCheck() { + public void testStopCommandCheckVmNOTRunning() { final Connect conn = Mockito.mock(Connect.class); final LibvirtUtilitiesHelper libvirtUtilitiesHelper = Mockito.mock(LibvirtUtilitiesHelper.class); - final Domain domain = Mockito.mock(Domain.class); + final Domain vm = Mockito.mock(Domain.class); + final DomainInfo info = Mockito.mock(DomainInfo.class); + final DomainState state = DomainInfo.DomainState.VIR_DOMAIN_SHUTDOWN; + info.state = state; final String vmName = "Test"; final StopCommand command = new StopCommand(vmName, false, true); @@ -515,7 +521,10 @@ public class LibvirtComputingResourceTest { when(libvirtComputingResource.getLibvirtUtilitiesHelper()).thenReturn(libvirtUtilitiesHelper); try { when(libvirtUtilitiesHelper.getConnectionByVmName(vmName)).thenReturn(conn); - when(conn.domainLookupByName(command.getVmName())).thenReturn(domain); + when(conn.domainLookupByName(command.getVmName())).thenReturn(vm); + + when(vm.getInfo()).thenReturn(info); + } catch (final LibvirtException e) { fail(e.getMessage()); } @@ -535,6 +544,83 @@ public class LibvirtComputingResourceTest { } } + @SuppressWarnings("unchecked") + @Test + public void testStopCommandCheckException1() { + final Connect conn = Mockito.mock(Connect.class); + final LibvirtUtilitiesHelper libvirtUtilitiesHelper = Mockito.mock(LibvirtUtilitiesHelper.class); + final Domain vm = Mockito.mock(Domain.class); + final DomainInfo info = Mockito.mock(DomainInfo.class); + final DomainState state = DomainInfo.DomainState.VIR_DOMAIN_RUNNING; + info.state = state; + + final String vmName = "Test"; + final StopCommand command = new StopCommand(vmName, false, true); + + when(libvirtComputingResource.getLibvirtUtilitiesHelper()).thenReturn(libvirtUtilitiesHelper); + try { + when(libvirtUtilitiesHelper.getConnectionByVmName(vmName)).thenThrow(LibvirtException.class); + when(conn.domainLookupByName(command.getVmName())).thenReturn(vm); + + when(vm.getInfo()).thenReturn(info); + + } 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)).getLibvirtUtilitiesHelper(); + try { + verify(libvirtUtilitiesHelper, times(2)).getConnectionByVmName(vmName); + } catch (final LibvirtException e) { + fail(e.getMessage()); + } + } + + @Test + public void testStopCommandCheckVmRunning() { + final Connect conn = Mockito.mock(Connect.class); + final LibvirtUtilitiesHelper libvirtUtilitiesHelper = Mockito.mock(LibvirtUtilitiesHelper.class); + final Domain vm = Mockito.mock(Domain.class); + final DomainInfo info = Mockito.mock(DomainInfo.class); + final DomainState state = DomainInfo.DomainState.VIR_DOMAIN_RUNNING; + info.state = state; + + final String vmName = "Test"; + final StopCommand command = new StopCommand(vmName, false, true); + + when(libvirtComputingResource.getLibvirtUtilitiesHelper()).thenReturn(libvirtUtilitiesHelper); + try { + when(libvirtUtilitiesHelper.getConnectionByVmName(vmName)).thenReturn(conn); + when(conn.domainLookupByName(command.getVmName())).thenReturn(vm); + + when(vm.getInfo()).thenReturn(info); + + } 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)).getLibvirtUtilitiesHelper(); + try { + verify(libvirtUtilitiesHelper, times(1)).getConnectionByVmName(vmName); + } catch (final LibvirtException e) { + fail(e.getMessage()); + } + } + @Test public void testGetVmStatsCommand() { final Connect conn = Mockito.mock(Connect.class); @@ -4098,4 +4184,148 @@ public class LibvirtComputingResourceTest { verify(libvirtComputingResource, times(1)).getStoragePoolMgr(); } + + @Test + public void testPvlanSetupCommandDhcpAdd() { + final String op = "add"; + final URI uri = URI.create("http://localhost"); + final String networkTag = "/105"; + final String dhcpName = "dhcp"; + final String dhcpMac = "00:00:00:00"; + final String dhcpIp = "172.10.10.10"; + + final PvlanSetupCommand command = PvlanSetupCommand.createDhcpSetup(op, uri, networkTag, dhcpName, dhcpMac, dhcpIp); + + final LibvirtUtilitiesHelper libvirtUtilitiesHelper = Mockito.mock(LibvirtUtilitiesHelper.class); + final Connect conn = Mockito.mock(Connect.class); + + final String guestBridgeName = "br0"; + when(libvirtComputingResource.getGuestBridgeName()).thenReturn(guestBridgeName); + + final int timeout = 0; + when(libvirtComputingResource.getTimeout()).thenReturn(timeout); + final String ovsPvlanDhcpHostPath = "/pvlan"; + when(libvirtComputingResource.getOvsPvlanDhcpHostPath()).thenReturn(ovsPvlanDhcpHostPath); + when(libvirtComputingResource.getLibvirtUtilitiesHelper()).thenReturn(libvirtUtilitiesHelper); + + final List ifaces = new ArrayList(); + final InterfaceDef nic = Mockito.mock(InterfaceDef.class); + ifaces.add(nic); + + try { + when(libvirtUtilitiesHelper.getConnectionByVmName(dhcpName)).thenReturn(conn); + when(libvirtComputingResource.getInterfaces(conn, dhcpName)).thenReturn(ifaces); + } 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)).getLibvirtUtilitiesHelper(); + try { + verify(libvirtUtilitiesHelper, times(1)).getConnectionByVmName(dhcpName); + } catch (final LibvirtException e) { + fail(e.getMessage()); + } + } + + @Test + public void testPvlanSetupCommandVm() { + final String op = "add"; + final URI uri = URI.create("http://localhost"); + final String networkTag = "/105"; + final String vmMac = "00:00:00:00"; + + final PvlanSetupCommand command = PvlanSetupCommand.createVmSetup(op, uri, networkTag, vmMac); + + final String guestBridgeName = "br0"; + when(libvirtComputingResource.getGuestBridgeName()).thenReturn(guestBridgeName); + final int timeout = 0; + when(libvirtComputingResource.getTimeout()).thenReturn(timeout); + + final String ovsPvlanVmPath = "/pvlan"; + when(libvirtComputingResource.getOvsPvlanVmPath()).thenReturn(ovsPvlanVmPath); + + final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(command, libvirtComputingResource); + assertFalse(answer.getResult()); + } + + @SuppressWarnings("unchecked") + @Test + public void testPvlanSetupCommandDhcpException() { + final String op = "add"; + final URI uri = URI.create("http://localhost"); + final String networkTag = "/105"; + final String dhcpName = "dhcp"; + final String dhcpMac = "00:00:00:00"; + final String dhcpIp = "172.10.10.10"; + + final PvlanSetupCommand command = PvlanSetupCommand.createDhcpSetup(op, uri, networkTag, dhcpName, dhcpMac, dhcpIp); + + final LibvirtUtilitiesHelper libvirtUtilitiesHelper = Mockito.mock(LibvirtUtilitiesHelper.class); + + final String guestBridgeName = "br0"; + when(libvirtComputingResource.getGuestBridgeName()).thenReturn(guestBridgeName); + + final int timeout = 0; + when(libvirtComputingResource.getTimeout()).thenReturn(timeout); + final String ovsPvlanDhcpHostPath = "/pvlan"; + when(libvirtComputingResource.getOvsPvlanDhcpHostPath()).thenReturn(ovsPvlanDhcpHostPath); + when(libvirtComputingResource.getLibvirtUtilitiesHelper()).thenReturn(libvirtUtilitiesHelper); + + try { + when(libvirtUtilitiesHelper.getConnectionByVmName(dhcpName)).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)).getLibvirtUtilitiesHelper(); + try { + verify(libvirtUtilitiesHelper, times(1)).getConnectionByVmName(dhcpName); + } catch (final LibvirtException e) { + fail(e.getMessage()); + } + } + + @Test + public void testPvlanSetupCommandDhcpDelete() { + final String op = "delete"; + final URI uri = URI.create("http://localhost"); + final String networkTag = "/105"; + final String dhcpName = "dhcp"; + final String dhcpMac = "00:00:00:00"; + final String dhcpIp = "172.10.10.10"; + + final PvlanSetupCommand command = PvlanSetupCommand.createDhcpSetup(op, uri, networkTag, dhcpName, dhcpMac, dhcpIp); + + final LibvirtUtilitiesHelper libvirtUtilitiesHelper = Mockito.mock(LibvirtUtilitiesHelper.class); + + final String guestBridgeName = "br0"; + when(libvirtComputingResource.getGuestBridgeName()).thenReturn(guestBridgeName); + + final int timeout = 0; + when(libvirtComputingResource.getTimeout()).thenReturn(timeout); + final String ovsPvlanDhcpHostPath = "/pvlan"; + when(libvirtComputingResource.getOvsPvlanDhcpHostPath()).thenReturn(ovsPvlanDhcpHostPath); + when(libvirtComputingResource.getLibvirtUtilitiesHelper()).thenReturn(libvirtUtilitiesHelper); + + final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance(); + assertNotNull(wrapper); + + final Answer answer = wrapper.execute(command, libvirtComputingResource); + assertFalse(answer.getResult()); + } } \ No newline at end of file