diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56FP1Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56FP1Resource.java index 26f148e57c4..11435283a23 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56FP1Resource.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56FP1Resource.java @@ -18,32 +18,22 @@ package com.cloud.hypervisor.xenserver.resource; import java.io.File; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import javax.ejb.Local; -import org.apache.log4j.Logger; import org.apache.xmlrpc.XmlRpcException; -import com.cloud.agent.api.FenceAnswer; -import com.cloud.agent.api.FenceCommand; import com.cloud.resource.ServerResource; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.Script; import com.xensource.xenapi.Connection; import com.xensource.xenapi.Host; import com.xensource.xenapi.Types.XenAPIException; -import com.xensource.xenapi.VBD; -import com.xensource.xenapi.VDI; -import com.xensource.xenapi.VM; @Local(value = ServerResource.class) public class XenServer56FP1Resource extends XenServer56Resource { - private static final long mem_128m = 134217728L; - private static final Logger s_logger = Logger.getLogger(XenServer56FP1Resource.class); public XenServer56FP1Resource() { super(); @@ -62,52 +52,6 @@ public class XenServer56FP1Resource extends XenServer56Resource { return files; } - @Override - protected FenceAnswer execute(final FenceCommand cmd) { - final Connection conn = getConnection(); - try { - final Boolean alive = checkHeartbeat(cmd.getHostGuid()); - if ( alive == null ) { - s_logger.debug("Failed to check heartbeat, so unable to fence"); - return new FenceAnswer(cmd, false, "Failed to check heartbeat, so unable to fence"); - } - if ( alive ) { - s_logger.debug("Heart beat is still going so unable to fence"); - return new FenceAnswer(cmd, false, "Heartbeat is still going on unable to fence"); - } - final Set vms = VM.getByNameLabel(conn, cmd.getVmName()); - for (final VM vm : vms) { - final Set vdis = new HashSet(); - final Set vbds = vm.getVBDs(conn); - for (final VBD vbd : vbds) { - final VDI vdi = vbd.getVDI(conn); - if (!isRefNull(vdi)) { - vdis.add(vdi); - } - } - s_logger.info("Fence command for VM " + cmd.getVmName()); - vm.powerStateReset(conn); - vm.destroy(conn); - for (final VDI vdi : vdis) { - final Map smConfig = vdi.getSmConfig(conn); - for (final String key : smConfig.keySet()) { - if (key.startsWith("host_")) { - vdi.removeFromSmConfig(conn, key); - break; - } - } - } - } - return new FenceAnswer(cmd); - } catch (final XmlRpcException e) { - s_logger.warn("Unable to fence", e); - return new FenceAnswer(cmd, false, e.getMessage()); - } catch (final XenAPIException e) { - s_logger.warn("Unable to fence", e); - return new FenceAnswer(cmd, false, e.getMessage()); - } - } - /** * When Dynamic Memory Control (DMC) is enabled - * xenserver allows scaling the guest memory while the guest is running diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56Resource.java index 85cdf04ac3b..3a9baf115e3 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56Resource.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56Resource.java @@ -19,7 +19,6 @@ package com.cloud.hypervisor.xenserver.resource; import java.io.File; import java.util.ArrayList; import java.util.List; -import java.util.Set; import javax.ejb.Local; @@ -28,8 +27,6 @@ import org.apache.xmlrpc.XmlRpcException; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; -import com.cloud.agent.api.FenceAnswer; -import com.cloud.agent.api.FenceCommand; import com.cloud.agent.api.NetworkUsageAnswer; import com.cloud.agent.api.NetworkUsageCommand; import com.cloud.agent.api.StartupCommand; @@ -46,7 +43,6 @@ import com.xensource.xenapi.PIF; import com.xensource.xenapi.Types.IpConfigurationMode; import com.xensource.xenapi.Types.XenAPIException; import com.xensource.xenapi.VLAN; -import com.xensource.xenapi.VM; @Local(value = ServerResource.class) public class XenServer56Resource extends CitrixResourceBase { @@ -63,9 +59,7 @@ public class XenServer56Resource extends CitrixResourceBase { // Ignore this for now. Still working on converting the other commands. } - if (cmd instanceof FenceCommand) { - return execute((FenceCommand) cmd); - } else if (cmd instanceof NetworkUsageCommand) { + if (cmd instanceof NetworkUsageCommand) { return execute((NetworkUsageCommand) cmd); } else { return super.executeRequest(cmd); @@ -238,34 +232,6 @@ public class XenServer56Resource extends CitrixResourceBase { } } - protected FenceAnswer execute(final FenceCommand cmd) { - final Connection conn = getConnection(); - try { - final Boolean alive = checkHeartbeat(cmd.getHostGuid()); - if (alive == null) { - s_logger.debug("Failed to check heartbeat, so unable to fence"); - return new FenceAnswer(cmd, false, "Failed to check heartbeat, so unable to fence"); - } - if (alive) { - s_logger.debug("Heart beat is still going so unable to fence"); - return new FenceAnswer(cmd, false, "Heartbeat is still going on unable to fence"); - } - final Set vms = VM.getByNameLabel(conn, cmd.getVmName()); - for (final VM vm : vms) { - s_logger.info("Fence command for VM " + cmd.getVmName()); - vm.powerStateReset(conn); - vm.destroy(conn); - } - return new FenceAnswer(cmd); - } catch (final XmlRpcException e) { - s_logger.warn("Unable to fence", e); - return new FenceAnswer(cmd, false, e.getMessage()); - } catch (final XenAPIException e) { - s_logger.warn("Unable to fence", e); - return new FenceAnswer(cmd, false, e.getMessage()); - } - } - @Override public boolean transferManagementNetwork(final Connection conn, final Host host, final PIF src, final PIF.Record spr, final PIF dest) throws XmlRpcException, XenAPIException { dest.reconfigureIp(conn, spr.ipConfigurationMode, spr.IP, spr.netmask, spr.gateway, spr.DNS); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapper.java index 05caabd1d4a..a5ca115cd8c 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapper.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapper.java @@ -35,6 +35,7 @@ import com.cloud.agent.api.CreateStoragePoolCommand; import com.cloud.agent.api.CreateVMSnapshotCommand; import com.cloud.agent.api.DeleteStoragePoolCommand; import com.cloud.agent.api.DeleteVMSnapshotCommand; +import com.cloud.agent.api.FenceCommand; import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.GetStorageStatsCommand; import com.cloud.agent.api.GetVmDiskStatsCommand; @@ -82,6 +83,7 @@ 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.xenserver.resource.CitrixResourceBase; +import com.cloud.hypervisor.xenserver.resource.XenServer56FP1Resource; import com.cloud.hypervisor.xenserver.resource.XenServer56Resource; import com.cloud.resource.CommandWrapper; import com.cloud.resource.RequestWrapper; @@ -173,8 +175,14 @@ public class CitrixRequestWrapper extends RequestWrapper { // XenServer56Resource commands final Hashtable, CommandWrapper> xenServer56Commands = new Hashtable, CommandWrapper>(); xenServer56Commands.put(CheckOnHostCommand.class, new XenServer56CheckOnHostCommandWrapper()); + xenServer56Commands.put(FenceCommand.class, new XenServer56FenceCommandWrapper()); resources.put(XenServer56Resource.class, xenServer56Commands); + // XenServer56FP1Resource commands + final Hashtable, CommandWrapper> xenServer56P1Commands = new Hashtable, CommandWrapper>(); + xenServer56P1Commands.put(FenceCommand.class, new XenServer56FP1FenceCommandWrapper()); + resources.put(XenServer56FP1Resource.class, xenServer56P1Commands); + initialised = true; } diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56FP1FenceCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56FP1FenceCommandWrapper.java new file mode 100644 index 00000000000..b169636cb4a --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56FP1FenceCommandWrapper.java @@ -0,0 +1,92 @@ +// +// 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.xenserver.resource.wrapper; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.FenceAnswer; +import com.cloud.agent.api.FenceCommand; +import com.cloud.hypervisor.xenserver.resource.XenServer56Resource; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VBD; +import com.xensource.xenapi.VDI; +import com.xensource.xenapi.VM; + +public final class XenServer56FP1FenceCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(XenServer56FP1FenceCommandWrapper.class); + + @Override + public Answer execute(final FenceCommand command, final XenServer56Resource xenServer56) { + final Connection conn = xenServer56.getConnection(); + try { + final Boolean alive = xenServer56.checkHeartbeat(command.getHostGuid()); + if ( alive == null ) { + s_logger.debug("Failed to check heartbeat, so unable to fence"); + return new FenceAnswer(command, false, "Failed to check heartbeat, so unable to fence"); + } + if ( alive ) { + s_logger.debug("Heart beat is still going so unable to fence"); + return new FenceAnswer(command, false, "Heartbeat is still going on unable to fence"); + } + final Set vms = VM.getByNameLabel(conn, command.getVmName()); + for (final VM vm : vms) { + final Set vdis = new HashSet(); + final Set vbds = vm.getVBDs(conn); + for (final VBD vbd : vbds) { + final VDI vdi = vbd.getVDI(conn); + if (!xenServer56.isRefNull(vdi)) { + vdis.add(vdi); + } + } + s_logger.info("Fence command for VM " + command.getVmName()); + vm.powerStateReset(conn); + vm.destroy(conn); + for (final VDI vdi : vdis) { + final Map smConfig = vdi.getSmConfig(conn); + for (final String key : smConfig.keySet()) { + if (key.startsWith("host_")) { + vdi.removeFromSmConfig(conn, key); + break; + } + } + } + } + return new FenceAnswer(command); + } catch (final XmlRpcException e) { + s_logger.warn("Unable to fence", e); + return new FenceAnswer(command, false, e.getMessage()); + } catch (final XenAPIException e) { + s_logger.warn("Unable to fence", e); + return new FenceAnswer(command, false, e.getMessage()); + } catch (final Exception e) { + s_logger.warn("Unable to fence", e); + return new FenceAnswer(command, false, e.getMessage()); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56FenceCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56FenceCommandWrapper.java new file mode 100644 index 00000000000..ece3329594d --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56FenceCommandWrapper.java @@ -0,0 +1,71 @@ +// +// 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.xenserver.resource.wrapper; + +import java.util.Set; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.FenceAnswer; +import com.cloud.agent.api.FenceCommand; +import com.cloud.hypervisor.xenserver.resource.XenServer56Resource; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VM; + +public final class XenServer56FenceCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(XenServer56FenceCommandWrapper.class); + + @Override + public Answer execute(final FenceCommand command, final XenServer56Resource xenServer56) { + final Connection conn = xenServer56.getConnection(); + try { + final Boolean alive = xenServer56.checkHeartbeat(command.getHostGuid()); + if (alive == null) { + s_logger.debug("Failed to check heartbeat, so unable to fence"); + return new FenceAnswer(command, false, "Failed to check heartbeat, so unable to fence"); + } + if (alive) { + s_logger.debug("Heart beat is still going so unable to fence"); + return new FenceAnswer(command, false, "Heartbeat is still going on unable to fence"); + } + final Set vms = VM.getByNameLabel(conn, command.getVmName()); + for (final VM vm : vms) { + s_logger.info("Fence command for VM " + command.getVmName()); + vm.powerStateReset(conn); + vm.destroy(conn); + } + return new FenceAnswer(command); + } catch (final XmlRpcException e) { + s_logger.warn("Unable to fence", e); + return new FenceAnswer(command, false, e.getMessage()); + } catch (final XenAPIException e) { + s_logger.warn("Unable to fence", e); + return new FenceAnswer(command, false, e.getMessage()); + } catch (final Exception e) { + s_logger.warn("Unable to fence", e); + return new FenceAnswer(command, false, e.getMessage()); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/test/com/cloud/ha/XenServerFencerTest.java b/plugins/hypervisors/xenserver/test/com/cloud/ha/XenServerFencerTest.java deleted file mode 100644 index bd1d8f80b23..00000000000 --- a/plugins/hypervisors/xenserver/test/com/cloud/ha/XenServerFencerTest.java +++ /dev/null @@ -1,39 +0,0 @@ -// 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.ha; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - - -public class XenServerFencerTest { - - @Test - public void testSetAndGetName() throws Exception { - XenServerFencer xenServerFencer = new XenServerFencer(); - String name = "name"; - - xenServerFencer.setName(name); - String actual = xenServerFencer.getName(); - - assertEquals(name, actual); - - } - -} diff --git a/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56FP1WrapperTest.java b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56FP1WrapperTest.java new file mode 100644 index 00000000000..578302ecb4d --- /dev/null +++ b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56FP1WrapperTest.java @@ -0,0 +1,49 @@ +package com.cloud.hypervisor.xenserver.resource.wrapper; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.powermock.modules.junit4.PowerMockRunner; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.FenceCommand; +import com.cloud.host.Host; +import com.cloud.hypervisor.xenserver.resource.XenServer56FP1Resource; +import com.cloud.vm.VMInstanceVO; +import com.xensource.xenapi.Connection; + +@RunWith(PowerMockRunner.class) +public class XenServer56FP1WrapperTest { + + @Mock + private XenServer56FP1Resource xenServer56Resource; + + @Test + public void testFenceCommand() { + final VMInstanceVO vm = Mockito.mock(VMInstanceVO.class); + final Host host = Mockito.mock(Host.class); + + final Connection conn = Mockito.mock(Connection.class); + + final FenceCommand fenceCommand = new FenceCommand(vm, host); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(xenServer56Resource.getConnection()).thenReturn(conn); + + final Answer answer = wrapper.execute(fenceCommand, xenServer56Resource); + + verify(xenServer56Resource, times(1)).getConnection(); + verify(xenServer56Resource, times(1)).checkHeartbeat(fenceCommand.getHostGuid()); + + assertFalse(answer.getResult()); + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56WrapperTest.java b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56WrapperTest.java index b8f43df7268..f93a83635e4 100644 --- a/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56WrapperTest.java +++ b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer56WrapperTest.java @@ -1,23 +1,27 @@ package com.cloud.hypervisor.xenserver.resource.wrapper; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import com.cloud.agent.api.Answer; import com.cloud.agent.api.CheckOnHostCommand; +import com.cloud.agent.api.FenceCommand; +import com.cloud.host.Host; import com.cloud.hypervisor.xenserver.resource.XenServer56Resource; +import com.cloud.vm.VMInstanceVO; import com.xensource.xenapi.Connection; -import com.xensource.xenapi.Host; @RunWith(PowerMockRunner.class) -@PrepareForTest({ Connection.class, Host.Record.class }) public class XenServer56WrapperTest { @Mock @@ -35,4 +39,26 @@ public class XenServer56WrapperTest { assertTrue(answer.getResult()); } -} + + @Test + public void testFenceCommand() { + final VMInstanceVO vm = Mockito.mock(VMInstanceVO.class); + final Host host = Mockito.mock(Host.class); + + final Connection conn = Mockito.mock(Connection.class); + + final FenceCommand fenceCommand = new FenceCommand(vm, host); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(xenServer56Resource.getConnection()).thenReturn(conn); + + final Answer answer = wrapper.execute(fenceCommand, xenServer56Resource); + + verify(xenServer56Resource, times(1)).getConnection(); + verify(xenServer56Resource, times(1)).checkHeartbeat(fenceCommand.getHostGuid()); + + assertFalse(answer.getResult()); + } +} \ No newline at end of file