From 02571728c61e64399bea77af3d6ac2d6d87d0404 Mon Sep 17 00:00:00 2001 From: wilderrodrigues Date: Mon, 30 Mar 2015 19:01:46 +0200 Subject: [PATCH] Refactored the remaining commands - Unit tests added In the executeRequest I needed to keep the following: // We need this one because the StorageSubSystemCommand is from another hierarchy. if (cmd instanceof StorageSubSystemCommand) { return storageHandler.handleStorageCommands((StorageSubSystemCommand) cmd); } --- .../resource/CitrixResourceBase.java | 47 ++- .../xenserver/resource/XcpServerResource.java | 39 ++- .../resource/XenServer56FP1Resource.java | 53 ++-- .../resource/Xenserver625Resource.java | 4 +- .../CitrixNetworkElementCommandWrapper.java | 35 ++ ...tworkRulesVmSecondaryIpCommandWrapper.java | 44 +++ ...itrixPerformanceMonitorCommandWrapper.java | 41 +++ .../CitrixPvlanSetupCommandWrapper.java | 92 ++++++ .../wrapper/CitrixRequestWrapper.java | 24 +- .../wrapper/CitrixScaleVmCommandWrapper.java | 106 +++++++ .../resource/CitrixResourceBaseTest.java | 4 +- .../wrapper/CitrixRequestWrapperTest.java | 300 ++++++++++++++++++ 12 files changed, 707 insertions(+), 82 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixNetworkElementCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixNetworkRulesVmSecondaryIpCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPerformanceMonitorCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPvlanSetupCommandWrapper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixScaleVmCommandWrapper.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 aa9268105ee..6ef756cb81e 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 @@ -350,6 +350,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe _password.add(password); } + public VirtualRoutingResource getVirtualRoutingResource() { + return _vrResource; + } + public boolean isOvs() { return _isOvs; } @@ -458,30 +462,15 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe @Override public Answer executeRequest(final Command cmd) { - final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); - try { - final Answer answer = wrapper.execute(cmd, this); - return answer; - } catch (final Exception e) { - // Ignore it for now. Just removing the command that have already been - // replaced by the new code. + // We need this one because the StorageSubSystemCommand is from another hierarchy. + if (cmd instanceof StorageSubSystemCommand) { + return storageHandler.handleStorageCommands((StorageSubSystemCommand) cmd); } - final Class clazz = cmd.getClass(); - - if (cmd instanceof NetworkElementCommand) { - return _vrResource.executeRequest((NetworkElementCommand)cmd); - } else if (cmd instanceof StorageSubSystemCommand) { - return storageHandler.handleStorageCommands((StorageSubSystemCommand) cmd); - } else if (clazz == NetworkRulesVmSecondaryIpCommand.class) { - return execute((NetworkRulesVmSecondaryIpCommand) cmd); - } else if (clazz == ScaleVmCommand.class) { - return execute((ScaleVmCommand)cmd); - } else if (clazz == PvlanSetupCommand.class) { - return execute((PvlanSetupCommand)cmd); - } else if (clazz == PerformanceMonitorCommand.class) { - return execute((PerformanceMonitorCommand)cmd); - } else { + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + try { + return wrapper.execute(cmd, this); + } catch (final Exception e) { return Answer.createUnsupportedCommandAnswer(cmd); } } @@ -564,7 +553,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - private String getPerfMon(final Connection conn, final Map params, + public String getPerfMon(final Connection conn, final Map params, final int wait) { String result = null; try { @@ -625,7 +614,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return null; } - protected void scaleVM(final Connection conn, final VM vm, final VirtualMachineTO vmSpec, final Host host) throws XenAPIException, XmlRpcException { + public void scaleVM(final Connection conn, final VM vm, final VirtualMachineTO vmSpec, final Host host) throws XenAPIException, XmlRpcException { final Long staticMemoryMax = vm.getMemoryStaticMax(conn); final Long staticMemoryMin = vm.getMemoryStaticMin(conn); @@ -806,7 +795,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe throw new CloudRuntimeException(errMsg); } - protected XsLocalNetwork getNativeNetworkForTraffic(final Connection conn, final TrafficType type, final String name) throws XenAPIException, XmlRpcException { + public XsLocalNetwork getNativeNetworkForTraffic(final Connection conn, final TrafficType type, final String name) throws XenAPIException, XmlRpcException { if (name != null) { if (s_logger.isDebugEnabled()) { s_logger.debug("Looking for network named " + name); @@ -3121,7 +3110,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe * By default this is disallowed, override the specific xenserver resource * if this is enabled */ - protected boolean isDmcEnabled(final Connection conn, final Host host) throws XenAPIException, XmlRpcException { + public boolean isDmcEnabled(final Connection conn, final Host host) throws XenAPIException, XmlRpcException { return false; } @@ -5576,7 +5565,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe CheckXenHostInfo(); - storageHandler = getStorageHandler(); + storageHandler = buildStorageHandler(); _vrResource = new VirtualRoutingResource(this); if (!_vrResource.configure(name, params)) { @@ -5585,7 +5574,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return true; } - protected StorageSubsystemCommandHandler getStorageHandler() { + protected StorageSubsystemCommandHandler buildStorageHandler() { final XenServerStorageProcessor processor = new XenServerStorageProcessor(this); return new StorageSubsystemCommandHandlerBase(processor); } @@ -7180,4 +7169,4 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final String result = callHostPlugin(conn, "ovstunnel", "getLabel"); return result; } -} +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpServerResource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpServerResource.java index 782a530d2e0..63cdf114bf2 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpServerResource.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpServerResource.java @@ -25,11 +25,6 @@ import javax.ejb.Local; import org.apache.log4j.Logger; import org.apache.xmlrpc.XmlRpcException; -import com.xensource.xenapi.Connection; -import com.xensource.xenapi.Host; -import com.xensource.xenapi.Types.XenAPIException; -import com.xensource.xenapi.VM; - import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.NetworkUsageAnswer; @@ -37,6 +32,10 @@ import com.cloud.agent.api.NetworkUsageCommand; 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.VM; @Local(value = ServerResource.class) public class XcpServerResource extends CitrixResourceBase { @@ -49,7 +48,7 @@ public class XcpServerResource extends CitrixResourceBase { } @Override - public Answer executeRequest(Command cmd) { + public Answer executeRequest(final Command cmd) { if (cmd instanceof NetworkUsageCommand) { return execute((NetworkUsageCommand)cmd); } else { @@ -59,29 +58,29 @@ public class XcpServerResource extends CitrixResourceBase { @Override protected List getPatchFiles() { - List files = new ArrayList(); - String patch = "scripts/vm/hypervisor/xenserver/xcpserver/patch"; - String patchfilePath = Script.findScript("", patch); + final List files = new ArrayList(); + final String patch = "scripts/vm/hypervisor/xenserver/xcpserver/patch"; + final String patchfilePath = Script.findScript("", patch); if (patchfilePath == null) { throw new CloudRuntimeException("Unable to find patch file " + patch); } - File file = new File(patchfilePath); + final File file = new File(patchfilePath); files.add(file); return files; } - protected NetworkUsageAnswer execute(NetworkUsageCommand cmd) { + protected NetworkUsageAnswer execute(final NetworkUsageCommand cmd) { try { - Connection conn = getConnection(); + final Connection conn = getConnection(); if (cmd.getOption() != null && cmd.getOption().equals("create")) { - String result = networkUsage(conn, cmd.getPrivateIP(), "create", null); - NetworkUsageAnswer answer = new NetworkUsageAnswer(cmd, result, 0L, 0L); + final String result = networkUsage(conn, cmd.getPrivateIP(), "create", null); + final NetworkUsageAnswer answer = new NetworkUsageAnswer(cmd, result, 0L, 0L); return answer; } - long[] stats = getNetworkStats(conn, cmd.getPrivateIP()); - NetworkUsageAnswer answer = new NetworkUsageAnswer(cmd, "", stats[0], stats[1]); + final long[] stats = getNetworkStats(conn, cmd.getPrivateIP()); + final NetworkUsageAnswer answer = new NetworkUsageAnswer(cmd, "", stats[0], stats[1]); return answer; - } catch (Exception ex) { + } catch (final Exception ex) { s_logger.warn("Failed to get network usage stats due to ", ex); return new NetworkUsageAnswer(cmd, ex); } @@ -137,17 +136,17 @@ public class XcpServerResource extends CitrixResourceBase { cf: https://wiki.xenserver.org/index.php?title=XCP_FAQ_Dynamic_Memory_Control */ @Override - protected void setMemory(Connection conn, VM vm, long minMemsize, long maxMemsize) throws XmlRpcException, XenAPIException { + protected void setMemory(final Connection conn, final VM vm, final long minMemsize, final long maxMemsize) throws XmlRpcException, XenAPIException { //setMemoryLimits(staticMin, staticMax, dynamicMin, dynamicMax) if (s_logger.isDebugEnabled()) { s_logger.debug("Memory Limits for VM [" + vm.getNameLabel(conn) + "[staticMin:" + mem_32m + ", staticMax:" + maxMemsize + ", dynamicMin: " + minMemsize + - ", dynamicMax:" + maxMemsize + "]]"); + ", dynamicMax:" + maxMemsize + "]]"); } vm.setMemoryLimits(conn, mem_32m, maxMemsize, minMemsize, maxMemsize); } @Override - protected boolean isDmcEnabled(Connection conn, Host host) { + public boolean isDmcEnabled(final Connection conn, final Host host) { //Dynamic Memory Control (DMC) is a technology provided by Xen Cloud Platform (XCP), starting from the 0.5 release //For the supported XCPs dmc is default enabled, XCP 1.0.0, 1.1.0, 1.4.x, 1.5 beta, 1.6.x; return true; 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 eeeb9590986..f695582f525 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 @@ -28,6 +28,11 @@ 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; @@ -35,12 +40,6 @@ import com.xensource.xenapi.VBD; import com.xensource.xenapi.VDI; import com.xensource.xenapi.VM; -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; - @Local(value = ServerResource.class) public class XenServer56FP1Resource extends XenServer56Resource { private static final long mem_128m = 134217728L; @@ -52,22 +51,22 @@ public class XenServer56FP1Resource extends XenServer56Resource { @Override protected List getPatchFiles() { - List files = new ArrayList(); - String patch = "scripts/vm/hypervisor/xenserver/xenserver56fp1/patch"; - String patchfilePath = Script.findScript("", patch); + final List files = new ArrayList(); + final String patch = "scripts/vm/hypervisor/xenserver/xenserver56fp1/patch"; + final String patchfilePath = Script.findScript("", patch); if (patchfilePath == null) { throw new CloudRuntimeException("Unable to find patch file " + patch); } - File file = new File(patchfilePath); + final File file = new File(patchfilePath); files.add(file); return files; } @Override - protected FenceAnswer execute(FenceCommand cmd) { - Connection conn = getConnection(); + protected FenceAnswer execute(final FenceCommand cmd) { + final Connection conn = getConnection(); try { - Boolean alive = check_heartbeat(cmd.getHostGuid()); + final Boolean alive = check_heartbeat(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"); @@ -76,12 +75,12 @@ public class XenServer56FP1Resource extends XenServer56Resource { 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"); } - Set vms = VM.getByNameLabel(conn, cmd.getVmName()); - for (VM vm : vms) { - Set vdis = new HashSet(); - Set vbds = vm.getVBDs(conn); - for (VBD vbd : vbds) { - VDI vdi = vbd.getVDI(conn); + 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); } @@ -89,9 +88,9 @@ public class XenServer56FP1Resource extends XenServer56Resource { s_logger.info("Fence command for VM " + cmd.getVmName()); vm.powerStateReset(conn); vm.destroy(conn); - for (VDI vdi : vdis) { - Map smConfig = vdi.getSmConfig(conn); - for (String key : smConfig.keySet()) { + 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; @@ -100,10 +99,10 @@ public class XenServer56FP1Resource extends XenServer56Resource { } } return new FenceAnswer(cmd); - } catch (XmlRpcException e) { + } catch (final XmlRpcException e) { s_logger.warn("Unable to fence", e); return new FenceAnswer(cmd, false, e.getMessage()); - } catch (XenAPIException e) { + } catch (final XenAPIException e) { s_logger.warn("Unable to fence", e); return new FenceAnswer(cmd, false, e.getMessage()); } @@ -117,9 +116,9 @@ public class XenServer56FP1Resource extends XenServer56Resource { * When false, scaling is allowed hence DMC is enabled */ @Override - protected boolean isDmcEnabled(Connection conn, Host host) throws XenAPIException, XmlRpcException { - Map hostParams = host.getLicenseParams(conn); - Boolean isDmcEnabled = hostParams.get("restrict_dmc").equalsIgnoreCase("false"); + public boolean isDmcEnabled(final Connection conn, final Host host) throws XenAPIException, XmlRpcException { + final Map hostParams = host.getLicenseParams(conn); + final Boolean isDmcEnabled = hostParams.get("restrict_dmc").equalsIgnoreCase("false"); return isDmcEnabled; } } diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/Xenserver625Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/Xenserver625Resource.java index 11ab7ba4395..6a782874fa7 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/Xenserver625Resource.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/Xenserver625Resource.java @@ -61,7 +61,7 @@ public class Xenserver625Resource extends XenServerResourceNewBase { } @Override - protected StorageSubsystemCommandHandler getStorageHandler() { + protected StorageSubsystemCommandHandler buildStorageHandler() { final XenServerStorageProcessor processor = new Xenserver625StorageProcessor(this); return new StorageSubsystemCommandHandlerBase(processor); } @@ -99,7 +99,7 @@ public class Xenserver625Resource extends XenServerResourceNewBase { } @Override - protected String revertToSnapshot(final Connection conn, final VM vmSnapshot, + public String revertToSnapshot(final Connection conn, final VM vmSnapshot, final String vmName, final String oldVmUuid, final Boolean snapshotMemory, final String hostUUID) throws Types.XenAPIException, XmlRpcException { diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixNetworkElementCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixNetworkElementCommandWrapper.java new file mode 100644 index 00000000000..801a43b29b6 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixNetworkElementCommandWrapper.java @@ -0,0 +1,35 @@ +// +// 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 com.cloud.agent.api.Answer; +import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; + +public final class CitrixNetworkElementCommandWrapper extends CommandWrapper { + + @Override + public Answer execute(final NetworkElementCommand command, final CitrixResourceBase citrixResourceBase) { + final VirtualRoutingResource routingResource = citrixResourceBase.getVirtualRoutingResource(); + return routingResource.executeRequest(command); + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixNetworkRulesVmSecondaryIpCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixNetworkRulesVmSecondaryIpCommandWrapper.java new file mode 100644 index 00000000000..48e57d8444a --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixNetworkRulesVmSecondaryIpCommandWrapper.java @@ -0,0 +1,44 @@ +// +// 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 com.cloud.agent.api.Answer; +import com.cloud.agent.api.NetworkRulesVmSecondaryIpCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; + +public final class CitrixNetworkRulesVmSecondaryIpCommandWrapper extends CommandWrapper { + + @Override + public Answer execute(final NetworkRulesVmSecondaryIpCommand command, final CitrixResourceBase citrixResourceBase) { + boolean success = true; + final Connection conn = citrixResourceBase.getConnection(); + + final String result = citrixResourceBase.callHostPlugin(conn, "vmops", "network_rules_vmSecondaryIp", "vmName", command.getVmName(), "vmMac", command.getVmMac(), + "vmSecIp", command.getVmSecIp(), "action", command.getAction()); + + if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { + success = false; + } + + return new Answer(command, success, ""); + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPerformanceMonitorCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPerformanceMonitorCommandWrapper.java new file mode 100644 index 00000000000..ad670c1fa3b --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPerformanceMonitorCommandWrapper.java @@ -0,0 +1,41 @@ +// +// 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 com.cloud.agent.api.Answer; +import com.cloud.agent.api.PerformanceMonitorAnswer; +import com.cloud.agent.api.PerformanceMonitorCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.xensource.xenapi.Connection; + +public final class CitrixPerformanceMonitorCommandWrapper extends CommandWrapper { + + @Override + public Answer execute(final PerformanceMonitorCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + final String perfMon = citrixResourceBase.getPerfMon(conn, command.getParams(), command.getWait()); + if (perfMon == null) { + return new PerformanceMonitorAnswer(command, false, perfMon); + } else { + return new PerformanceMonitorAnswer(command, true, perfMon); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPvlanSetupCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPvlanSetupCommandWrapper.java new file mode 100644 index 00000000000..6db9383a79a --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixPvlanSetupCommandWrapper.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 org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.PvlanSetupCommand; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.hypervisor.xenserver.resource.XsLocalNetwork; +import com.cloud.network.Networks.TrafficType; +import com.cloud.resource.CommandWrapper; +import com.cloud.utils.exception.CloudRuntimeException; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Types.XenAPIException; + +public final class CitrixPvlanSetupCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixPvlanSetupCommandWrapper.class); + + @Override + public Answer execute(final PvlanSetupCommand command, final CitrixResourceBase citrixResourceBase) { + final Connection conn = citrixResourceBase.getConnection(); + + 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(); + final String networkTag = command.getNetworkTag(); + + String nwNameLabel = null; + try { + final XsLocalNetwork nw = citrixResourceBase.getNativeNetworkForTraffic(conn, TrafficType.Guest, networkTag); + if (nw == null) { + s_logger.error("Network is not configured on the backend for pvlan " + primaryPvlan); + throw new CloudRuntimeException("Network for the backend is not configured correctly for pvlan primary: " + primaryPvlan); + } + nwNameLabel = nw.getNetwork().getNameLabel(conn); + } catch (final XenAPIException e) { + s_logger.warn("Fail to get network", e); + return new Answer(command, false, e.toString()); + } catch (final XmlRpcException e) { + s_logger.warn("Fail to get network", e); + return new Answer(command, false, e.toString()); + } + + String result = null; + if (command.getType() == PvlanSetupCommand.Type.DHCP) { + result = citrixResourceBase.callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-dhcp", "op", op, "nw-label", nwNameLabel, "primary-pvlan", primaryPvlan, "isolated-pvlan", + isolatedPvlan, "dhcp-name", dhcpName, "dhcp-ip", dhcpIp, "dhcp-mac", dhcpMac); + + if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { + 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) { + result = citrixResourceBase.callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-vm", "op", op, "nw-label", nwNameLabel, "primary-pvlan", primaryPvlan, "isolated-pvlan", + isolatedPvlan, "vm-mac", vmMac); + + if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { + 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); + } + } + 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/CitrixRequestWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapper.java index 289fff9f596..15532397f37 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 @@ -21,6 +21,8 @@ package com.cloud.hypervisor.xenserver.resource.wrapper; import java.util.Hashtable; +import org.apache.cloudstack.storage.command.StorageSubSystemCommand; + import com.cloud.agent.api.Answer; import com.cloud.agent.api.AttachIsoCommand; import com.cloud.agent.api.AttachVolumeCommand; @@ -45,6 +47,7 @@ import com.cloud.agent.api.MigrateCommand; 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.OvsCreateGreTunnelCommand; import com.cloud.agent.api.OvsCreateTunnelCommand; import com.cloud.agent.api.OvsDeleteFlowCommand; @@ -55,13 +58,16 @@ import com.cloud.agent.api.OvsSetTagAndFlowCommand; import com.cloud.agent.api.OvsSetupBridgeCommand; import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand; import com.cloud.agent.api.OvsVpcRoutingPolicyConfigCommand; +import com.cloud.agent.api.PerformanceMonitorCommand; 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; import com.cloud.agent.api.RevertToVMSnapshotCommand; +import com.cloud.agent.api.ScaleVmCommand; import com.cloud.agent.api.SecurityGroupRulesCmd; import com.cloud.agent.api.SetupCommand; import com.cloud.agent.api.StartCommand; @@ -72,6 +78,7 @@ import com.cloud.agent.api.UpgradeSnapshotCommand; import com.cloud.agent.api.check.CheckSshCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; +import com.cloud.agent.api.routing.NetworkElementCommand; import com.cloud.agent.api.storage.CreateCommand; import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; @@ -151,16 +158,29 @@ public class CitrixRequestWrapper extends RequestWrapper { map.put(CreateVMSnapshotCommand.class, new CitrixCreateVMSnapshotCommandWrapper()); map.put(DeleteVMSnapshotCommand.class, new CitrixDeleteVMSnapshotCommandWrapper()); map.put(RevertToVMSnapshotCommand.class, new CitrixRevertToVMSnapshotCommandWrapper()); + map.put(NetworkRulesVmSecondaryIpCommand.class, new CitrixNetworkRulesVmSecondaryIpCommandWrapper()); + map.put(ScaleVmCommand.class, new CitrixScaleVmCommandWrapper()); + map.put(PvlanSetupCommand.class, new CitrixPvlanSetupCommandWrapper()); + map.put(PerformanceMonitorCommand.class, new CitrixPerformanceMonitorCommandWrapper()); + map.put(NetworkElementCommand.class, new CitrixNetworkElementCommandWrapper()); } public static CitrixRequestWrapper getInstance() { return instance; } + @SuppressWarnings("unchecked") @Override public Answer execute(final Command command, final ServerResource serverResource) { - @SuppressWarnings("unchecked") - final CommandWrapper commandWrapper = map.get(command.getClass()); + CommandWrapper commandWrapper = map.get(command.getClass()); + + // This is temporary. We have to map the classes with several sub-classes better. + if (commandWrapper == null && command instanceof StorageSubSystemCommand) { + commandWrapper = map.get(StorageSubSystemCommand.class); + } + if (commandWrapper == null && command instanceof NetworkElementCommand) { + commandWrapper = map.get(NetworkElementCommand.class); + } if (commandWrapper == null) { throw new NullPointerException("No key found for '" + command.getClass() + "' in the Map!"); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixScaleVmCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixScaleVmCommandWrapper.java new file mode 100644 index 00000000000..47a30f59fa7 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixScaleVmCommandWrapper.java @@ -0,0 +1,106 @@ +// +// 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.Iterator; +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.ScaleVmAnswer; +import com.cloud.agent.api.ScaleVmCommand; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.cloud.utils.exception.CloudRuntimeException; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Types.VmPowerState; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VM; + +public final class CitrixScaleVmCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(CitrixScaleVmCommandWrapper.class); + + @Override + public Answer execute(final ScaleVmCommand command, final CitrixResourceBase citrixResourceBase) { + final VirtualMachineTO vmSpec = command.getVirtualMachine(); + final String vmName = vmSpec.getName(); + try { + final Connection conn = citrixResourceBase.getConnection(); + final Set vms = VM.getByNameLabel(conn, vmName); + final Host host = Host.getByUuid(conn, citrixResourceBase.getHost().getUuid()); + + // If DMC is not enable then don't execute this command. + if (!citrixResourceBase.isDmcEnabled(conn, host)) { + throw new CloudRuntimeException("Unable to scale the vm: " + vmName + " as DMC - Dynamic memory control is not enabled for the XenServer:" + + citrixResourceBase.getHost().getUuid() + " ,check your license and hypervisor version."); + } + + if (vms == null || vms.size() == 0) { + s_logger.info("No running VM " + vmName + " exists on XenServer" + citrixResourceBase.getHost().getUuid()); + return new ScaleVmAnswer(command, false, "VM does not exist"); + } + + // stop vm which is running on this host or is in halted state + final Iterator iter = vms.iterator(); + while (iter.hasNext()) { + final VM vm = iter.next(); + final VM.Record vmr = vm.getRecord(conn); + + if (vmr.powerState == VmPowerState.HALTED || vmr.powerState == VmPowerState.RUNNING && !citrixResourceBase.isRefNull(vmr.residentOn) + && !vmr.residentOn.getUuid(conn).equals(citrixResourceBase.getHost().getUuid())) { + iter.remove(); + } + } + + for (final VM vm : vms) { + vm.getRecord(conn); + try { + citrixResourceBase.scaleVM(conn, vm, vmSpec, host); + } catch (final Exception e) { + final String msg = "Catch exception " + e.getClass().getName() + " when scaling VM:" + vmName + " due to " + e.toString(); + s_logger.debug(msg); + return new ScaleVmAnswer(command, false, msg); + } + + } + final String msg = "scaling VM " + vmName + " is successful on host " + host; + s_logger.debug(msg); + return new ScaleVmAnswer(command, true, msg); + + } catch (final XenAPIException e) { + final String msg = "Upgrade Vm " + vmName + " fail due to " + e.toString(); + s_logger.warn(msg, e); + return new ScaleVmAnswer(command, false, msg); + } catch (final XmlRpcException e) { + final String msg = "Upgrade Vm " + vmName + " fail due to " + e.getMessage(); + s_logger.warn(msg, e); + return new ScaleVmAnswer(command, false, msg); + } catch (final Exception e) { + final String msg = "Unable to upgrade " + vmName + " due to " + e.getMessage(); + s_logger.warn(msg, e); + return new ScaleVmAnswer(command, false, msg); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/CitrixResourceBaseTest.java b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/CitrixResourceBaseTest.java index e79e8af5039..4d492aaac12 100644 --- a/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/CitrixResourceBaseTest.java +++ b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/CitrixResourceBaseTest.java @@ -66,13 +66,13 @@ public class CitrixResourceBaseTest { } @Override - protected void scaleVM(final Connection conn, final VM vm, final VirtualMachineTO vmSpec, final Host host) throws Types.XenAPIException, XmlRpcException { + public void scaleVM(final Connection conn, final VM vm, final VirtualMachineTO vmSpec, final Host host) throws Types.XenAPIException, XmlRpcException { _host.setSpeed(500); super.scaleVM(conn, vm, vmSpec, host); } @Override - protected boolean isDmcEnabled(final Connection conn, final Host host) throws Types.XenAPIException, XmlRpcException { + public boolean isDmcEnabled(final Connection conn, final Host host) throws Types.XenAPIException, XmlRpcException { return true; } }; 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 72d5c1a3017..286708a6e8f 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 @@ -11,6 +11,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.net.URI; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; @@ -52,6 +53,7 @@ import com.cloud.agent.api.MigrateCommand; 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.OvsCreateGreTunnelCommand; import com.cloud.agent.api.OvsCreateTunnelCommand; import com.cloud.agent.api.OvsDeleteFlowCommand; @@ -62,14 +64,17 @@ import com.cloud.agent.api.OvsSetTagAndFlowCommand; import com.cloud.agent.api.OvsSetupBridgeCommand; import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand; import com.cloud.agent.api.OvsVpcRoutingPolicyConfigCommand; +import com.cloud.agent.api.PerformanceMonitorCommand; 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.RebootAnswer; import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.RebootRouterCommand; import com.cloud.agent.api.RevertToVMSnapshotCommand; +import com.cloud.agent.api.ScaleVmCommand; import com.cloud.agent.api.SecurityGroupRulesCmd; import com.cloud.agent.api.SetupCommand; import com.cloud.agent.api.StartCommand; @@ -81,19 +86,23 @@ import com.cloud.agent.api.VMSnapshotTO; import com.cloud.agent.api.check.CheckSshCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; +import com.cloud.agent.api.routing.IpAssocVpcCommand; import com.cloud.agent.api.storage.CreateAnswer; import com.cloud.agent.api.storage.CreateCommand; import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; import com.cloud.agent.api.storage.ResizeVolumeCommand; import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.IpAddressTO; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource; import com.cloud.host.HostEnvironment; import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; import com.cloud.hypervisor.xenserver.resource.XsHost; import com.cloud.hypervisor.xenserver.resource.XsLocalNetwork; +import com.cloud.network.Networks.TrafficType; import com.cloud.network.PhysicalNetworkSetupInfo; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; @@ -1471,6 +1480,297 @@ public class CitrixRequestWrapperTest { assertFalse(answer.getResult()); } + + @Test + public void testNetworkRulesVmSecondaryIpCommandSuccess() { + final Connection conn = Mockito.mock(Connection.class); + + final NetworkRulesVmSecondaryIpCommand rulesVm = new NetworkRulesVmSecondaryIpCommand("Test", VirtualMachine.Type.User); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + when(citrixResourceBase.callHostPlugin(conn, "vmops", "network_rules_vmSecondaryIp", "vmName", rulesVm.getVmName(), "vmMac", rulesVm.getVmMac(), + "vmSecIp", rulesVm.getVmSecIp(), "action", rulesVm.getAction())).thenReturn("true"); + + final Answer answer = wrapper.execute(rulesVm, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertTrue(answer.getResult()); + } + + @Test + public void testNetworkRulesVmSecondaryIpCommandFailure() { + final Connection conn = Mockito.mock(Connection.class); + + final NetworkRulesVmSecondaryIpCommand rulesVm = new NetworkRulesVmSecondaryIpCommand("Test", VirtualMachine.Type.User); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + when(citrixResourceBase.callHostPlugin(conn, "vmops", "network_rules_vmSecondaryIp", "vmName", rulesVm.getVmName(), "vmMac", rulesVm.getVmMac(), + "vmSecIp", rulesVm.getVmSecIp(), "action", rulesVm.getAction())).thenReturn("false"); + + final Answer answer = wrapper.execute(rulesVm, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testScaleVmCommand() { + final String uuid = "6172d8b7-ba10-4a70-93f9-ecaf41f51d53"; + + final VirtualMachineTO machineTO = Mockito.mock(VirtualMachineTO.class); + final Connection conn = Mockito.mock(Connection.class); + final XsHost xsHost = Mockito.mock(XsHost.class); + final Host host = Mockito.mock(Host.class); + + final ScaleVmCommand scaleVm = new ScaleVmCommand(machineTO); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + when(citrixResourceBase.getHost()).thenReturn(xsHost); + when(citrixResourceBase.getHost().getUuid()).thenReturn(uuid); + + try { + when(citrixResourceBase.isDmcEnabled(conn, host)).thenReturn(true); + } catch (final XenAPIException e) { + fail(e.getMessage()); + } catch (final XmlRpcException e) { + fail(e.getMessage()); + } + + final Answer answer = wrapper.execute(scaleVm, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testPvlanSetupCommandDhcpSuccess() { + final String label = "net"; + + final Connection conn = Mockito.mock(Connection.class); + final XsLocalNetwork network = Mockito.mock(XsLocalNetwork.class); + final Network network2 = Mockito.mock(Network.class); + + final PvlanSetupCommand lanSetup = PvlanSetupCommand.createDhcpSetup("add", URI.create("http://127.0.0.1"), "tag", "dhcp", "0:0:0:0:0:0", "127.0.0.1"); + + final String primaryPvlan = lanSetup.getPrimary(); + final String isolatedPvlan = lanSetup.getIsolated(); + final String op = lanSetup.getOp(); + final String dhcpName = lanSetup.getDhcpName(); + final String dhcpMac = lanSetup.getDhcpMac(); + final String dhcpIp = lanSetup.getDhcpIp(); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + try { + when(citrixResourceBase.getNativeNetworkForTraffic(conn, TrafficType.Guest, "tag")).thenReturn(network); + when(network.getNetwork()).thenReturn(network2); + when(network2.getNameLabel(conn)).thenReturn(label); + } catch (final XenAPIException e) { + fail(e.getMessage()); + } catch (final XmlRpcException e) { + fail(e.getMessage()); + } + + when(citrixResourceBase.callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-dhcp", "op", op, "nw-label", label, "primary-pvlan", primaryPvlan, "isolated-pvlan", + isolatedPvlan, "dhcp-name", dhcpName, "dhcp-ip", dhcpIp, "dhcp-mac", dhcpMac)).thenReturn("true"); + + final Answer answer = wrapper.execute(lanSetup, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertTrue(answer.getResult()); + } + + @Test + public void testPvlanSetupCommandDhcpFailure() { + final String label = "net"; + + final Connection conn = Mockito.mock(Connection.class); + final XsLocalNetwork network = Mockito.mock(XsLocalNetwork.class); + final Network network2 = Mockito.mock(Network.class); + + final PvlanSetupCommand lanSetup = PvlanSetupCommand.createDhcpSetup("add", URI.create("http://127.0.0.1"), "tag", "dhcp", "0:0:0:0:0:0", "127.0.0.1"); + + final String primaryPvlan = lanSetup.getPrimary(); + final String isolatedPvlan = lanSetup.getIsolated(); + final String op = lanSetup.getOp(); + final String dhcpName = lanSetup.getDhcpName(); + final String dhcpMac = lanSetup.getDhcpMac(); + final String dhcpIp = lanSetup.getDhcpIp(); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + try { + when(citrixResourceBase.getNativeNetworkForTraffic(conn, TrafficType.Guest, "tag")).thenReturn(network); + when(network.getNetwork()).thenReturn(network2); + when(network2.getNameLabel(conn)).thenReturn(label); + } catch (final XenAPIException e) { + fail(e.getMessage()); + } catch (final XmlRpcException e) { + fail(e.getMessage()); + } + + when(citrixResourceBase.callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-dhcp", "op", op, "nw-label", label, "primary-pvlan", primaryPvlan, "isolated-pvlan", + isolatedPvlan, "dhcp-name", dhcpName, "dhcp-ip", dhcpIp, "dhcp-mac", dhcpMac)).thenReturn("false"); + + final Answer answer = wrapper.execute(lanSetup, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testPvlanSetupCommandVmSuccess() { + final String label = "net"; + + final Connection conn = Mockito.mock(Connection.class); + final XsLocalNetwork network = Mockito.mock(XsLocalNetwork.class); + final Network network2 = Mockito.mock(Network.class); + + final PvlanSetupCommand lanSetup = PvlanSetupCommand.createVmSetup("add", URI.create("http://127.0.0.1"), "tag", "0:0:0:0:0:0"); + + final String primaryPvlan = lanSetup.getPrimary(); + final String isolatedPvlan = lanSetup.getIsolated(); + final String op = lanSetup.getOp(); + final String vmMac = lanSetup.getVmMac(); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + try { + when(citrixResourceBase.getNativeNetworkForTraffic(conn, TrafficType.Guest, "tag")).thenReturn(network); + when(network.getNetwork()).thenReturn(network2); + when(network2.getNameLabel(conn)).thenReturn(label); + } catch (final XenAPIException e) { + fail(e.getMessage()); + } catch (final XmlRpcException e) { + fail(e.getMessage()); + } + + when(citrixResourceBase.callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-vm", "op", op, "nw-label", label, "primary-pvlan", primaryPvlan, "isolated-pvlan", + isolatedPvlan, "vm-mac", vmMac)).thenReturn("true"); + + final Answer answer = wrapper.execute(lanSetup, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertTrue(answer.getResult()); + } + + @Test + public void testPvlanSetupCommandVmFailure() { + final String label = "net"; + + final Connection conn = Mockito.mock(Connection.class); + final XsLocalNetwork network = Mockito.mock(XsLocalNetwork.class); + final Network network2 = Mockito.mock(Network.class); + + final PvlanSetupCommand lanSetup = PvlanSetupCommand.createVmSetup("add", URI.create("http://127.0.0.1"), "tag", "0:0:0:0:0:0"); + + final String primaryPvlan = lanSetup.getPrimary(); + final String isolatedPvlan = lanSetup.getIsolated(); + final String op = lanSetup.getOp(); + final String vmMac = lanSetup.getVmMac(); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + try { + when(citrixResourceBase.getNativeNetworkForTraffic(conn, TrafficType.Guest, "tag")).thenReturn(network); + when(network.getNetwork()).thenReturn(network2); + when(network2.getNameLabel(conn)).thenReturn(label); + } catch (final XenAPIException e) { + fail(e.getMessage()); + } catch (final XmlRpcException e) { + fail(e.getMessage()); + } + + when(citrixResourceBase.callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-vm", "op", op, "nw-label", label, "primary-pvlan", primaryPvlan, "isolated-pvlan", + isolatedPvlan, "vm-mac", vmMac)).thenReturn("false"); + + final Answer answer = wrapper.execute(lanSetup, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testPerformanceMonitorCommandSuccess() { + final Connection conn = Mockito.mock(Connection.class); + + final PerformanceMonitorCommand performanceMonitor = new PerformanceMonitorCommand(new Hashtable(), 200); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + when(citrixResourceBase.getPerfMon(conn, performanceMonitor.getParams(), performanceMonitor.getWait())).thenReturn("performance"); + + final Answer answer = wrapper.execute(performanceMonitor, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertTrue(answer.getResult()); + } + + @Test + public void testPerformanceMonitorCommandFailure() { + final Connection conn = Mockito.mock(Connection.class); + + final PerformanceMonitorCommand performanceMonitor = new PerformanceMonitorCommand(new Hashtable(), 200); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getConnection()).thenReturn(conn); + when(citrixResourceBase.getPerfMon(conn, performanceMonitor.getParams(), performanceMonitor.getWait())).thenReturn(null); + + final Answer answer = wrapper.execute(performanceMonitor, citrixResourceBase); + + verify(citrixResourceBase, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testNetworkElementCommand() { + final VirtualRoutingResource routingResource = Mockito.mock(VirtualRoutingResource.class); + final IpAddressTO [] ips = new IpAddressTO[0]; + + final IpAssocVpcCommand ipAssociation = new IpAssocVpcCommand(ips); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(citrixResourceBase.getVirtualRoutingResource()).thenReturn(routingResource); + + final Answer answer = wrapper.execute(ipAssociation, citrixResourceBase); + + verify(routingResource, times(1)).executeRequest(ipAssociation); + + // Requires more testing, but the VirtualResourceRouting is quite big. + assertNull(answer); + } } class NotAValidCommand extends Command {