From 751c14b929c1f9a7e703f2a1fa0d46ca0ca8fe6f Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Mon, 30 Mar 2015 15:18:46 +0200 Subject: [PATCH] Refactoring CleanupNetworkRulesCmd, OvsCreateGreTunnelCommand, OvsDeleteFlowCommand, OvsVpcPhysicalTopologyConfigCommand and OvsVpcRoutingPolicyConfigCommand in order to cope with the new design. - Meny new unit tests added that cover more than the basics! --- .../resource/CitrixResourceBase.java | 22 +- .../CitrixCleanupNetworkRulesCmdWrapper.java | 54 ++++ ...itrixOvsCreateGreTunnelCommandWrapper.java | 67 +++++ .../CitrixOvsDeleteFlowCommandWrapper.java | 62 ++++ ...cPhysicalTopologyConfigCommandWrapper.java | 57 ++++ ...sVpcRoutingPolicyConfigCommandWrapper.java | 57 ++++ .../wrapper/CitrixRequestWrapper.java | 10 + .../wrapper/CitrixRequestWrapperTest.java | 264 +++++++++++++++++- 8 files changed, 578 insertions(+), 15 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCleanupNetworkRulesCmdWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsCreateGreTunnelCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsDeleteFlowCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsVpcPhysicalTopologyConfigCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsVpcRoutingPolicyConfigCommandWrapper.java diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java index 4477a701e54..c1705c0ce8e 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java @@ -259,8 +259,12 @@ import com.xensource.xenapi.XenAPIObject; */ @Local(value = ServerResource.class) public abstract class CitrixResourceBase implements ServerResource, HypervisorResource, VirtualRouterDeployer { + private static final Logger s_logger = Logger.getLogger(CitrixResourceBase.class); + + static final Random Rand = new Random(System.currentTimeMillis()); protected static final XenServerConnectionPool ConnPool = XenServerConnectionPool.getInstance(); + protected String _name; protected String _username; protected Queue _password = new LinkedList(); @@ -278,9 +282,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected int _wait; protected int _migratewait; protected String _instance; //instance name (default is usually "VM") - static final Random Rand = new Random(System.currentTimeMillis()); protected boolean _securityGroupEnabled; - protected IAgentControl _agentControl; final int _maxWeight = 256; @@ -340,6 +342,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return _host; } + public String getVMInstanceName() { + return _instance; + } + public boolean isOvs() { return _isOvs; } @@ -461,16 +467,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (cmd instanceof NetworkElementCommand) { return _vrResource.executeRequest((NetworkElementCommand)cmd); - } else if (clazz == OvsCreateGreTunnelCommand.class) { - return execute((OvsCreateGreTunnelCommand)cmd); - } else if (clazz == OvsDeleteFlowCommand.class) { - return execute((OvsDeleteFlowCommand)cmd); - } else if (clazz == OvsVpcPhysicalTopologyConfigCommand.class) { - return execute((OvsVpcPhysicalTopologyConfigCommand) cmd); - } else if (clazz == OvsVpcRoutingPolicyConfigCommand.class) { - return execute((OvsVpcRoutingPolicyConfigCommand) cmd); - } else if (clazz == CleanupNetworkRulesCmd.class) { - return execute((CleanupNetworkRulesCmd)cmd); } else if (clazz == NetworkRulesSystemVmCommand.class) { return execute((NetworkRulesSystemVmCommand)cmd); } else if (clazz == OvsCreateTunnelCommand.class) { @@ -889,7 +885,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe /** * This method just creates a XenServer network following the tunnel network naming convention */ - private synchronized Network findOrCreateTunnelNetwork(final Connection conn, final String nwName) { + public synchronized Network findOrCreateTunnelNetwork(final Connection conn, final String nwName) { try { Network nw = null; final Network.Record rec = new Network.Record(); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCleanupNetworkRulesCmdWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCleanupNetworkRulesCmdWrapper.java new file mode 100644 index 00000000000..471c1e8a9eb --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixCleanupNetworkRulesCmdWrapper.java @@ -0,0 +1,54 @@ +// +// 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 org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CleanupNetworkRulesCmd; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; + +public final class CitrixCleanupNetworkRulesCmdWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixCleanupNetworkRulesCmdWrapper.class); + + @Override + public Answer execute(final CleanupNetworkRulesCmd command, final CitrixResourceBase citrixResourceBase) { + if (!citrixResourceBase.canBridgeFirewall()) { + return new Answer(command, true, null); + } + final Connection conn = citrixResourceBase.getConnection(); + + final String result = citrixResourceBase.callHostPlugin(conn, "vmops", "cleanup_rules", "instance", citrixResourceBase.getVMInstanceName()); + final int numCleaned = Integer.parseInt(result); + + if (result == null || result.isEmpty() || numCleaned < 0) { + s_logger.warn("Failed to cleanup rules for host " + citrixResourceBase.getHost().getIp()); + return new Answer(command, false, result); + } + + if (numCleaned > 0) { + s_logger.info("Cleaned up rules for " + result + " vms on host " + citrixResourceBase.getHost().getIp()); + } + return new Answer(command, true, result); + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsCreateGreTunnelCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsCreateGreTunnelCommandWrapper.java new file mode 100644 index 00000000000..c944e9a16df --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsCreateGreTunnelCommandWrapper.java @@ -0,0 +1,67 @@ +// +// 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 org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.OvsCreateGreTunnelAnswer; +import com.cloud.agent.api.OvsCreateGreTunnelCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Network; +import com.xensource.xenapi.Types.BadServerResponse; +import com.xensource.xenapi.Types.XenAPIException; + +public final class CitrixOvsCreateGreTunnelCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixOvsCreateGreTunnelCommandWrapper.class); + + @Override + public Answer execute(final OvsCreateGreTunnelCommand command, final CitrixResourceBase citrixResourceBase) { + citrixResourceBase.setIsOvs(true); + + final Connection conn = citrixResourceBase.getConnection(); + String bridge = "unkonwn"; + try { + final Network nw = citrixResourceBase.setupvSwitchNetwork(conn); + bridge = nw.getBridge(conn); + + final String result = citrixResourceBase.callHostPlugin(conn, "ovsgre", "ovs_create_gre", "bridge", bridge, "remoteIP", command.getRemoteIp(), "greKey", + command.getKey(), "from", Long.toString(command.getFrom()), "to", Long.toString(command.getTo())); + final String[] res = result.split(":"); + if (res.length != 2 || res.length == 2 && res[1].equalsIgnoreCase("[]")) { + return new OvsCreateGreTunnelAnswer(command, false, result, citrixResourceBase.getHost().getIp(), bridge); + } else { + return new OvsCreateGreTunnelAnswer(command, true, result, citrixResourceBase.getHost().getIp(), bridge, Integer.parseInt(res[1])); + } + } catch (final BadServerResponse e) { + s_logger.error("An error occurred while creating a GRE tunnel to " + command.getRemoteIp() + " on host " + citrixResourceBase.getHost().getIp(), e); + } catch (final XenAPIException e) { + s_logger.error("An error occurred while creating a GRE tunnel to " + command.getRemoteIp() + " on host " + citrixResourceBase.getHost().getIp(), e); + } catch (final XmlRpcException e) { + s_logger.error("An error occurred while creating a GRE tunnel to " + command.getRemoteIp() + " on host " + citrixResourceBase.getHost().getIp(), e); + } + + return new OvsCreateGreTunnelAnswer(command, false, "EXCEPTION", citrixResourceBase.getHost().getIp(), bridge); + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsDeleteFlowCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsDeleteFlowCommandWrapper.java new file mode 100644 index 00000000000..e96f1364b37 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsDeleteFlowCommandWrapper.java @@ -0,0 +1,62 @@ +// +// 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 org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.OvsDeleteFlowCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Network; +import com.xensource.xenapi.Types.BadServerResponse; +import com.xensource.xenapi.Types.XenAPIException; + +public final class CitrixOvsDeleteFlowCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixOvsDeleteFlowCommandWrapper.class); + + @Override + public Answer execute(final OvsDeleteFlowCommand command, final CitrixResourceBase citrixResourceBase) { + citrixResourceBase.setIsOvs(true); + + final Connection conn = citrixResourceBase.getConnection(); + try { + final Network nw = citrixResourceBase.setupvSwitchNetwork(conn); + final String bridge = nw.getBridge(conn); + final String result = citrixResourceBase.callHostPlugin(conn, "ovsgre", "ovs_delete_flow", "bridge", bridge, "vmName", command.getVmName()); + + if (result.equalsIgnoreCase("SUCCESS")) { + return new Answer(command, true, "success to delete flows for " + command.getVmName()); + } else { + return new Answer(command, false, result); + } + } catch (final BadServerResponse e) { + s_logger.error("Failed to delete flow", e); + } catch (final XenAPIException e) { + s_logger.error("Failed to delete flow", e); + } catch (final XmlRpcException e) { + s_logger.error("Failed to delete flow", e); + } + return new Answer(command, false, "failed to delete flow for " + command.getVmName()); + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsVpcPhysicalTopologyConfigCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsVpcPhysicalTopologyConfigCommandWrapper.java new file mode 100644 index 00000000000..0dc4fb6df74 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsVpcPhysicalTopologyConfigCommandWrapper.java @@ -0,0 +1,57 @@ +// +// 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 org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Network; + +public final class CitrixOvsVpcPhysicalTopologyConfigCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixOvsVpcPhysicalTopologyConfigCommandWrapper.class); + + @Override + public Answer execute(final OvsVpcPhysicalTopologyConfigCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + try { + final Network nw = citrixResourceBase.findOrCreateTunnelNetwork(conn, command.getBridgeName()); + final String bridgeName = nw.getBridge(conn); + final long sequenceNo = command.getSequenceNumber(); + + final String result = citrixResourceBase.callHostPlugin(conn, "ovstunnel", "configure_ovs_bridge_for_network_topology", "bridge", + bridgeName, "config", command.getVpcConfigInJson(), "host-id", ((Long)command.getHostId()).toString(), + "seq-no", Long.toString(sequenceNo)); + + if (result.startsWith("SUCCESS")) { + return new Answer(command, true, result); + } else { + return new Answer(command, false, result); + } + } catch (final Exception e) { + s_logger.warn("caught exception while updating host with latest VPC topology", e); + return new Answer(command, false, e.getMessage()); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsVpcRoutingPolicyConfigCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsVpcRoutingPolicyConfigCommandWrapper.java new file mode 100644 index 00000000000..4b1e56d7598 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixOvsVpcRoutingPolicyConfigCommandWrapper.java @@ -0,0 +1,57 @@ +// +// 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 org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.OvsVpcRoutingPolicyConfigCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Network; + +public final class CitrixOvsVpcRoutingPolicyConfigCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixOvsVpcRoutingPolicyConfigCommandWrapper.class); + + @Override + public Answer execute(final OvsVpcRoutingPolicyConfigCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + try { + final Network nw = citrixResourceBase.findOrCreateTunnelNetwork(conn, command.getBridgeName()); + final String bridgeName = nw.getBridge(conn); + final long sequenceNo = command.getSequenceNumber(); + + final String result = citrixResourceBase.callHostPlugin(conn, "ovstunnel", "configure_ovs_bridge_for_routing_policies", "bridge", + bridgeName, "host-id", ((Long)command.getHostId()).toString(), "config", + command.getVpcConfigInJson(), "seq-no", Long.toString(sequenceNo)); + + if (result.startsWith("SUCCESS")) { + return new Answer(command, true, result); + } else { + return new Answer(command, false, result); + } + } catch (final Exception e) { + s_logger.warn("caught exception while updating host with latest routing policies", e); + return new Answer(command, false, e.getMessage()); + } + } +} \ No newline at end of file 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 be7aec66485..eb179bb4a0c 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 @@ -27,6 +27,7 @@ import com.cloud.agent.api.AttachVolumeCommand; import com.cloud.agent.api.CheckHealthCommand; import com.cloud.agent.api.CheckOnHostCommand; import com.cloud.agent.api.CheckVirtualMachineCommand; +import com.cloud.agent.api.CleanupNetworkRulesCmd; import com.cloud.agent.api.Command; import com.cloud.agent.api.CreateStoragePoolCommand; import com.cloud.agent.api.DeleteStoragePoolCommand; @@ -39,8 +40,12 @@ import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.MigrateCommand; import com.cloud.agent.api.ModifySshKeysCommand; import com.cloud.agent.api.ModifyStoragePoolCommand; +import com.cloud.agent.api.OvsCreateGreTunnelCommand; +import com.cloud.agent.api.OvsDeleteFlowCommand; import com.cloud.agent.api.OvsFetchInterfaceCommand; import com.cloud.agent.api.OvsSetTagAndFlowCommand; +import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand; +import com.cloud.agent.api.OvsVpcRoutingPolicyConfigCommand; import com.cloud.agent.api.PingTestCommand; import com.cloud.agent.api.PrepareForMigrationCommand; import com.cloud.agent.api.ReadyCommand; @@ -115,6 +120,11 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(CheckSshCommand.class, new CitrixCheckSshCommandWrapper()); map.put(SecurityGroupRulesCmd.class, new CitrixSecurityGroupRulesCommandWrapper()); map.put(OvsFetchInterfaceCommand.class, new CitrixOvsFetchInterfaceCommandWrapper()); + map.put(OvsCreateGreTunnelCommand.class, new CitrixOvsCreateGreTunnelCommandWrapper()); + map.put(OvsDeleteFlowCommand.class, new CitrixOvsDeleteFlowCommandWrapper()); + map.put(OvsVpcPhysicalTopologyConfigCommand.class, new CitrixOvsVpcPhysicalTopologyConfigCommandWrapper()); + map.put(OvsVpcRoutingPolicyConfigCommand.class, new CitrixOvsVpcRoutingPolicyConfigCommandWrapper()); + map.put(CleanupNetworkRulesCmd.class, new CitrixCleanupNetworkRulesCmdWrapper()); } public static CitrixRequestWrapper getInstance() { diff --git a/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapperTest.java b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapperTest.java index 75dd051ffcf..5fde596c720 100644 --- a/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapperTest.java +++ b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapperTest.java @@ -1,7 +1,9 @@ package com.cloud.hypervisor.xenserver.resource.wrapper; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.spy; @@ -30,6 +32,7 @@ import com.cloud.agent.api.AttachVolumeCommand; import com.cloud.agent.api.CheckHealthCommand; import com.cloud.agent.api.CheckOnHostCommand; import com.cloud.agent.api.CheckVirtualMachineCommand; +import com.cloud.agent.api.CleanupNetworkRulesCmd; import com.cloud.agent.api.Command; import com.cloud.agent.api.CreateStoragePoolCommand; import com.cloud.agent.api.DeleteStoragePoolCommand; @@ -42,7 +45,12 @@ import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.MigrateCommand; import com.cloud.agent.api.ModifySshKeysCommand; import com.cloud.agent.api.ModifyStoragePoolCommand; +import com.cloud.agent.api.OvsCreateGreTunnelCommand; +import com.cloud.agent.api.OvsDeleteFlowCommand; +import com.cloud.agent.api.OvsFetchInterfaceCommand; import com.cloud.agent.api.OvsSetTagAndFlowCommand; +import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand; +import com.cloud.agent.api.OvsVpcRoutingPolicyConfigCommand; import com.cloud.agent.api.PingTestCommand; import com.cloud.agent.api.PrepareForMigrationCommand; import com.cloud.agent.api.ReadyCommand; @@ -77,6 +85,7 @@ import com.xensource.xenapi.Connection; import com.xensource.xenapi.Host; import com.xensource.xenapi.Marshalling; import com.xensource.xenapi.Network; +import com.xensource.xenapi.PIF; import com.xensource.xenapi.Types.BadServerResponse; import com.xensource.xenapi.Types.XenAPIException; @@ -663,6 +672,7 @@ public class CitrixRequestWrapperTest { verify(citrixResourceBase, times(1)).getConnection(); verify(citrixResourceBase, times(1)).setupvSwitchNetwork(conn); + verify(citrixResourceBase, times(1)).setIsOvs(true); assertFalse(answer.getResult()); } @@ -704,13 +714,17 @@ public class CitrixRequestWrapperTest { @Test public void testOvsFetchInterfaceCommand() { final String label = "[abc]"; + final String uuid = "befc4dcd-f5c6-4015-8791-3c18622b7c7f"; final Connection conn = Mockito.mock(Connection.class); final XsLocalNetwork network = Mockito.mock(XsLocalNetwork.class); + final Network network2 = Mockito.mock(Network.class); + final PIF pif = Mockito.mock(PIF.class); + final PIF.Record pifRec = Mockito.mock(PIF.Record.class); final XsHost xsHost = Mockito.mock(XsHost.class); - final SecurityGroupRulesCmd sshCommand = new SecurityGroupRulesCmd(); + final OvsFetchInterfaceCommand fetchInterCommand = new OvsFetchInterfaceCommand(label); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); @@ -721,6 +735,11 @@ public class CitrixRequestWrapperTest { when(citrixResourceBase.getHost()).thenReturn(xsHost); try { + when(network.getNetwork()).thenReturn(network2); + when(network.getPif(conn)).thenReturn(pif); + when(network.getPif(conn)).thenReturn(pif); + when(pif.getRecord(conn)).thenReturn(pifRec); + when(network.getNetwork().getUuid(conn)).thenReturn(uuid); when(citrixResourceBase.getNetworkByName(conn, label)).thenReturn(network); } catch (final XenAPIException e) { fail(e.getMessage()); @@ -728,12 +747,253 @@ public class CitrixRequestWrapperTest { fail(e.getMessage()); } - final Answer answer = wrapper.execute(sshCommand, citrixResourceBase); + final Answer answer = wrapper.execute(fetchInterCommand, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertTrue(answer.getResult()); + } + + @Test + public void testOvsCreateGreTunnelCommand() { + final String bridge = "gre"; + final Connection conn = Mockito.mock(Connection.class); + final Network network = Mockito.mock(Network.class); + final XsHost xsHost = Mockito.mock(XsHost.class); + + final OvsCreateGreTunnelCommand createGreCommand = new OvsCreateGreTunnelCommand("172.0.0.1", "KEY", 1l, 2l); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + when(citrixResourceBase.getHost()).thenReturn(xsHost); + when(citrixResourceBase.setupvSwitchNetwork(conn)).thenReturn(network); + try { + when(network.getBridge(conn)).thenReturn(bridge); + when(citrixResourceBase.callHostPlugin(conn, "ovsgre", "ovs_create_gre", "bridge", bridge, "remoteIP", createGreCommand.getRemoteIp(), "greKey", + createGreCommand.getKey(), "from", Long.toString(createGreCommand.getFrom()), "to", Long.toString(createGreCommand.getTo()))).thenReturn("1:2"); + + } catch (final BadServerResponse e) { + fail(e.getMessage()); + } catch (final XenAPIException e) { + fail(e.getMessage()); + } catch (final XmlRpcException e) { + fail(e.getMessage()); + } + + final Answer answer = wrapper.execute(createGreCommand, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + verify(citrixResourceBase, times(1)).setIsOvs(true); + + assertTrue(answer.getResult()); + } + + @Test + public void testOvsDeleteFlowCommandSuccess() { + final String bridge = "gre"; + final Connection conn = Mockito.mock(Connection.class); + final Network network = Mockito.mock(Network.class); + + final OvsDeleteFlowCommand deleteFlowCommand = new OvsDeleteFlowCommand("Test"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + when(citrixResourceBase.setupvSwitchNetwork(conn)).thenReturn(network); + try { + when(network.getBridge(conn)).thenReturn(bridge); + when(citrixResourceBase.callHostPlugin(conn, "ovsgre", "ovs_delete_flow", "bridge", bridge, "vmName", deleteFlowCommand.getVmName())).thenReturn("SUCCESS"); + + } catch (final BadServerResponse e) { + fail(e.getMessage()); + } catch (final XenAPIException e) { + fail(e.getMessage()); + } catch (final XmlRpcException e) { + fail(e.getMessage()); + } + + final Answer answer = wrapper.execute(deleteFlowCommand, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + verify(citrixResourceBase, times(1)).setIsOvs(true); + + assertTrue(answer.getResult()); + } + + @Test + public void testOvsDeleteFlowCommandFailure() { + final String bridge = "gre"; + final Connection conn = Mockito.mock(Connection.class); + final Network network = Mockito.mock(Network.class); + + final OvsDeleteFlowCommand deleteFlowCommand = new OvsDeleteFlowCommand("Test"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + when(citrixResourceBase.setupvSwitchNetwork(conn)).thenReturn(network); + try { + when(network.getBridge(conn)).thenReturn(bridge); + when(citrixResourceBase.callHostPlugin(conn, "ovsgre", "ovs_delete_flow", "bridge", bridge, "vmName", deleteFlowCommand.getVmName())).thenReturn("FAILED"); + + } catch (final BadServerResponse e) { + fail(e.getMessage()); + } catch (final XenAPIException e) { + fail(e.getMessage()); + } catch (final XmlRpcException e) { + fail(e.getMessage()); + } + + final Answer answer = wrapper.execute(deleteFlowCommand, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + verify(citrixResourceBase, times(1)).setIsOvs(true); + + assertFalse(answer.getResult()); + } + + @Test + public void testOvsVpcPhysicalTopologyConfigCommand() { + final String bridge = "gre"; + final Connection conn = Mockito.mock(Connection.class); + final Network network = Mockito.mock(Network.class); + + final OvsVpcPhysicalTopologyConfigCommand.Host[] hosts = new OvsVpcPhysicalTopologyConfigCommand.Host[0]; + final OvsVpcPhysicalTopologyConfigCommand.Tier[] tiers = new OvsVpcPhysicalTopologyConfigCommand.Tier[0]; + final OvsVpcPhysicalTopologyConfigCommand.Vm[] vms = new OvsVpcPhysicalTopologyConfigCommand.Vm[0]; + + final OvsVpcPhysicalTopologyConfigCommand physicalTopology = new OvsVpcPhysicalTopologyConfigCommand(hosts, tiers, vms, "10.0.0.1/24"); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + try { + when(citrixResourceBase.findOrCreateTunnelNetwork(conn, physicalTopology.getBridgeName())).thenReturn(network); + when(network.getBridge(conn)).thenReturn(bridge); + + when(citrixResourceBase.callHostPlugin(conn, "ovstunnel", "configure_ovs_bridge_for_network_topology", "bridge", + bridge, "config", physicalTopology.getVpcConfigInJson(), "host-id", ((Long)physicalTopology.getHostId()).toString(), + "seq-no", Long.toString(1))).thenReturn("SUCCESS"); + + } catch (final BadServerResponse e) { + fail(e.getMessage()); + } catch (final XenAPIException e) { + fail(e.getMessage()); + } catch (final XmlRpcException e) { + fail(e.getMessage()); + } + + final Answer answer = wrapper.execute(physicalTopology, citrixResourceBase); verify(citrixResourceBase, times(1)).getConnection(); assertFalse(answer.getResult()); } + + @Test + public void testOvsVpcRoutingPolicyConfigCommand() { + final String bridge = "gre"; + final Connection conn = Mockito.mock(Connection.class); + final Network network = Mockito.mock(Network.class); + + final OvsVpcRoutingPolicyConfigCommand.Acl[] acls = new OvsVpcRoutingPolicyConfigCommand.Acl[0]; + final OvsVpcRoutingPolicyConfigCommand.Tier[] tiers = new OvsVpcRoutingPolicyConfigCommand.Tier[0]; + + final OvsVpcRoutingPolicyConfigCommand routingPolicy = new OvsVpcRoutingPolicyConfigCommand("v1", "10.0.0.1/24", acls, tiers); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + try { + when(citrixResourceBase.findOrCreateTunnelNetwork(conn, routingPolicy.getBridgeName())).thenReturn(network); + when(network.getBridge(conn)).thenReturn(bridge); + + when(citrixResourceBase.callHostPlugin(conn, "ovstunnel", "configure_ovs_bridge_for_routing_policies", "bridge", + bridge, "host-id", ((Long)routingPolicy.getHostId()).toString(), "config", + routingPolicy.getVpcConfigInJson(), "seq-no", Long.toString(1))).thenReturn("SUCCESS"); + + } catch (final BadServerResponse e) { + fail(e.getMessage()); + } catch (final XenAPIException e) { + fail(e.getMessage()); + } catch (final XmlRpcException e) { + fail(e.getMessage()); + } + + final Answer answer = wrapper.execute(routingPolicy, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testCleanupNetworkRulesCmd() { + final Connection conn = Mockito.mock(Connection.class); + final XsHost xsHost = Mockito.mock(XsHost.class); + + final CleanupNetworkRulesCmd cleanupNets = new CleanupNetworkRulesCmd(20); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.canBridgeFirewall()).thenReturn(true); + when(citrixResourceBase.getConnection()).thenReturn(conn); + when(citrixResourceBase.getHost()).thenReturn(xsHost); + when(citrixResourceBase.getVMInstanceName()).thenReturn("VM"); + when(citrixResourceBase.callHostPlugin(conn, "vmops", "cleanup_rules", "instance", citrixResourceBase.getVMInstanceName())).thenReturn("1"); + + final Answer answer = wrapper.execute(cleanupNets, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertTrue(answer.getResult()); + } + + @Test + public void testCleanupNetworkRulesCmdLTZ() { + final Connection conn = Mockito.mock(Connection.class); + final XsHost xsHost = Mockito.mock(XsHost.class); + + final CleanupNetworkRulesCmd cleanupNets = new CleanupNetworkRulesCmd(20); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.canBridgeFirewall()).thenReturn(true); + when(citrixResourceBase.getConnection()).thenReturn(conn); + when(citrixResourceBase.getHost()).thenReturn(xsHost); + when(citrixResourceBase.getVMInstanceName()).thenReturn("VM"); + when(citrixResourceBase.callHostPlugin(conn, "vmops", "cleanup_rules", "instance", citrixResourceBase.getVMInstanceName())).thenReturn("-1"); + + final Answer answer = wrapper.execute(cleanupNets, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + verify(xsHost, times(1)).getIp(); + + assertFalse(answer.getResult()); + assertEquals(answer.getDetails(), "-1"); + } + + @Test + public void testCleanupNetworkRulesCmdNullDetails() { + final CleanupNetworkRulesCmd cleanupNets = new CleanupNetworkRulesCmd(20); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.canBridgeFirewall()).thenReturn(false); + final Answer answer = wrapper.execute(cleanupNets, citrixResourceBase); + + assertTrue(answer.getResult()); + assertNull(answer.getDetails()); + } } class NotAValidCommand extends Command {